costmetics update

This commit is contained in:
2026-02-23 10:24:59 +01:00
parent 1ab0820bac
commit 7eb500a35c
4 changed files with 315 additions and 68 deletions

View File

@@ -1,16 +1,21 @@
package dev.tggamesyt.szar.client;
import dev.tggamesyt.szar.Szar;
import com.google.gson.*;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.minecraft.client.MinecraftClient;
import net.minecraft.network.PacketByteBuf;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.minecraft.util.math.MathHelper;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.io.InputStream;
import java.lang.management.ManagementFactory;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
public class ClientCosmetics {
@@ -20,62 +25,41 @@ public class ClientCosmetics {
}
public static class CosmeticProfile {
public final NameType nameType;
public final Formatting staticColor; // for STATIC names
public final Identifier capeTexture; // optional cape
public final int gradientStart; // RGB int, for GRADIENT
public final int gradientEnd; // RGB int, for GRADIENT
public CosmeticProfile(NameType nameType, Formatting staticColor, Identifier capeTexture,
int gradientStart, int gradientEnd) {
this.nameType = nameType;
this.staticColor = staticColor;
this.capeTexture = capeTexture;
this.gradientStart = gradientStart;
this.gradientEnd = gradientEnd;
}
public NameType nameType;
public Integer staticColor;
public Integer gradientStart;
public Integer gradientEnd;
public Identifier capeTexture;
}
// Registry
private static final Map<UUID, CosmeticProfile> PROFILES = new HashMap<>();
static {
// ===== TGdoesCode ===== animated gradient
PROFILES.put(
UUID.fromString("20bbb23e-2f22-46ba-b201-c6bd435b445b"),
new CosmeticProfile(
NameType.GRADIENT,
null,
new Identifier(Szar.MOD_ID, "textures/etc/tg_cape.png"),
0x8CD6FF, // light blue
0x00FFFF // cyan
)
);
// Player UUID -> Mojang cape list
public static final Map<UUID, List<MojangCape>> MOJANG_CAPES = new HashMap<>();
// ===== Berci08ur_mom =====
PROFILES.put(
UUID.fromString("dda61748-15a4-45ff-9eea-29efc99c1711"),
new CosmeticProfile(
NameType.STATIC,
Formatting.GREEN,
new Identifier(Szar.MOD_ID, "textures/etc/gold_cape.png"),
0, 0
)
);
// ===== gabri =====
PROFILES.put(
UUID.fromString("52af5540-dd18-4ad9-9acb-50eb11531180"),
new CosmeticProfile(
NameType.STATIC,
Formatting.RED,
new Identifier(Szar.MOD_ID, "textures/etc/gabri_cape.png"),
0, 0
)
);
public static class MojangCape {
public String id;
public String name;
public String url;
}
public static CosmeticProfile getProfile(UUID uuid) {
public static void apply(UUID uuid, NameType type,
Integer staticColor,
Integer gradientStart,
Integer gradientEnd,
Identifier capeTexture) {
CosmeticProfile profile = new CosmeticProfile();
profile.nameType = type;
profile.staticColor = staticColor;
profile.gradientStart = gradientStart;
profile.gradientEnd = gradientEnd;
profile.capeTexture = capeTexture;
PROFILES.put(uuid, profile);
}
public static CosmeticProfile get(UUID uuid) {
return PROFILES.get(uuid);
}
@@ -83,33 +67,89 @@ public class ClientCosmetics {
CosmeticProfile profile = PROFILES.get(uuid);
if (profile == null) return null;
if (profile.nameType == NameType.STATIC) {
return Text.literal(name).formatted(profile.staticColor, Formatting.BOLD);
if (profile.nameType == NameType.STATIC && profile.staticColor != null) {
return Text.literal(name)
.styled(s -> s.withColor(profile.staticColor).withBold(true));
}
// GRADIENT animation
long time = Util.getMeasuringTimeMs();
MutableText animated = Text.empty();
for (int i = 0; i < name.length(); i++) {
// Animate wave
float progress = (time * 0.08f) + (i * 1.2f);
float progress = (time * 0.008f) + (i * 0.5f);
float wave = (float) Math.sin(progress);
float t = (wave + 1f) / 2f; // 0..1
float t = (wave + 1f) / 2f;
// Interpolate RGB
int r = (int) MathHelper.lerp(t, (profile.gradientStart >> 16) & 0xFF, (profile.gradientEnd >> 16) & 0xFF);
int g = (int) MathHelper.lerp(t, (profile.gradientStart >> 8) & 0xFF, (profile.gradientEnd >> 8) & 0xFF);
int b = (int) MathHelper.lerp(t, profile.gradientStart & 0xFF, profile.gradientEnd & 0xFF);
int r = (int) MathHelper.lerp(t,
(profile.gradientStart >> 16) & 0xFF,
(profile.gradientEnd >> 16) & 0xFF);
int g = (int) MathHelper.lerp(t,
(profile.gradientStart >> 8) & 0xFF,
(profile.gradientEnd >> 8) & 0xFF);
int b = (int) MathHelper.lerp(t,
profile.gradientStart & 0xFF,
profile.gradientEnd & 0xFF);
int color = (r << 16) | (g << 8) | b;
animated.append(
Text.literal(String.valueOf(name.charAt(i)))
.styled(style -> style.withColor(color).withBold(true))
.styled(s -> s.withColor(color).withBold(true))
);
}
return animated;
}
/* ---------------- FETCH MOJANG CAPES ---------------- */
public static void fetchMojangCapes(UUID uuid) {
try {
String accessToken = getAccessTokenFromLaunchArgs();
if (accessToken == null) return;
URL url = new URL("https://api.minecraftservices.com/minecraft/profile");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestProperty("Authorization", "Bearer " + accessToken);
con.setRequestMethod("GET");
InputStream in = con.getInputStream();
String json = new String(in.readAllBytes());
in.close();
System.out.println("[ClientCosmetics] Mojang capes JSON: " + json);
JsonObject obj = JsonParser.parseString(json).getAsJsonObject();
JsonArray capes = obj.getAsJsonArray("capes");
if (capes == null) return;
List<MojangCape> list = new ArrayList<>();
for (JsonElement e : capes) {
JsonObject c = e.getAsJsonObject();
MojangCape cape = new MojangCape();
cape.id = c.get("id").getAsString();
cape.name = c.has("alias") ? c.get("alias").getAsString() : cape.id;
cape.url = c.get("url").getAsString();
list.add(cape);
}
MOJANG_CAPES.put(uuid, list);
} catch (Exception ex) {
ex.printStackTrace();
}
}
private static String getAccessTokenFromLaunchArgs() {
for (String arg : ManagementFactory.getRuntimeMXBean().getInputArguments()) {
if (arg.startsWith("--accessToken")) {
String[] split = arg.split("=", 2);
if (split.length == 2) return split[1];
else continue;
}
}
return null;
}
}

View File

@@ -13,11 +13,15 @@ public abstract class TGcapeMixin {
@Inject(method = "getCapeTexture", at = @At("HEAD"), cancellable = true)
private void injectCapeTexture(CallbackInfoReturnable<Identifier> cir) {
AbstractClientPlayerEntity self = (AbstractClientPlayerEntity)(Object)this;
AbstractClientPlayerEntity player = (AbstractClientPlayerEntity)(Object) this;
var profile = ClientCosmetics.getProfile(self.getUuid());
ClientCosmetics.CosmeticProfile profile =
ClientCosmetics.get(player.getUuid());
// Only override if we actually have a custom cape
if (profile != null && profile.capeTexture != null) {
cir.setReturnValue(profile.capeTexture);
}
// Otherwise vanilla continues → Mojang cape works normally
}
}