aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron <51387595+AzureAaron@users.noreply.github.com>2024-01-10 17:24:53 -0500
committerGitHub <noreply@github.com>2024-01-10 17:24:53 -0500
commitde96684315a10bd224069c253bbefa408659dc3c (patch)
treefd52f7b7e6c97709441a64b786ef612f11b9b36a
parentffab9576c0f7534195f276b677bd5bdeac5e8a3a (diff)
downloadSkyblocker-de96684315a10bd224069c253bbefa408659dc3c.tar.gz
Skyblocker-de96684315a10bd224069c253bbefa408659dc3c.tar.bz2
Skyblocker-de96684315a10bd224069c253bbefa408659dc3c.zip
Fix Skin Transparency applying to player skins (#477)
-rw-r--r--src/main/java/de/hysky/skyblocker/SkyblockerMod.java1
-rw-r--r--src/main/java/de/hysky/skyblocker/mixin/PlayerSkinTextureMixin.java28
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/PlayerHeadHashCache.java64
3 files changed, 89 insertions, 4 deletions
diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java
index f2359265..6e702e7b 100644
--- a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java
+++ b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java
@@ -84,6 +84,7 @@ public class SkyblockerMod implements ClientModInitializer {
Tips.init();
NEURepoManager.init();
ItemRepository.init();
+ PlayerHeadHashCache.init();
HotbarSlotLock.init();
ItemTooltip.init();
WikiLookup.init();
diff --git a/src/main/java/de/hysky/skyblocker/mixin/PlayerSkinTextureMixin.java b/src/main/java/de/hysky/skyblocker/mixin/PlayerSkinTextureMixin.java
index ea771c1e..1065bab0 100644
--- a/src/main/java/de/hysky/skyblocker/mixin/PlayerSkinTextureMixin.java
+++ b/src/main/java/de/hysky/skyblocker/mixin/PlayerSkinTextureMixin.java
@@ -1,19 +1,39 @@
package de.hysky.skyblocker.mixin;
+import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import com.llamalad7.mixinextras.injector.WrapWithCondition;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.skyblock.item.PlayerHeadHashCache;
import de.hysky.skyblocker.utils.Utils;
import dev.cbyrne.betterinject.annotations.Inject;
+import net.minecraft.client.texture.NativeImage;
import net.minecraft.client.texture.PlayerSkinTexture;
@Mixin(PlayerSkinTexture.class)
public class PlayerSkinTextureMixin {
+ @Shadow
+ @Final
+ private String url;
+
+ @Unique
+ private boolean isSkyblockSkinTexture;
+
+ @Inject(method = "remapTexture", at = @At("HEAD"))
+ private void skyblocker$determineSkinSource() {
+ if (Utils.isOnSkyblock()) {
+ int skinHash = PlayerHeadHashCache.getSkinHash(this.url).hashCode();
+ this.isSkyblockSkinTexture = PlayerHeadHashCache.contains(skinHash);
+ }
+ }
- @Inject(method = "stripAlpha", at = @At("HEAD"), cancellable = true)
- private static void skyblocker$dontStripAlphaValues(CallbackInfo ci) {
- if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().general.dontStripSkinAlphaValues) ci.cancel();
+ @WrapWithCondition(method = "remapTexture", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/texture/PlayerSkinTexture;stripAlpha(Lnet/minecraft/client/texture/NativeImage;IIII)V"))
+ private boolean skyblocker$dontStripAlphaValues(NativeImage image, int x1, int y1, int x2, int y2) {
+ return !(SkyblockerConfigManager.get().general.dontStripSkinAlphaValues && this.isSkyblockSkinTexture);
}
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/PlayerHeadHashCache.java b/src/main/java/de/hysky/skyblocker/skyblock/item/PlayerHeadHashCache.java
new file mode 100644
index 00000000..2a1688fc
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/item/PlayerHeadHashCache.java
@@ -0,0 +1,64 @@
+package de.hysky.skyblocker.skyblock.item;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Base64;
+import java.util.concurrent.CompletableFuture;
+
+import org.apache.commons.io.FilenameUtils;
+import org.slf4j.Logger;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParser;
+import com.mojang.logging.LogUtils;
+
+import de.hysky.skyblocker.utils.Http;
+import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
+
+public class PlayerHeadHashCache {
+ private static final Logger LOGGER = LogUtils.getLogger();
+ private static final IntOpenHashSet CACHE = new IntOpenHashSet();
+
+ public static void init() {
+ CompletableFuture.runAsync(PlayerHeadHashCache::loadSkins);
+ }
+
+ private static void loadSkins() {
+ try {
+ String response = Http.sendGetRequest("https://api.hypixel.net/v2/resources/skyblock/items");
+ JsonArray items = JsonParser.parseString(response).getAsJsonObject().getAsJsonArray("items");
+
+ items.asList().stream()
+ .map(JsonElement::getAsJsonObject)
+ .filter(item -> item.get("material").getAsString().equals("SKULL_ITEM"))
+ .filter(item -> item.has("skin"))
+ .map(item -> Base64.getDecoder().decode(item.get("skin").getAsString()))
+ .map(String::new)
+ .map(profile -> JsonParser.parseString(profile).getAsJsonObject())
+ .map(profile -> profile.getAsJsonObject("textures").getAsJsonObject("SKIN").get("url").getAsString())
+ .map(PlayerHeadHashCache::getSkinHash)
+ .mapToInt(String::hashCode)
+ .forEach(CACHE::add);
+
+ LOGGER.info("[Skyblocker Player Head Hash Cache] Successfully cached the hashes of all player head items!");
+ } catch (Exception e) {
+ LOGGER.error("[Skyblocker Player Head Hash Cache] Failed to cache skin hashes!", e);
+ }
+ }
+
+ //From MinecraftProfileTexture#getHash
+ public static String getSkinHash(String url) {
+ try {
+ return FilenameUtils.getBaseName(new URL(url).getPath());
+ } catch (MalformedURLException e) {
+ LOGGER.error("[Skyblocker Player Head Hash Cache] Malformed Skin URL! URL: {}", url, e);
+ }
+
+ return "";
+ }
+
+ public static boolean contains(int hash) {
+ return CACHE.contains(hash);
+ }
+}