From 803986214268c4c80cb5cc838584556ff5be12b0 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 8 Mar 2026 11:29:45 +0100 Subject: [PATCH] Moving cloaks to common --- common | 2 +- .../cosmetics/cloak/CloakFeatureRenderer.java | 2 +- .../saturnclient/cosmetics/cloak/Cloaks.java | 21 +++-- .../cloak/utils/AnimatedCloakData.java | 36 -------- .../cloak/utils/IdentifierUtils.java | 84 +++++++------------ .../cosmetics/cloak/utils/RandomUtils.java | 48 ----------- .../impl/provider/SaturnProviderImpl.java | 2 +- 7 files changed, 41 insertions(+), 154 deletions(-) delete mode 100644 versions/1.21.4/src/main/java/org/saturnclient/cosmetics/cloak/utils/AnimatedCloakData.java delete mode 100644 versions/1.21.4/src/main/java/org/saturnclient/cosmetics/cloak/utils/RandomUtils.java diff --git a/common b/common index a54aa9e..5b34d3e 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit a54aa9eaba4239b4a47acf9aec0ccbfb4c0aac2f +Subproject commit 5b34d3eb374d0260402c9ed17012192ca7d26bf4 diff --git a/versions/1.21.4/src/main/java/org/saturnclient/cosmetics/cloak/CloakFeatureRenderer.java b/versions/1.21.4/src/main/java/org/saturnclient/cosmetics/cloak/CloakFeatureRenderer.java index fbdf18a..b5b9f5e 100644 --- a/versions/1.21.4/src/main/java/org/saturnclient/cosmetics/cloak/CloakFeatureRenderer.java +++ b/versions/1.21.4/src/main/java/org/saturnclient/cosmetics/cloak/CloakFeatureRenderer.java @@ -282,7 +282,7 @@ public class CloakFeatureRenderer extends FeatureRenderer availableCloaks = new ArrayList<>(); - public static Identifier cloakCacheIdentifier = null; + public static IdentifierRef cloakCacheIdentifier = null; public static final Map> animatedCloaks = new ConcurrentHashMap<>(); private static final Map lastFrameTime = new ConcurrentHashMap<>(); @@ -129,8 +128,8 @@ public class Cloaks { .replace(' ', '_') .replaceAll("[^a-z0-9/._-]", ""); - cloakCacheIdentifier = Identifier.of(SaturnClient.MOD_ID, "cloaks_" + safeFileName); - IdentifierUtils.registerBufferedImageTexture(cloakCacheIdentifier, image); + cloakCacheIdentifier = IdentifierRef.of(SaturnClient.MOD_ID, "cloaks_" + safeFileName); + IdentifierUtils.registerBufferedImageTextureFast(cloakCacheIdentifier, image); } } catch (IOException e) { SaturnClient.LOGGER.error("Failed to load static cloak from resources: " + fileName, e); @@ -177,7 +176,7 @@ public class Cloaks { int delay = Math.max(gif.getDelay(i) * 10, 50); // Minimum 50ms delay String frameId = baseFrameId + "_frame_" + i; - Identifier frameIdentifier = Identifier.of(SaturnClient.MOD_ID, "cloaks_" + frameId); + IdentifierRef frameIdentifier = IdentifierRef.of(SaturnClient.MOD_ID, "cloaks_" + frameId); try { IdentifierUtils.registerBufferedImageTextureFast(frameIdentifier, frame); @@ -217,7 +216,7 @@ public class Cloaks { }, CLOAK_LOADER_EXECUTOR); } - public static Identifier getCurrentCloakTexture(UUID uuid) { + public static IdentifierRef getCurrentCloakTexture(UUID uuid) { SaturnPlayer player = SaturnPlayer.get(uuid); if (player == null || player.cloak.isEmpty()) { @@ -251,15 +250,15 @@ public class Cloaks { currentFrame = 0; } - Identifier identifier = frames.get(currentFrame).getTextureId(); + IdentifierRef identifier = frames.get(currentFrame).getTextureId(); if (identifier == null) { - return Identifier.of(SaturnClient.MOD_ID, "textures/cloaks/" + cloakName + ".png"); + return IdentifierRef.of(SaturnClient.MOD_ID, "textures/cloaks/" + cloakName + ".png"); } return identifier; } else { - return Identifier.of(SaturnClient.MOD_ID, "textures/cloaks/" + cloakName + ".png"); + return IdentifierRef.of(SaturnClient.MOD_ID, "textures/cloaks/" + cloakName + ".png"); } } } \ No newline at end of file diff --git a/versions/1.21.4/src/main/java/org/saturnclient/cosmetics/cloak/utils/AnimatedCloakData.java b/versions/1.21.4/src/main/java/org/saturnclient/cosmetics/cloak/utils/AnimatedCloakData.java deleted file mode 100644 index ca92aa0..0000000 --- a/versions/1.21.4/src/main/java/org/saturnclient/cosmetics/cloak/utils/AnimatedCloakData.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.saturnclient.cosmetics.cloak.utils; - -import net.minecraft.util.Identifier; - -/** - * Represents a single frame of an animated cloak. - */ -public class AnimatedCloakData { - private final Identifier textureId; - private final int delayMs; - - /** - * Creates a new animated cloak frame. - * - * @param textureId The texture identifier for this frame - * @param delayMs The delay in milliseconds before the next frame - */ - public AnimatedCloakData(Identifier textureId, int delayMs) { - this.textureId = textureId; - this.delayMs = delayMs; - } - - /** - * @return The texture identifier for this frame - */ - public Identifier getTextureId() { - return textureId; - } - - /** - * @return The delay in milliseconds before the next frame - */ - public int getDelayMs() { - return delayMs; - } -} diff --git a/versions/1.21.4/src/main/java/org/saturnclient/cosmetics/cloak/utils/IdentifierUtils.java b/versions/1.21.4/src/main/java/org/saturnclient/cosmetics/cloak/utils/IdentifierUtils.java index 93fb940..514d7e6 100644 --- a/versions/1.21.4/src/main/java/org/saturnclient/cosmetics/cloak/utils/IdentifierUtils.java +++ b/versions/1.21.4/src/main/java/org/saturnclient/cosmetics/cloak/utils/IdentifierUtils.java @@ -1,98 +1,70 @@ package org.saturnclient.cosmetics.cloak.utils; +import org.saturnclient.common.ref.asset.IdentifierRef; import org.saturnclient.saturnclient.SaturnClient; + import net.minecraft.client.texture.NativeImage; import net.minecraft.client.texture.NativeImageBackedTexture; import net.minecraft.util.Identifier; import java.awt.image.BufferedImage; import java.awt.image.DataBufferInt; +import java.util.Map; public class IdentifierUtils { - /** - * ORIGINAL METHOD - EXTREMELY SLOW - causes 10-20 second freezes - * This converts BufferedImage -> PNG bytes -> ByteBuffer -> NativeImage -> - * Texture - * This is completely unnecessary and wastes massive amounts of CPU time! - */ - public static void registerBufferedImageTexture(Identifier i, BufferedImage bi) { + public static void registerBufferedImageTextureFast(IdentifierRef identifierRef, BufferedImage bufferedImage) { try { - // This is the performance killer: - // 1. Converts BufferedImage to PNG (expensive compression) - // 2. Creates ByteBuffer copy (memory allocation) - // 3. NativeImage.read() parses PNG back to raw pixels (expensive decompression) - // This is doing compression -> decompression for no reason! + Identifier identifier = (Identifier) (Object) identifierRef; - java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream(); - javax.imageio.ImageIO.write(bi, "png", baos); - byte[] bytes = baos.toByteArray(); - java.nio.ByteBuffer bb = org.lwjgl.BufferUtils.createByteBuffer(bytes.length).put(bytes); - bb.flip(); - NativeImageBackedTexture nibt = new NativeImageBackedTexture(NativeImage.read(bb)); - SaturnClient.client.getTextureManager().registerTexture(i, nibt); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * OPTIMIZED METHOD - Direct pixel conversion without unnecessary PNG - * encoding/decoding - * This should reduce loading time from 10-20 seconds to under 1 second - */ - public static void registerBufferedImageTextureFast(Identifier identifier, BufferedImage bufferedImage) { - try { int width = bufferedImage.getWidth(); int height = bufferedImage.getHeight(); - // Create NativeImage directly with the correct format NativeImage nativeImage = new NativeImage(NativeImage.Format.RGBA, width, height, false); - // Direct pixel copy - much faster than PNG conversion if (bufferedImage.getType() == BufferedImage.TYPE_INT_ARGB) { - // Fast path for ARGB images - direct memory access int[] pixels = ((DataBufferInt) bufferedImage.getRaster().getDataBuffer()).getData(); + + int index = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { - int pixel = pixels[y * width + x]; - nativeImage.setColorArgb(x, y, pixel); + nativeImage.setColorArgb(x, y, pixels[index++]); } } + } else { - // Fallback for other image types - still faster than PNG conversion + for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { - int rgb = bufferedImage.getRGB(x, y); - nativeImage.setColorArgb(x, y, rgb); + nativeImage.setColorArgb(x, y, bufferedImage.getRGB(x, y)); } } + } - // Register the texture NativeImageBackedTexture texture = new NativeImageBackedTexture(nativeImage); - SaturnClient.client.execute( - () -> SaturnClient.client.getTextureManager().registerTexture(identifier, texture)); + + SaturnClient.client.execute(() -> + SaturnClient.client.getTextureManager().registerTexture(identifier, texture) + ); } catch (Exception e) { - SaturnClient.LOGGER.error("Failed to register texture: " + identifier, e); - // Fallback to slow method if fast method fails - registerBufferedImageTexture(identifier, bufferedImage); + SaturnClient.LOGGER.error("Failed to register texture: {}", identifierRef, e); } } - /** - * EVEN FASTER VERSION - Bulk texture registration - * Use this when registering many textures at once (like animated cloak frames) - */ - public static void registerBufferedImageTexturesBulk(java.util.Map textures) { - long startTime = System.currentTimeMillis(); + public static void registerBufferedImageTexturesBulk(Map textures) { - for (java.util.Map.Entry entry : textures.entrySet()) { - registerBufferedImageTextureFast(entry.getKey(), entry.getValue()); - } + long start = System.currentTimeMillis(); - long endTime = System.currentTimeMillis(); - SaturnClient.LOGGER.info("Registered {} textures in {}ms", textures.size(), (endTime - startTime)); + textures.forEach(IdentifierUtils::registerBufferedImageTextureFast); + + long end = System.currentTimeMillis(); + + SaturnClient.LOGGER.info( + "Registered {} textures in {}ms", + textures.size(), + (end - start) + ); } } \ No newline at end of file diff --git a/versions/1.21.4/src/main/java/org/saturnclient/cosmetics/cloak/utils/RandomUtils.java b/versions/1.21.4/src/main/java/org/saturnclient/cosmetics/cloak/utils/RandomUtils.java deleted file mode 100644 index b555d83..0000000 --- a/versions/1.21.4/src/main/java/org/saturnclient/cosmetics/cloak/utils/RandomUtils.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.saturnclient.cosmetics.cloak.utils; - -import java.util.Random; - -/** - * Utility class for generating random strings and numbers. - */ -public final class RandomUtils { - private static final String ALPHANUMERIC = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - private static final String ALPHANUMERIC_LOWERCASE = "0123456789abcdefghijklmnopqrstuvwxyz"; - private static final Random RANDOM = new Random(); - - private RandomUtils() { - // Prevent instantiation - } - - /** - * Generates a random string of specified length using given characters. - */ - private static String random(final int length, final char[] chars) { - StringBuilder sb = new StringBuilder(length); - for (int i = 0; i < length; i++) { - sb.append(chars[RANDOM.nextInt(chars.length)]); - } - return sb.toString(); - } - - /** - * Generates a random string of specified length using alphanumeric characters. - */ - public static String randomString(final int length) { - return random(length, ALPHANUMERIC.toCharArray()); - } - - /** - * Generates a random lowercase string of specified length. - */ - public static String randomStringLowercase(final int length) { - return random(length, ALPHANUMERIC_LOWERCASE.toCharArray()); - } - - /** - * Generates a random integer between min and max (inclusive). - */ - public static int randBetween(int min, int max) { - return RANDOM.nextInt(max - min + 1) + min; - } -} \ No newline at end of file diff --git a/versions/1.21.4/src/main/java/org/saturnclient/impl/provider/SaturnProviderImpl.java b/versions/1.21.4/src/main/java/org/saturnclient/impl/provider/SaturnProviderImpl.java index 2ef99a1..f31019f 100644 --- a/versions/1.21.4/src/main/java/org/saturnclient/impl/provider/SaturnProviderImpl.java +++ b/versions/1.21.4/src/main/java/org/saturnclient/impl/provider/SaturnProviderImpl.java @@ -67,6 +67,6 @@ public class SaturnProviderImpl implements SaturnProvider { @Override public void registerBufferedImageTexture(IdentifierRef i, BufferedImage bi) { - IdentifierUtils.registerBufferedImageTextureFast((Identifier) (Object) i, bi); + IdentifierUtils.registerBufferedImageTextureFast(i, bi); } }