Rank Stuff

This commit is contained in:
Patrick
2026-07-12 17:01:53 +02:00
parent cebcd4b79d
commit 728d955ff0
12 changed files with 192 additions and 3 deletions
@@ -11,9 +11,15 @@ import net.fabricmc.fabric.api.client.keymapping.v1.KeyMappingHelper;
import net.minecraft.client.KeyMapping;
import net.minecraft.resources.Identifier;
import org.lwjgl.glfw.GLFW;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CitrusDevClient implements ClientModInitializer {
public static final Logger logger = LoggerFactory.getLogger(CitrusDevClient.class);
private static final boolean debug = true;
public static final String API_URL = "https://citrus-api.winniepat.de";
private static KeyMapping openScreenKey;
@@ -59,4 +65,9 @@ public class CitrusDevClient implements ClientModInitializer {
});
}
public static void debugLog(String message) {
if (debug) {
logger.info("[Citrus] [DEBUG] {}", message);
}
}
}
@@ -32,8 +32,7 @@ public class Verifier {
HTTP.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenAccept(response -> {
System.out.println("Status: " + response.statusCode());
System.out.println("Body: " + response.body());
CitrusDevClient.debugLog("Verification Response - Status: " + response.statusCode() + ", Body: " + response.body());
})
.exceptionally(error -> {
error.printStackTrace();
@@ -0,0 +1,89 @@
package de.fullrisk.citrusDev.helper;
import de.fullrisk.citrusDev.client.CitrusDevClient;
import net.minecraft.client.Minecraft;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
public class RankHelper {
public static final ConcurrentHashMap<UUID, String> rankCache = new ConcurrentHashMap<>();
private static final HttpClient client = HttpClient.newHttpClient();
public static String getRankIcon(UUID uuid) {
String rank = rankCache.get(uuid);
if (rank == null) {
rankCache.put(uuid, "loading");
// TODO fetch rank
return " ";
}
if (rank.equals("loading")) return " ";
// TODO Icons
return switch (rank) {
case "owner" -> "\uE001";
case "admin" -> "\uE002";
case "vip" -> "\uE003";
case "dev" -> "\uE004";
case "bughunter" -> "\uE005";
case "default" -> "\uE099";
default -> "";
};
}
private static String RANK_URL = CitrusDevClient.API_URL + "/api/player/%s/rank";
private static void fetchRank(UUID uuid) {
CompletableFuture.runAsync(() -> {
try {
HttpRequest request = HttpRequest.newBuilder().uri(URI.create(RANK_URL.formatted(uuid)))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
String rawRank = response.body().trim().toLowerCase();
if (rawRank.equals(rankCache.get(uuid))) {
return; // No change
}
CitrusDevClient.debugLog("Received Rank Content: '" + rawRank + "'");
rankCache.put(uuid, rawRank);
Minecraft.getInstance().execute(() -> {
var world = Minecraft.getInstance().level;
if (world != null) {
var player = world.getPlayerByUUID(uuid);
if (player != null) {
player.setCustomNameVisible(player.isCustomNameVisible());
CitrusDevClient.debugLog("Refreshed nametag for: " + player.getName().getString());
}
}
});
} else {
rankCache.put(uuid, "none");
}
} catch (Exception e) {
CitrusDevClient.debugLog("Failed to fetch rank: " + e.getMessage());
rankCache.put(uuid, "none");
}
});
}
public static void refreshRankIfChanged() {
Minecraft client = Minecraft.getInstance();
if (client.getConnection() == null) return;
client.getConnection().getOnlinePlayers().forEach(playerInfo -> fetchRank(playerInfo.getProfile().id()));
}
}
@@ -0,0 +1,43 @@
package de.fullrisk.citrusDev.mixin;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import de.fullrisk.citrusDev.helper.RankHelper;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.FontDescription;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.Style;
import net.minecraft.resources.Identifier;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import java.util.UUID;
@Mixin(EntityRenderer.class)
public abstract class PlayerNametagMixin<T extends Entity> {
@ModifyReturnValue(method = "getNameTag", at = @At("RETURN"))
private Component citrusDev$addRankIcon(Component original, T entity) {
if (entity instanceof Player player) {
UUID uuid = player.getUUID();
// TODO Check if player is online with client
String iconChar = RankHelper.getRankIcon(uuid);
if (!iconChar.trim().isEmpty()) {
MutableComponent icon = Component.literal(iconChar).setStyle(Style.EMPTY.withFont(
new FontDescription.Resource(Identifier.fromNamespaceAndPath("citrus-dev", "icon_font"))
));
MutableComponent nameWithSpace = Component.literal(" ")
.append(original)
.setStyle(Style.EMPTY.withFont(new FontDescription.Resource(Identifier.fromNamespaceAndPath("minecraft", "default"))));
return icon.append(nameWithSpace);
}
}
return original;
}
}