diff --git a/src/main/java/org/saturnclient/saturnclient/auth/Auth.java b/src/main/java/org/saturnclient/saturnclient/auth/Auth.java deleted file mode 100644 index 3bcd7af..0000000 --- a/src/main/java/org/saturnclient/saturnclient/auth/Auth.java +++ /dev/null @@ -1,283 +0,0 @@ -package org.saturnclient.saturnclient.auth; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Collectors; - -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; -import net.minecraft.client.network.AbstractClientPlayerEntity; -import net.minecraft.util.Identifier; - -import org.saturnclient.saturnclient.cosmetics.Hats; -import org.saturnclient.saturnclient.cosmetics.cloaks.Cloaks; -import org.saturnclient.ui2.Utils; -import org.saturnclient.ui2.elements.Notification.NotificationKind; - -import dev.kosmx.playerAnim.api.layered.AnimationStack; -import dev.kosmx.playerAnim.minecraftApi.PlayerAnimationAccess; -import dev.kosmx.playerAnim.minecraftApi.PlayerAnimationRegistry; - -import org.saturnclient.saturnclient.SaturnClient; - -public class Auth { - public static Map players = new HashMap<>(); - public static Map playerNames = new HashMap<>(); - public static String uuid; - private static Thread listenerThread; - private static Thread pingThread; - private static volatile boolean running = false; - - public static boolean authenticate() { - // Register shutdown hook ONCE - ClientLifecycleEvents.CLIENT_STOPPING.register(_o -> close()); - - try { - if (SaturnClient.client.getSession() == null) { - SaturnClient.LOGGER.error("No active Minecraft session found"); - return false; - } - - String accessToken = SaturnClient.client.getSession().getAccessToken(); - SaturnClient.LOGGER.info("Authenticating"); - - Network.init(); - - Network.write(accessToken); - - String response = Network.read(); - - SaturnParser parser = new SaturnParser(response); - - uuid = parser.getString("uuid"); - String cloak = parser.getString("cloak"); - String hat = parser.getString("hat"); - - for (String availableCloak : parser.getArray("cloaks")) { - Cloaks.availableCloaks.add(availableCloak); - } - - for (String availableHat : parser.getArray("hats")) { - Hats.availableHats.add(availableHat); - } - - players.put(uuid, new SaturnPlayer(cloak, hat)); - - Cloaks.loadCloak(uuid); - - playerNames.put(SaturnClient.client.getSession().getUsername(), uuid); - - afterAuth(); - - startListenerThread(); - startPingThread(); - - return true; - } catch (Exception e) { - SaturnClient.LOGGER.error("Authentication failed", e); - return false; - } - } - - private static void startListenerThread() { - running = true; - listenerThread = new Thread(() -> { - try { - while (running) { - String message = Network.read(); - if (message == null) { - SaturnClient.LOGGER.error("Connection closed"); - running = false; - break; - } - - SaturnClient.LOGGER.info("Received: " + message); - - SaturnParser parser = new SaturnParser(message); - - switch (parser.method) { - case "player": - String uuid = parser.getString("uuid"); - if (parser.getBool("saturn")) { - String cloak = parser.getString("cloak"); - String hat = parser.getString("hat"); - players.put(uuid, new SaturnPlayer(cloak, hat)); - Cloaks.loadCloak(uuid); - } else { - playerNames.entrySet().removeIf(entry -> entry.getValue().equals(uuid)); - } - break; - - case "successful_transaction": - String cloak = parser.getStringOrNull("cloak"); - String hat = parser.getStringOrNull("hat"); - if (cloak != null) { - Cloaks.availableCloaks.add(cloak); - - } - if (hat != null) { - Hats.availableHats.add(hat); - } - - case "update_cloak": - String targetUuid = parser.getStringOrNull("uuid"); - String targetCloak = parser.getStringOrNull("cloak"); - if (targetUuid != null && targetCloak != null) { - SaturnPlayer player = players.get(targetUuid); - if (player != null) { - player.cloak = targetCloak; - } - } - break; - - case "update_hat": - targetUuid = parser.getStringOrNull("uuid"); - String targetHat = parser.getStringOrNull("hat"); - if (targetUuid != null && targetHat != null) { - SaturnPlayer player = players.get(targetUuid); - if (player != null) { - player.hat = targetHat; - } - } - break; - - case "emote": - targetUuid = parser.getStringOrNull("uuid"); - String emote = parser.getStringOrNull("name"); - - for (AbstractClientPlayerEntity player : SaturnClient.client.world.getPlayers()) { - if (player.getUuidAsString().replace("-", "").equals(targetUuid)) { - AnimationStack animationStack = PlayerAnimationAccess.getPlayerAnimLayer(player); - if (emote != null && !emote.isEmpty()) { - if (animationStack.isActive() && animationStack.getPriority() == 1000) { - animationStack.removeLayer(1000); - } - animationStack.addAnimLayer(1000, - PlayerAnimationRegistry - .getAnimation(Identifier.of("saturnclient", emote)) - .playAnimation()); - } else { - animationStack.removeLayer(1000); - } - } - } - break; - - default: - if (parser.error != null) { - String[] a = parser.error.replace("!", "").split(": "); - Utils.notify(NotificationKind.Error, a[0], a[1]); - } - break; - } - } - } catch (Exception e) { - SaturnClient.LOGGER.error("Error reading from server", e); - } finally { - close(); - } - }); - - listenerThread.setDaemon(true); - listenerThread.start(); - } - - private static void startPingThread() { - pingThread = new Thread(() -> { - try { - while (running && !Thread.currentThread().isInterrupted()) { - try { - Thread.sleep(25000); // 25 seconds - if (running) { - Network.write("ping"); - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); // Restore interrupt status - break; // Exit the loop on interruption - } - } - } catch (Exception e) { - if (!(e instanceof InterruptedException)) { - SaturnClient.LOGGER.error("Error in ping thread", e); - } - } - }); - - pingThread.setDaemon(true); - pingThread.start(); - } - - public static void close() { - running = false; - if (pingThread != null) { - pingThread.interrupt(); - } - if (listenerThread != null) { - listenerThread.interrupt(); - } - try { - close(); - SaturnClient.LOGGER.info("SaturnApi connection closed."); - } catch (Exception e) { - SaturnClient.LOGGER.error("Failed to close resources", e); - } - } - - public static void afterAuth() { - PlayerTracker.initialize(); - } - - public static void setCloak(String cloakName) { - try { - Network.write("set_cloak@cloak=" + cloakName + "@notify=" + stringifyPlayers()); - } catch (Exception e) { - SaturnClient.LOGGER.error("Request failed", e); - } - } - - public static void setHat(String hatName) { - try { - Network.write("set_hat@hat=" + hatName + "@notify=" + stringifyPlayers()); - } catch (Exception e) { - SaturnClient.LOGGER.error("Request failed", e); - } - } - - public static void emote(String name) { - try { - Network.write("emote@name=" + name + "@notify=" + stringifyPlayers()); - } catch (Exception e) { - SaturnClient.LOGGER.error("Request failed", e); - } - } - - public static String stringifyPlayers() { - return players.keySet().stream() - .filter(key -> key != uuid) - .collect(Collectors.joining("$")); - } - - public static void player(String name, String uuid) { - try { - playerNames.put(name, uuid.replaceAll("-", "")); - Network.write("player@uuid=" + uuid.replaceAll("-", "")); - } catch (Exception e) { - SaturnClient.LOGGER.error("Request failed", e); - } - } - - public static void buyCloak(String name) { - try { - Network.write("buy_cloak@cloak=" + name); - } catch (Exception e) { - SaturnClient.LOGGER.error("Request failed", e); - } - } - - public static void buyHat(String name) { - try { - Network.write("buy_hat@hat=" + name); - } catch (Exception e) { - SaturnClient.LOGGER.error("Request failed", e); - } - } -} diff --git a/src/main/java/org/saturnclient/saturnclient/auth/Network.java b/src/main/java/org/saturnclient/saturnclient/auth/Network.java deleted file mode 100644 index d3f2346..0000000 --- a/src/main/java/org/saturnclient/saturnclient/auth/Network.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.saturnclient.saturnclient.auth; - -import java.io.*; -import java.net.*; -import java.security.*; -import java.util.Base64; -import javax.crypto.*; -import javax.crypto.spec.*; -import java.security.interfaces.*; -import java.security.spec.X509EncodedKeySpec; - -public class Network { - // static Session session; - static Socket socket; - static PrintWriter out; - static BufferedReader in; - static byte[] key = new byte[32]; - - private static final int CONNECTION_TIMEOUT = 5000; - private static final int READ_TIMEOUT = 5000; - - public static class AES { - public static byte[] encryptAES256(String message, byte[] key) throws Exception { - Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); - SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); - cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); - byte[] encryptedMessage = cipher.doFinal(message.getBytes()); - return encryptedMessage; - } - - public static String decryptAES256(byte[] encryptedMessage, byte[] key) throws Exception { - Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); - SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); - cipher.init(Cipher.DECRYPT_MODE, secretKeySpec); - byte[] decryptedMessage = cipher.doFinal(encryptedMessage); - return new String(decryptedMessage); - } - } - - public static void init() throws Exception { - // Generate AES key - new SecureRandom().nextBytes(key); - - socket = new Socket(); - socket.connect(new InetSocketAddress("77.247.92.168", 8080), CONNECTION_TIMEOUT); - - socket.setSoTimeout(READ_TIMEOUT); - - // out = new DataOutputStream(socket.getOutputStream()); - out = new PrintWriter(socket.getOutputStream(), true); - in = new BufferedReader(new InputStreamReader(socket.getInputStream())); - - StringBuilder publicKeyBuilder = new StringBuilder(); - String line; - while (!(line = in.readLine()).contains("-----END PUBLIC KEY-----")) { - publicKeyBuilder.append(line).append("\n"); - } - publicKeyBuilder.append(line); - - String publicKeyPem = publicKeyBuilder.toString(); - - String publicKeyBase64 = publicKeyPem.replace("-----BEGIN PUBLIC KEY-----", "") - .replace("-----END PUBLIC KEY-----", "").replace("\n", "").replace("\r", ""); - byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyBase64); - - X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes); - KeyFactory keyFactory = KeyFactory.getInstance("RSA"); - RSAPublicKey publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec); - - Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); - rsaCipher.init(Cipher.ENCRYPT_MODE, publicKey); - byte[] encryptedKey = rsaCipher.doFinal(key); - - out.println(Base64.getEncoder().encodeToString(encryptedKey)); - } - - public static void write(String message) { - try { - out.println(Base64.getEncoder().encodeToString(AES.encryptAES256(message, key))); - } catch (Exception e) { - throw new RuntimeException("Failed to write to server: " + e.getMessage()); - } - } - - public static String read() { - try { - String msg = in.readLine(); - if (msg != null) { - return AES.decryptAES256(Base64.getDecoder().decode(msg), key); - } else { - return ""; - } - } catch (Exception e) { - return ""; - } - } - - public static void close() { - try { - socket.close(); - out.close(); - in.close(); - } catch (Exception e) { - } - } -} \ No newline at end of file diff --git a/src/main/java/org/saturnclient/saturnclient/auth/SaturnParser.java b/src/main/java/org/saturnclient/saturnclient/auth/SaturnParser.java deleted file mode 100644 index 60d1c31..0000000 --- a/src/main/java/org/saturnclient/saturnclient/auth/SaturnParser.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.saturnclient.saturnclient.auth; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -public class SaturnParser { - public String method = ""; - public String error; - private Map params = new HashMap<>(); - - public SaturnParser(String input) throws IOException { - String[] parts = input.split("@"); - - if (parts.length == 0) { - throw new IOException("Invalid input string"); - } - - if (parts[0].startsWith("!")) { - error = input; - } - - method = parts[0]; - - for (int i = 1; i < parts.length; i++) { - String[] keyValue = parts[i].split("="); - if (keyValue.length == 2) { - params.put(keyValue[0].trim(), keyValue[1].trim()); - } else if (keyValue.length == 1) { - params.put(keyValue[0].trim(), ""); - } else { - throw new IOException("Invalid parameter format: " + parts[i]); - } - } - } - - public String getString(String i) throws IOException { - String val = params.get(i); - if (val != null) { - return val; - } else { - throw new IOException("Parameter not found " + i); - } - } - - public String getStringOrNull(String i) throws IOException { - String val = params.get(i); - return val; - } - - public boolean getBool(String i) throws IOException { - String val = params.get(i); - if (val != null) { - return val.equals("true"); - } else { - throw new IOException("Parameter not found " + i); - } - } - - public String[] getArray(String i) throws IOException { - String val = params.get(i); - if (val != null) { - if (val.isEmpty()) { - return new String[] {}; - } - return val.split("\\$"); - } else { - throw new IOException("Parameter not found " + i); - } - } -} diff --git a/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java b/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java new file mode 100644 index 0000000..0809ad3 --- /dev/null +++ b/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java @@ -0,0 +1,68 @@ +package org.saturnclient.saturnclient.client; + +import java.net.http.WebSocket; +import java.util.UUID; + +import org.saturnclient.saturnclient.SaturnClient; +import org.saturnclient.saturnclient.cosmetics.Hats; +import org.saturnclient.saturnclient.cosmetics.cloaks.Cloaks; + +import dev.selimaj.session.Session; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; + +public class ServiceClient { + private static Session session; + public static UUID uuid; + + 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(); + + SaturnClient.LOGGER.info("Authenticating with UUID: " + accessToken); + + // String cloak = parser.getString("cloak"); + // String hat = parser.getString("hat"); + + // for (String availableCloak : parser.getArray("cloaks")) { + // Cloaks.availableCloaks.add(availableCloak); + // } + + // for (String availableHat : parser.getArray("hats")) { + // Hats.availableHats.add(availableHat); + // } + + // players.put(uuid, new SaturnPlayer(cloak, hat)); + + // Cloaks.loadCloak(uuid); + + // playerNames.put(SaturnClient.client.getSession().getUsername(), uuid); + + // afterAuth(); + + // startListenerThread(); + // startPingThread(); + + return true; + } catch (Exception e) { + SaturnClient.LOGGER.error("Authentication failed", e); + return false; + } + } +} diff --git a/src/main/java/org/saturnclient/saturnclient/client/ServiceMethods.java b/src/main/java/org/saturnclient/saturnclient/client/ServiceMethods.java new file mode 100644 index 0000000..c9065c8 --- /dev/null +++ b/src/main/java/org/saturnclient/saturnclient/client/ServiceMethods.java @@ -0,0 +1,5 @@ +package org.saturnclient.saturnclient.client; + +public class ServiceMethods { + +} diff --git a/src/main/java/org/saturnclient/saturnclient/auth/PlayerTracker.java b/src/main/java/org/saturnclient/saturnclient/client/player/PlayerTracker.java similarity index 89% rename from src/main/java/org/saturnclient/saturnclient/auth/PlayerTracker.java rename to src/main/java/org/saturnclient/saturnclient/client/player/PlayerTracker.java index a6aff97..308fb3a 100644 --- a/src/main/java/org/saturnclient/saturnclient/auth/PlayerTracker.java +++ b/src/main/java/org/saturnclient/saturnclient/client/player/PlayerTracker.java @@ -1,4 +1,4 @@ -package org.saturnclient.saturnclient.auth; +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; @@ -45,8 +45,8 @@ public class PlayerTracker { private static void onPlayerJoin(MinecraftClient client, PlayerListEntry player) { GameProfile profile = player.getProfile(); - String uuid = profile.getId().toString(); - if (uuid != Auth.uuid) - Auth.player(profile.getName(), uuid); + UUID uuid = profile.getId(); + // if (uuid != ServiceClient.uuid) + // ServiceClient.player(profile.getName(), uuid); } } diff --git a/src/main/java/org/saturnclient/saturnclient/auth/SaturnPlayer.java b/src/main/java/org/saturnclient/saturnclient/client/player/SaturnPlayer.java similarity index 79% rename from src/main/java/org/saturnclient/saturnclient/auth/SaturnPlayer.java rename to src/main/java/org/saturnclient/saturnclient/client/player/SaturnPlayer.java index 8ffe19e..5bfd6a1 100644 --- a/src/main/java/org/saturnclient/saturnclient/auth/SaturnPlayer.java +++ b/src/main/java/org/saturnclient/saturnclient/client/player/SaturnPlayer.java @@ -1,4 +1,4 @@ -package org.saturnclient.saturnclient.auth; +package org.saturnclient.saturnclient.client.player; public class SaturnPlayer { public String cloak = ""; diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/HatFeatureRenderer.java b/src/main/java/org/saturnclient/saturnclient/cosmetics/HatFeatureRenderer.java index 422e2cc..de91606 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/HatFeatureRenderer.java +++ b/src/main/java/org/saturnclient/saturnclient/cosmetics/HatFeatureRenderer.java @@ -1,8 +1,7 @@ package org.saturnclient.saturnclient.cosmetics; -import org.saturnclient.saturnclient.auth.SaturnPlayer; import org.saturnclient.saturnclient.auth.Auth; - +import org.saturnclient.saturnclient.client.player.SaturnPlayer; import org.saturnclient.saturnclient.SaturnClient; import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.VertexConsumerProvider; diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/Hats.java b/src/main/java/org/saturnclient/saturnclient/cosmetics/Hats.java index ea30e6f..24de9d2 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/Hats.java +++ b/src/main/java/org/saturnclient/saturnclient/cosmetics/Hats.java @@ -2,8 +2,9 @@ package org.saturnclient.saturnclient.cosmetics; import java.util.ArrayList; import java.util.List; -import org.saturnclient.saturnclient.auth.SaturnPlayer; + import org.saturnclient.saturnclient.auth.Auth; +import org.saturnclient.saturnclient.client.player.SaturnPlayer; public class Hats { public static final String[] ALL_HATS = { "horns_black", "horns_white", "halo", "halo_black" }; diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/Cloaks.java b/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/Cloaks.java index 556a7c4..4a31396 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/Cloaks.java +++ b/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/Cloaks.java @@ -2,9 +2,9 @@ package org.saturnclient.saturnclient.cosmetics.cloaks; import net.minecraft.util.Identifier; import org.saturnclient.saturnclient.auth.Auth; +import org.saturnclient.saturnclient.client.player.SaturnPlayer; import org.saturnclient.saturnclient.cosmetics.cloaks.utils.AnimatedCloakData; import org.saturnclient.saturnclient.cosmetics.cloaks.utils.IdentifierUtils; -import org.saturnclient.saturnclient.auth.SaturnPlayer; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; diff --git a/src/main/java/org/saturnclient/ui2/screens/cosmetics/CloakMenu.java b/src/main/java/org/saturnclient/ui2/screens/cosmetics/CloakMenu.java index aae0b06..5261827 100644 --- a/src/main/java/org/saturnclient/ui2/screens/cosmetics/CloakMenu.java +++ b/src/main/java/org/saturnclient/ui2/screens/cosmetics/CloakMenu.java @@ -2,7 +2,7 @@ package org.saturnclient.ui2.screens.cosmetics; import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.auth.Auth; -import org.saturnclient.saturnclient.auth.SaturnPlayer; +import org.saturnclient.saturnclient.client.player.SaturnPlayer; import org.saturnclient.saturnclient.cosmetics.cloaks.Cloaks; import org.saturnclient.ui2.resources.Textures; import org.saturnclient.ui2.SaturnScreen; diff --git a/src/main/java/org/saturnclient/ui2/screens/cosmetics/HatMenu.java b/src/main/java/org/saturnclient/ui2/screens/cosmetics/HatMenu.java index d81a9cb..978ec90 100644 --- a/src/main/java/org/saturnclient/ui2/screens/cosmetics/HatMenu.java +++ b/src/main/java/org/saturnclient/ui2/screens/cosmetics/HatMenu.java @@ -2,7 +2,7 @@ package org.saturnclient.ui2.screens.cosmetics; import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.auth.Auth; -import org.saturnclient.saturnclient.auth.SaturnPlayer; +import org.saturnclient.saturnclient.client.player.SaturnPlayer; import org.saturnclient.saturnclient.cosmetics.Hats; import org.saturnclient.ui2.resources.Textures; import org.saturnclient.ui2.SaturnScreen; diff --git a/src/main/java/org/saturnclient/ui2/screens/store/CloakStore.java b/src/main/java/org/saturnclient/ui2/screens/store/CloakStore.java index e400320..848e598 100644 --- a/src/main/java/org/saturnclient/ui2/screens/store/CloakStore.java +++ b/src/main/java/org/saturnclient/ui2/screens/store/CloakStore.java @@ -2,7 +2,7 @@ package org.saturnclient.ui2.screens.store; import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.auth.Auth; -import org.saturnclient.saturnclient.auth.SaturnPlayer; +import org.saturnclient.saturnclient.client.player.SaturnPlayer; import org.saturnclient.saturnclient.cosmetics.cloaks.Cloaks; import org.saturnclient.ui2.SaturnScreen; import org.saturnclient.ui2.Utils; diff --git a/src/main/java/org/saturnclient/ui2/screens/store/HatStore.java b/src/main/java/org/saturnclient/ui2/screens/store/HatStore.java index 579ffa5..bb06249 100644 --- a/src/main/java/org/saturnclient/ui2/screens/store/HatStore.java +++ b/src/main/java/org/saturnclient/ui2/screens/store/HatStore.java @@ -2,7 +2,7 @@ package org.saturnclient.ui2.screens.store; import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.auth.Auth; -import org.saturnclient.saturnclient.auth.SaturnPlayer; +import org.saturnclient.saturnclient.client.player.SaturnPlayer; import org.saturnclient.saturnclient.cosmetics.Hats; import org.saturnclient.ui2.SaturnScreen; import org.saturnclient.ui2.Utils;