Cloak loading

This commit is contained in:
2026-03-20 23:06:01 +01:00
parent 2969a8340a
commit 9f2406abdb
2 changed files with 76 additions and 106 deletions
@@ -69,6 +69,8 @@ public class ServiceClient {
SaturnPlayer.set(new SaturnPlayer(uuid, username, response.cloak(), response.hat())); SaturnPlayer.set(new SaturnPlayer(uuid, username, response.cloak(), response.hat()));
Cloaks.loadCloak(response.cloak());
return true; return true;
} catch (Exception e) { } catch (Exception e) {
Providers.saturn.logError("Authentication failed", e); Providers.saturn.logError("Authentication failed", e);
@@ -10,10 +10,7 @@ import java.awt.image.BufferedImage;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.*; import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.saturnclient.cosmetics.utils.AnimatedCloakData; import org.saturnclient.cosmetics.utils.AnimatedCloakData;
import org.saturnclient.cosmetics.utils.GifDecoder; import org.saturnclient.cosmetics.utils.GifDecoder;
@@ -33,17 +30,8 @@ public class Cloaks {
private static final String CLOAKS_RESOURCE_PATH = "assets/saturnclient/textures/cloaks/"; private static final String CLOAKS_RESOURCE_PATH = "assets/saturnclient/textures/cloaks/";
public static final List<String> availableCloaks = new ArrayList<>(); public static final List<String> availableCloaks = new ArrayList<>();
public static IdentifierRef cloakCacheIdentifier = null; public static IdentifierRef cloakCacheIdentifier = null;
public static final Map<UUID, List<AnimatedCloakData>> animatedCloaks = new ConcurrentHashMap<>(); public static final Map<String, List<AnimatedCloakData>> animatedCloaks = new ConcurrentHashMap<>();
private static final Map<UUID, Long> lastFrameTime = new ConcurrentHashMap<>(); private static final Map<String, Long> lastFrameTime = new ConcurrentHashMap<>();
private static final ExecutorService CLOAK_LOADER_EXECUTOR = Executors.newFixedThreadPool(
Math.min(4, Runtime.getRuntime().availableProcessors()),
r -> {
Thread t = new Thread(r, "cloak-loader");
t.setDaemon(true);
t.setPriority(Thread.NORM_PRIORITY - 1);
return t;
});
private static final ConcurrentHashMap<String, List<AnimatedCloakData>> CLOAK_CACHE = new ConcurrentHashMap<>(); private static final ConcurrentHashMap<String, List<AnimatedCloakData>> CLOAK_CACHE = new ConcurrentHashMap<>();
@@ -80,7 +68,7 @@ public class Cloaks {
player.cloak = cloakName; player.cloak = cloakName;
} }
loadCloak(uuid); loadCloak(cloakName);
} }
/** /**
@@ -89,22 +77,12 @@ public class Cloaks {
* *
* @param cloakName Name of the cloak file to load * @param cloakName Name of the cloak file to load
*/ */
public static void loadCloak(UUID uuid) { public static void loadCloak(String cloakName) {
SaturnPlayer player = SaturnPlayer.get(uuid); if (cloakName != null && !cloakName.isEmpty()) {
if (Arrays.asList(ANIMATED_CLOAKS).contains(cloakName)) {
if (player != null && player.cloak != null) { Providers.saturn.getClient().executeOnThread(() -> loadAnimatedCloak(cloakName));
if (!player.cloak.isEmpty()) {
if (Arrays.asList(ANIMATED_CLOAKS).contains(player.cloak)) {
loadAnimatedCloakAsync(uuid, player.cloak)
.exceptionally(throwable -> {
Providers.saturn.logError("Failed to load animated cloak for player: " + player.cloak,
throwable);
return null;
});
} else { } else {
Providers.saturn.getClient().executeOnThread(() -> loadStaticCloak(player.cloak + ".png")); Providers.saturn.getClient().executeOnThread(() -> loadStaticCloak(cloakName + ".png"));
}
} }
} }
} }
@@ -137,15 +115,14 @@ public class Cloaks {
} }
} }
public static CompletableFuture<Void> loadAnimatedCloakAsync(UUID uuid, String cloakName) { public static void loadAnimatedCloak(String cloakName) {
return CompletableFuture.runAsync(() -> {
String fileName = cloakName + ".gif"; String fileName = cloakName + ".gif";
// Check cache first // Check cache first
List<AnimatedCloakData> cached = CLOAK_CACHE.get(fileName); List<AnimatedCloakData> cached = CLOAK_CACHE.get(fileName);
if (cached != null) { if (cached != null) {
animatedCloaks.put(uuid, cached); animatedCloaks.put(cloakName, cached);
lastFrameTime.put(uuid, System.currentTimeMillis()); lastFrameTime.put(cloakName, System.currentTimeMillis());
return; return;
} }
@@ -191,8 +168,8 @@ public class Cloaks {
if (!animatedFrames.isEmpty()) { if (!animatedFrames.isEmpty()) {
// Cache the result for future use // Cache the result for future use
CLOAK_CACHE.put(fileName, animatedFrames); CLOAK_CACHE.put(fileName, animatedFrames);
animatedCloaks.put(uuid, animatedFrames); animatedCloaks.put(cloakName, animatedFrames);
lastFrameTime.put(uuid, System.currentTimeMillis()); lastFrameTime.put(cloakName, System.currentTimeMillis());
Providers.saturn.logInfo("Loaded " + animatedFrames.size() + " frames for animated cloak: " Providers.saturn.logInfo("Loaded " + animatedFrames.size() + " frames for animated cloak: "
+ fileName + " (cached)"); + fileName + " (cached)");
@@ -205,26 +182,17 @@ public class Cloaks {
} catch (Exception e) { } catch (Exception e) {
Providers.saturn.logError("Unexpected error loading animated cloak: " + fileName, e); Providers.saturn.logError("Unexpected error loading animated cloak: " + fileName, e);
} }
}, CLOAK_LOADER_EXECUTOR);
} }
public static IdentifierRef getCurrentCloakTexture(UUID uuid) { public static IdentifierRef getCurrentCloakTexture(String cloakName) {
SaturnPlayer player = SaturnPlayer.get(uuid);
if (player == null || player.cloak.isEmpty()) {
return null;
}
String cloakName = player.cloak;
if (Arrays.asList(ANIMATED_CLOAKS).contains(cloakName)) { if (Arrays.asList(ANIMATED_CLOAKS).contains(cloakName)) {
List<AnimatedCloakData> frames = animatedCloaks.get(uuid); List<AnimatedCloakData> frames = animatedCloaks.get(cloakName);
if (frames == null || frames.isEmpty()) { if (frames == null || frames.isEmpty()) {
return null; return null;
} }
long currentTime = System.currentTimeMillis(); long currentTime = System.currentTimeMillis();
long lastTime = lastFrameTime.getOrDefault(uuid, currentTime); long lastTime = lastFrameTime.getOrDefault(cloakName, currentTime);
int currentFrame = 0; int currentFrame = 0;
long elapsedTime = currentTime - lastTime; long elapsedTime = currentTime - lastTime;
@@ -238,7 +206,7 @@ public class Cloaks {
} }
if (elapsedTime >= totalTime) { if (elapsedTime >= totalTime) {
lastFrameTime.put(uuid, currentTime); lastFrameTime.put(cloakName, currentTime);
currentFrame = 0; currentFrame = 0;
} }