few updates

This commit is contained in:
2025-03-17 16:05:29 +01:00
parent 6e7acb2716
commit 8e53ed7292
11 changed files with 186 additions and 125 deletions
@@ -5,7 +5,7 @@ import net.minecraft.util.math.ColorHelper;
import org.saturnclient.saturnclient.cloaks.Cloaks;
import org.saturnclient.saturnclient.event.KeyInputHandler;
import org.saturnclient.saturnclient.auth.SaturnApi;
import org.saturnclient.saturnclient.auth.SaturnSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -23,7 +23,7 @@ public class SaturnClient implements ModInitializer {
LOGGER.info("Initializing " + MOD_ID);
KeyInputHandler.register();
if (SaturnApi.authenticate()) {
if (SaturnSocket.authenticate()) {
Cloaks.initialize();
LOGGER.info(MOD_ID + " initialization complete");
} else {
@@ -1,97 +0,0 @@
package org.saturnclient.saturnclient.auth;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.minecraft.client.MinecraftClient;
import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.saturnclient.cloaks.Cloaks;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
public class SaturnApi {
private static final String server = "127.0.0.1";
private static final int port = 8080;
public static Map<String, SaturnPlayer> players = new HashMap<>();
public static Map<String, String> playerNames = new HashMap<>();
private static Socket socket;
private static BufferedReader reader;
private static PrintWriter writer;
public static boolean authenticate() {
// Register shutdown hook ONCE
ClientLifecycleEvents.CLIENT_STOPPING.register(c -> close());
try {
MinecraftClient client = MinecraftClient.getInstance();
if (client.getSession() == null) {
SaturnClient.LOGGER.error("No active Minecraft session found");
return false;
}
String accessToken = client.getSession().getAccessToken();
SaturnClient.LOGGER.info("Authenticating");
// Use try-with-resources to ensure proper cleanup
try (Socket tempSocket = new Socket(server, port);
BufferedReader tempReader = new BufferedReader(new InputStreamReader(tempSocket.getInputStream()));
PrintWriter tempWriter = new PrintWriter(tempSocket.getOutputStream(), true)) {
// Assign to class fields
socket = tempSocket;
reader = tempReader;
writer = tempWriter;
writer.println(accessToken);
String response = reader.readLine();
SaturnParser parser = new SaturnParser(response);
String uuid = parser.getString("uuid");
String cloak = parser.getString("cloak");
if (cloak != null) {
SaturnClient.LOGGER.info("Setting cloak to " + cloak + " for " + uuid);
MinecraftClient.getInstance().execute(() -> Cloaks.setCloak(uuid, cloak));
}
return true;
}
} catch (IOException e) {
SaturnClient.LOGGER.error("Authentication failed", e);
return false;
}
}
public static void close() {
try {
if (writer != null) {
writer.close();
}
if (reader != null) {
reader.close();
}
if (socket != null) {
socket.close();
}
SaturnClient.LOGGER.info("SaturnApi connection closed.");
} catch (IOException e) {
SaturnClient.LOGGER.error("Failed to close resources", e);
}
}
public static void setCloak(String cloakName) {
try {
writer.println("set_cloak@cloak=" + cloakName);
String response = reader.readLine();
new SaturnParser(response);
} catch (IOException e) {
SaturnClient.LOGGER.error("Request failed", e);
}
}
}
@@ -22,6 +22,8 @@ public class SaturnParser {
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]);
}
@@ -36,4 +38,16 @@ public class SaturnParser {
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);
}
}
}
@@ -2,4 +2,8 @@ package org.saturnclient.saturnclient.auth;
public class SaturnPlayer {
public String cloak = "";
public SaturnPlayer(String cloak) {
this.cloak = cloak;
}
}
@@ -0,0 +1,134 @@
package org.saturnclient.saturnclient.auth;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.minecraft.client.MinecraftClient;
import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.saturnclient.cloaks.Cloaks;
import java.io.*;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
public class SaturnSocket {
private static final String server = "127.0.0.1";
private static final int port = 8080;
public static Map<String, SaturnPlayer> players = new HashMap<>();
public static Map<String, String> playerNames = new HashMap<>();
public static String uuid;
private static Socket socket;
private static BufferedReader reader;
private static PrintWriter writer;
private static Thread listenerThread;
private static volatile boolean running = false;
@SuppressWarnings("resource")
public static boolean authenticate() {
// Register shutdown hook ONCE
ClientLifecycleEvents.CLIENT_STOPPING.register(c -> close());
try {
MinecraftClient client = MinecraftClient.getInstance();
if (client.getSession() == null) {
SaturnClient.LOGGER.error("No active Minecraft session found");
return false;
}
String accessToken = client.getSession().getAccessToken();
SaturnClient.LOGGER.info("Authenticating");
// Establish a persistent connection
socket = new Socket(server, port);
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer = new PrintWriter(socket.getOutputStream(), true);
// Send authentication request
writer.println(accessToken);
String response = reader.readLine();
SaturnClient.LOGGER.info(response);
SaturnParser parser = new SaturnParser(response);
uuid = parser.getString("uuid");
String cloak = parser.getString("cloak");
for (String availableCloak : parser.getArray("cloaks")) {
SaturnClient.LOGGER.info("Available cloak: " + availableCloak);
Cloaks.availableCloaks.add(availableCloak);
}
players.put(uuid, new SaturnPlayer(cloak));
if (cloak != null) {
SaturnClient.LOGGER.info("Setting cloak to " + cloak + " for " + uuid);
MinecraftClient.getInstance().execute(() -> Cloaks.setCloak(uuid, cloak));
}
playerNames.put(client.getSession().getUsername(), uuid);
// Start listening for server messages
startListenerThread();
return true;
} catch (IOException e) {
SaturnClient.LOGGER.error("Authentication failed", e);
return false;
}
}
private static void startListenerThread() {
running = true;
listenerThread = new Thread(() -> {
try {
while (running) {
String message = reader.readLine();
if (message == null) {
running = false;
break;
}
SaturnClient.LOGGER.info("Received: " + message);
// TODO: make a server response/request handler
}
} catch (IOException e) {
SaturnClient.LOGGER.error("Error reading from server", e);
} finally {
close();
}
});
listenerThread.setDaemon(true);
listenerThread.start();
}
public static void close() {
running = false;
try {
if (writer != null) {
writer.close();
}
if (reader != null) {
reader.close();
}
if (socket != null) {
socket.close();
}
SaturnClient.LOGGER.info("SaturnApi connection closed.");
} catch (IOException e) {
SaturnClient.LOGGER.error("Failed to close resources", e);
}
}
public static void setCloak(String cloakName) {
try {
writer.println("set_cloak@cloak=" + cloakName);
} catch (Exception e) {
SaturnClient.LOGGER.error("Request failed", e);
}
}
}
@@ -2,7 +2,7 @@ package org.saturnclient.saturnclient.cloaks;
import net.minecraft.util.Identifier;
import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.saturnclient.auth.SaturnApi;
import org.saturnclient.saturnclient.auth.SaturnSocket;
import org.saturnclient.saturnclient.auth.SaturnPlayer;
import org.saturnclient.saturnclient.cloaks.utils.AnimatedCloakData;
import org.saturnclient.saturnclient.cloaks.utils.IdentifierUtils;
@@ -41,13 +41,20 @@ public class Cloaks {
* @param cloakName Name of the cloak file to load
*/
public static void setCloak(String uuid, String cloakName) {
SaturnApi.setCloak(cloakName);
SaturnSocket.setCloak(cloakName);
setCloakSilent(uuid, cloakName);
}
SaturnPlayer player = SaturnApi.players.get(uuid);
/**
* Handles loading and caching of a new cloak texture, without connecting to the
* server.
*
* @param cloakName Name of the cloak file to load
*/
public static void setCloakSilent(String uuid, String cloakName) {
SaturnPlayer player = SaturnSocket.players.get(uuid);
if (player == null) {
SaturnPlayer newPlayer = new SaturnPlayer();
newPlayer.cloak = cloakName;
SaturnApi.players.put(uuid, newPlayer);
SaturnSocket.players.put(uuid, new SaturnPlayer(cloakName));
} else {
player.cloak = cloakName;
}
@@ -59,7 +66,6 @@ public class Cloaks {
loadStaticCloak(cloakName + ".png");
}
}
}
/**
@@ -128,11 +134,11 @@ public class Cloaks {
}
public static Identifier getCurrentCloakTexture(String uuid) {
if (!SaturnApi.players.containsKey(uuid)) {
if (!SaturnSocket.players.containsKey(uuid)) {
return null;
}
String cloakName = SaturnApi.players.get(uuid).cloak;
String cloakName = SaturnSocket.players.get(uuid).cloak;
if (cloakName.isEmpty()) {
return null;
@@ -1,6 +1,6 @@
package org.saturnclient.saturnclient.menus;
import org.saturnclient.saturnclient.auth.SaturnApi;
import org.saturnclient.saturnclient.auth.SaturnSocket;
import org.saturnclient.saturnclient.cloaks.Cloaks;
import org.saturnclient.ui.SaturnUi;
import org.saturnclient.ui.Textures;
@@ -55,7 +55,7 @@ public class CloaksMenu extends SaturnUi {
.setHeight(cloakHeight));
draw(new SaturnClickableSprite(Textures.BUTTON_BORDER, () -> {
SaturnApi.setCloak(cloak);
Cloaks.setCloak(SaturnSocket.uuid, cloak);
})
.setColor(10526880)
.setX(modX - 3)
@@ -26,7 +26,7 @@ public class MainMenu extends SaturnUi {
}).setX((width - buttonWidth) / 2).setY((height - buttonHeight) /
2).setWidth(buttonWidth)
.setHeight(buttonHeight)
.setAnimations(new FadeIn(3)));
.setAnimations(new FadeIn(1)));
draw(
new SaturnImageButton(Textures.EMOTE, 14, 14,
@@ -37,7 +37,7 @@ public class MainMenu extends SaturnUi {
.setY((height - buttonHeight) / 2)
.setWidth(buttonHeight)
.setHeight(buttonHeight)
.setAnimations(new FadeIn(3)));
.setAnimations(new FadeIn(1)));
draw(
new SaturnImageButton(Textures.COSMETICS, 14, 14,
@@ -48,7 +48,7 @@ public class MainMenu extends SaturnUi {
.setY((height - buttonHeight) / 2)
.setWidth(buttonHeight)
.setHeight(buttonHeight)
.setAnimations(new FadeIn(3)));
.setAnimations(new FadeIn(1)));
int logoSize = 49;
@@ -58,7 +58,7 @@ public class MainMenu extends SaturnUi {
.setY((height - 8) / 2 - 23)
.setWidth(logoSize)
.setHeight(8)
.setAnimations(new FadeIn(3)));
.setAnimations(new FadeIn(1)));
draw(
new SaturnImage(Textures.LOGO)
@@ -66,6 +66,6 @@ public class MainMenu extends SaturnUi {
.setY(height / 2 - logoSize - 24)
.setWidth(logoSize)
.setHeight(logoSize)
.setAnimations(new Slide(2, 14)));
.setAnimations(new Slide(1, 14)));
}
}
@@ -13,7 +13,7 @@ import net.minecraft.text.Text;
import net.minecraft.util.math.Vec3d;
import net.minecraft.client.render.LightmapTextureManager;
import org.saturnclient.saturnclient.auth.SaturnApi;
import org.saturnclient.saturnclient.auth.SaturnSocket;
import org.joml.Matrix4f;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
@@ -60,7 +60,7 @@ public abstract class NameTagMixin<S extends EntityRenderState> {
private boolean isSaturn(S state) {
if (state instanceof PlayerEntityRenderState) {
String name = ((PlayerEntityRenderState) state).name;
return SaturnApi.playerNames.containsKey(name);
return SaturnSocket.playerNames.containsKey(name);
}
return false;
}
@@ -1,6 +1,6 @@
package org.saturnclient.saturnclient.mixin;
import org.saturnclient.saturnclient.auth.SaturnApi;
import org.saturnclient.saturnclient.auth.SaturnSocket;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
@@ -22,6 +22,6 @@ public abstract class TabListMixin {
@Nullable
public Text getDisplayName() {
String name = displayName.getString();
return Text.literal(SaturnApi.playerNames.containsKey(name) ? "" + name : name);
return Text.literal(SaturnSocket.playerNames.containsKey(name) ? "" + name : name);
}
}
@@ -12,26 +12,26 @@ import net.minecraft.util.math.ColorHelper;
import net.minecraft.util.math.MathHelper;
public class SaturnClickableImage extends SaturnWidget {
public Identifier sprite;
public Identifier texture;
public boolean selected = false;
public Consumer<SaturnClickableImage> onPress;
public int color = ColorHelper.getWhite(1.0f);
public int hoverColor = SaturnClient.COLOR;
public SaturnClickableImage(Identifier sprite, Consumer<SaturnClickableImage> onPress) {
this.sprite = sprite;
public SaturnClickableImage(Identifier texture, Consumer<SaturnClickableImage> onPress) {
this.texture = texture;
this.onPress = onPress;
}
public SaturnClickableImage(Identifier sprite, Runnable onPress) {
this(sprite, (m) -> {
public SaturnClickableImage(Identifier texture, Runnable onPress) {
this(texture, (m) -> {
onPress.run();
});
}
@Override
public void render(DrawContext context, boolean hovering, int mouseX, int mouseY) {
context.drawTexture(RenderLayer::getGuiTextured, sprite, x, y, 0, 0, width, height, width,
context.drawTexture(RenderLayer::getGuiTextured, texture, x, y, 0, 0, width, height, width,
height, (hovering || selected ? hoverColor : color) | MathHelper.ceil(this.alpha * 255.0F) << 24);
}