Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Issue-4641]Provide a way to get the player's head by uuid #4770

Open
wants to merge 4 commits into
base: 1.20.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -424,8 +424,8 @@ public static void render(RunicAltarBlockEntity altar, GuiGraphics gui, Minecraf
ms.popPose();
}

RenderHelper.renderProgressPie(gui, xc + radius + 32, yc - 8, progress,
recipe.assemble(altar.getItemHandler(), altar.getLevel().registryAccess()));
ItemStack output = recipe.assemble(altar.getItemHandler(), altar.getLevel().registryAccess());
RenderHelper.renderProgressPie(gui, xc + radius + 32, yc - 8, progress, output);

if (progress == 1F) {
gui.drawString(mc.font, "+", xc + radius + 14, yc + 12, 0xFFFFFF, false);
Expand All @@ -445,9 +445,13 @@ public static void render(RunicAltarBlockEntity altar, GuiGraphics gui, Minecraf
}
if (altar.recipeKeepTicks > 0 && altar.canAddLastRecipe()) {
String s = I18n.get("botaniamisc.altarRefill0");
gui.drawString(mc.font, s, xc - mc.font.width(s) / 2, yc + 10, 0xFFFFFF);
if (s != null && !s.isEmpty()) {
gui.drawString(mc.font, s, xc - mc.font.width(s) / 2, yc + 10, 0xFFFFFF);
}
s = I18n.get("botaniamisc.altarRefill1");
gui.drawString(mc.font, s, xc - mc.font.width(s) / 2, yc + 20, 0xFFFFFF);
if (s != null && !s.isEmpty()) {
gui.drawString(mc.font, s, xc - mc.font.width(s) / 2, yc + 20, 0xFFFFFF);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@
import vazkii.botania.common.crafting.BotaniaRecipeTypes;
import vazkii.botania.common.crafting.RunicAltarRecipe;
import vazkii.botania.common.helper.ItemNBTHelper;
import vazkii.botania.data.UuidNameProvider;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

public class HeadRecipe extends RunicAltarRecipe {

Expand Down Expand Up @@ -70,7 +72,15 @@ public ItemStack assemble(@NotNull Container inv, @NotNull RegistryAccess regist
for (int i = 0; i < inv.getContainerSize(); i++) {
ItemStack ingr = inv.getItem(i);
if (ingr.is(Items.NAME_TAG)) {
ItemNBTHelper.setString(stack, "SkullOwner", ingr.getHoverName().getString());
String nameTagText = ingr.getHoverName().getString();
if (isUUID(nameTagText)) {
// UUID
String PlayerName = UuidNameProvider.getPlayerNameFromUUID(nameTagText.replace("-", ""));
ItemNBTHelper.setString(stack, "SkullOwner", PlayerName);
} else {
// Player Name
ItemNBTHelper.setString(stack, "SkullOwner", ingr.getHoverName().getString());
}
break;
}
}
Expand Down Expand Up @@ -109,4 +119,10 @@ public void toNetwork(@NotNull FriendlyByteBuf buf, @NotNull HeadRecipe recipe)
}
}

private boolean isUUID(String input) {
String uuidRegex = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$|^[0-9a-fA-F]{32}$";
Pattern pattern = Pattern.compile(uuidRegex);
return pattern.matcher(input).matches();
}

}
99 changes: 99 additions & 0 deletions Xplat/src/main/java/vazkii/botania/data/UuidNameProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package vazkii.botania.data;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import org.jetbrains.annotations.Nullable;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.Duration;
import java.time.Instant;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class UuidNameProvider {

private static final Map<String, CacheEntry> cache = new ConcurrentHashMap<>();
private static final Map<String, FailureEntry> failureTimes = new ConcurrentHashMap<>();
private static final Duration CACHE_DURATION = Duration.ofMinutes(15);
private static final int MAX_FAILURES = 5;

public static String getPlayerNameFromUUID(String uuid) {
CacheEntry entry = cache.get(uuid);
boolean isCacheExpired = entry == null || entry.isExpired();

if (!isCacheExpired) {
return entry.name;
}

try {
URL url = new URL("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");

BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuilder content = new StringBuilder();

while ((inputLine = in.readLine()) != null) {
content.append(inputLine);
}
in.close();

JsonObject jsonObject = JsonParser.parseString(content.toString()).getAsJsonObject();
if (jsonObject.has("name")) {
String name = jsonObject.get("name").getAsString();

cache.put(uuid, new CacheEntry(name));
failureTimes.remove(uuid); // Reset failure count on success

return name;
} else {
return SaveFailureData(uuid);
}
} catch (Exception e) {
e.printStackTrace();
return SaveFailureData(uuid);
}
}

@Nullable
private static String SaveFailureData(String uuid) {
recordFailureTime(uuid);
FailureEntry failureEntry = failureTimes.getOrDefault(uuid, new FailureEntry());
if (failureEntry.failures >= MAX_FAILURES) {
cache.put(uuid, new CacheEntry(uuid)); // Store UUID as Name
failureTimes.remove(uuid); // Reset failure count after storing UUID as Name
return uuid;
}
return null;
}

private static void recordFailureTime(String uuid) {
FailureEntry failureEntry = failureTimes.computeIfAbsent(uuid, k -> new FailureEntry());
failureEntry.failures++;
failureEntry.lastFailureTime = Instant.now();
}

private static class CacheEntry {
final String name;
final Instant creationTime;

CacheEntry(String name) {
this.name = name;
this.creationTime = Instant.now();
}

boolean isExpired() {
return Instant.now().isAfter(creationTime.plus(CACHE_DURATION));
}
}

private static class FailureEntry {
int failures = 0;
Instant lastFailureTime = Instant.now();
}
}