diff --git a/core/src/main/java/com/funkeln/pronouns/PronounAddon.java b/core/src/main/java/com/funkeln/pronouns/PronounAddon.java index ad926df..96a930f 100644 --- a/core/src/main/java/com/funkeln/pronouns/PronounAddon.java +++ b/core/src/main/java/com/funkeln/pronouns/PronounAddon.java @@ -1,7 +1,10 @@ package com.funkeln.pronouns; +import com.funkeln.pronouns.event.BroadcastEventListener; +import com.funkeln.pronouns.event.ServerJoinListener; import com.funkeln.pronouns.nametag.FlagNameTag; -import com.funkeln.pronouns.utils.Pridetags; +import com.funkeln.pronouns.profile.ProfileRepository; +import com.google.gson.JsonObject; import net.labymod.api.Laby; import net.labymod.api.addon.LabyAddon; import net.labymod.api.client.component.Component; @@ -10,9 +13,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.funkeln.pronouns.nametag.PronounNameTag; -import com.funkeln.pronouns.utils.Profile; -import com.funkeln.pronouns.utils.PronounsAPI; -import com.funkeln.pronouns.utils.PronounsAPI.ProfileFetchListener; @AddonMain public class PronounAddon extends LabyAddon { @@ -38,34 +38,17 @@ protected void enable() { INSTANCE = this; this.registerSettingCategory(); if(this.configuration().enabled().get()) { - if(configuration().name().get().isEmpty()) { - displayMessage("Please set the name in the config"); - } else { - meow = configuration().name().get().trim(); - } - PronounsAPI.addProfileFetchListener(meow, new ProfileFetchListener() { - @Override - public void onProfileFetched(Profile profile) { - log.info("Fetched profile for " + meow); - pronoun = profile.getPronoun().trim(); - } - - @Override - public void onProfileFetchFailed(String username, Exception e) { - log.error("Failed to fetch profile for " + username, e); - e.printStackTrace(); - } - }); - - // Request the profile - PronounsAPI.getProfile(meow); - - // Wait to ensure the async task completes (for demonstration purposes) - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - e.printStackTrace(); - } + labyAPI().eventBus().registerListener(new BroadcastEventListener()); + labyAPI().taskExecutor().getScheduledPool().scheduleAtFixedRate( + () -> { + publishNameUpdate(); + ProfileRepository.updateProfiles(false); + }, + 30000, + 30000, + java.util.concurrent.TimeUnit.MILLISECONDS + ); + labyAPI().eventBus().registerListener(new ServerJoinListener(this)); } this.logger().info("Enabled the Addon"); this.labyAPI().tagRegistry().register( diff --git a/core/src/main/java/com/funkeln/pronouns/event/BroadcastEventListener.java b/core/src/main/java/com/funkeln/pronouns/event/BroadcastEventListener.java new file mode 100644 index 0000000..e6f5f0c --- /dev/null +++ b/core/src/main/java/com/funkeln/pronouns/event/BroadcastEventListener.java @@ -0,0 +1,31 @@ +package com.funkeln.pronouns.event; + +import com.funkeln.pronouns.profile.ProfileRepository; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import net.labymod.api.event.Subscribe; +import net.labymod.api.event.labymod.labyconnect.session.LabyConnectBroadcastEvent; +import java.util.UUID; + +/** + * @author https://github.com/PrincessAkira (Sarah) Today is the 9/9/2024 @9:58 PM This project is + * named labymod4-addon-template + * @description Another day of Insanity + */ +public class BroadcastEventListener { + @Subscribe + public void onBroadcastReceive(LabyConnectBroadcastEvent event) { + if (!event.getKey().equals("pronouns")) { + return; + } + JsonElement payload = event.getPayload(); + if (!payload.isJsonObject()) { + return; + } + JsonObject jsonObject = payload.getAsJsonObject(); + UUID sender = event.getSender(); + String name = jsonObject.get("name").getAsJsonPrimitive().getAsString(); + ProfileRepository.enterName(sender, name); + ProfileRepository.updateProfiles(true); + } + } diff --git a/core/src/main/java/com/funkeln/pronouns/flag/FlagResolver.java b/core/src/main/java/com/funkeln/pronouns/flag/FlagResolver.java new file mode 100644 index 0000000..8cfd71c --- /dev/null +++ b/core/src/main/java/com/funkeln/pronouns/flag/FlagResolver.java @@ -0,0 +1,65 @@ +package com.funkeln.pronouns.flag; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Consumer; +import net.labymod.api.Laby; +import net.labymod.api.client.gui.icon.Icon; + +/** + * @author https://github.com/PrincessAkira (Sarah) Today is the 9/9/2024 @10:30 PM This project is + * named labymod4-addon-template + * @description Another day of Insanity + */ +public class FlagResolver { + private final static Map cache = new HashMap<>(); + private static final String FLAGS_URL = "https://en.pronouns.page/flags/"; + + // Name zu Icon + public static void iconFromName( + String name, + Consumer lazyReturn + ) { + if (name.contains("?") || name.contains("&") || name.contains("/") || name.contains(".")) { + return; + } + if (cache.containsKey(name)) { + lazyReturn.accept(cache.get(name)); + } + Laby.labyAPI().taskExecutor().getPool().submit(() -> { + Icon icon = Icon.url(FLAGS_URL + name + ".png"); + cache.put(name, icon); + lazyReturn.accept(icon); + }); + } + + // Namen zu Icons + public static void iconsFromName( + Consumer lazyReturn, + String... names + ) { + int size = names.length; + AtomicLong remaining = new AtomicLong(size); + Icon[] results = new Icon[size]; + + for (int i = 0; i < names.length; i++) { + String name = names[i]; + int finalI = i; + iconFromName(name, icon -> { + results[finalI] = icon; + if (remaining.decrementAndGet() == 0) { + lazyReturn.accept(results); + } + }); + } + } + + public static void iconsFromName( + List names, + Consumer lazyReturn + ) { + iconsFromName(lazyReturn, names.toArray(new String[0])); + } +} diff --git a/core/src/main/java/com/funkeln/pronouns/nametag/FlagNameTag.java b/core/src/main/java/com/funkeln/pronouns/nametag/FlagNameTag.java index 5e8eb73..e9f1f90 100644 --- a/core/src/main/java/com/funkeln/pronouns/nametag/FlagNameTag.java +++ b/core/src/main/java/com/funkeln/pronouns/nametag/FlagNameTag.java @@ -36,12 +36,12 @@ public FlagNameTag(RectangleRenderer rectangleRenderer) { @Override protected @Nullable RenderableComponent getRenderableComponent() { - if (!(this.entity instanceof Player) || this.entity.isCrouching() || !Laby.labyAPI().minecraft().getClientPlayer().getName().equals(((Player) this.entity).getName())) { + if (!(this.entity instanceof Player) || this.entity.isCrouching()) { return null; } - HorizontalAlignment alignment; - alignment = HorizontalAlignment.CENTER; + if (ProfileRepository.find(this.entity.getUniqueId()).isPresent()) { + HorizontalAlignment alignment = HorizontalAlignment.CENTER; PronounAddon addon = PronounAddon.getInstance(); if (!addon.configuration().enabled().get()) { @@ -58,7 +58,10 @@ public FlagNameTag(RectangleRenderer rectangleRenderer) { } return RenderableComponent.of(component, alignment); + } else { + return null; } + } @Override protected void renderText( @@ -80,6 +83,7 @@ protected void renderText( for (Icon flag : flags) { // Render flag at the updated x position + flagcount++; flag.render(stack, x, +1, 15, height - 1); // Move the x position to the right for the next flag diff --git a/core/src/main/java/com/funkeln/pronouns/nametag/PronounNameTag.java b/core/src/main/java/com/funkeln/pronouns/nametag/PronounNameTag.java index 5c724f0..87a1ae9 100644 --- a/core/src/main/java/com/funkeln/pronouns/nametag/PronounNameTag.java +++ b/core/src/main/java/com/funkeln/pronouns/nametag/PronounNameTag.java @@ -10,7 +10,7 @@ import net.labymod.api.client.render.draw.RectangleRenderer; import net.labymod.api.client.render.font.RenderableComponent; import net.labymod.api.client.render.matrix.Stack; -import com.funkeln.pronouns.utils.Profile; +import com.funkeln.pronouns.profile.Profile; import org.jetbrains.annotations.Nullable; /** diff --git a/core/src/main/java/com/funkeln/pronouns/profile/Profile.java b/core/src/main/java/com/funkeln/pronouns/profile/Profile.java new file mode 100644 index 0000000..a65608f --- /dev/null +++ b/core/src/main/java/com/funkeln/pronouns/profile/Profile.java @@ -0,0 +1,154 @@ +package com.funkeln.pronouns.profile; + + +import com.funkeln.pronouns.flag.FlagResolver; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import net.labymod.api.Laby; +import net.labymod.api.client.gui.icon.Icon; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * @author https://github.com/PrincessAkira (Sarah) Today is the 9/8/2024 @2:39 AM This project is + * named labymod4-addon-template + * @description Another day of Insanity + */ +public class Profile { + public static final String API_URL = "https://en.pronouns.page/api/"; + public static long PROFILE_EXPIRY = 5 * 60 * 1000L; + public static long PRONOUN_EXPIRY = 5 * 60 * 1000L; + + private final UUID id; + private String websiteName = ""; + private String pronoun; + public Icon[] flags; + + private boolean requestedUpdate; + private boolean firstRequestSpent = false; + private long lastNameUpdate = System.currentTimeMillis(); + private long lastPronounUpdate = System.currentTimeMillis(); + + public Profile(UUID id) { + this.id = id; + } + + public void updateName(String name) { + if (!websiteName.equals(name)) { + this.websiteName = name; + pronoun = null; + flags = null; + requestedUpdate = true; + } + lastNameUpdate = System.currentTimeMillis(); + } + + public void update() { + firstRequestSpent = true; + requestedUpdate = false; + Laby.labyAPI().taskExecutor().getPool().submit(() -> { + // async + try { + URL url = new URI(API_URL + "profile/get/" + websiteName + "?version=2").toURL(); + JsonObject profile = null; + try (InputStream stream = url.openStream()) { + JsonElement element = JsonParser.parseReader(new InputStreamReader(stream)); + profile = element.getAsJsonObject(); + } + updatePronouns(pronounFromJson(profile)); + List flagNames = flagNamesFromJson(profile); + FlagResolver.iconsFromName(flagNames, this::updateFlags); + } catch (URISyntaxException | IOException e) { + e.printStackTrace(); + } + }); + } + + public boolean updateRequired() { + return System.currentTimeMillis() - lastPronounUpdate > PRONOUN_EXPIRY || requestedUpdate; + } + + public boolean requiresUpdateNow() { + return !firstRequestSpent; + } + + public static String pronounFromJson(JsonObject profile) { + JsonArray pronounsArray = profile.getAsJsonObject("profiles").getAsJsonObject("en").getAsJsonArray("pronouns"); + if (pronounsArray == null || pronounsArray.isEmpty()) return null; + List outputPronounList = new ArrayList<>(); + for(JsonElement pronoun : pronounsArray) { + outputPronounList.add(pronoun.getAsJsonObject().get("value").getAsString()); + if(outputPronounList.size() > 3) { + break; + } + } + return String.join(" & ", outputPronounList); + } + + public static List flagNamesFromJson(JsonObject profile) { + JsonObject profiles = profile.getAsJsonObject("profiles"); + if (profiles == null) { + return null; + } + JsonObject enProfile = profiles.getAsJsonObject("en"); + if (enProfile == null) { + return null; + } + JsonArray flagsArray = enProfile.getAsJsonArray("flags"); + if (flagsArray == null || flagsArray.isEmpty()) { + return null; + } + List flagNamesList = new ArrayList<>(); + for (JsonElement flag : flagsArray) { + if(flagNamesList.size() > 3) { + break; + } + flagNamesList.add(flag.getAsString()); + } + return flagNamesList; + } + + public boolean expired() { + return System.currentTimeMillis() - lastNameUpdate > PROFILE_EXPIRY + ; + } + + public boolean pronounsAvailable() { + return pronoun != null; + } + + public boolean flagsAvailable() { + return flags != null; + } + + public Icon[] flags() { + return flags; + } + + public void updatePronouns(String pronoun) { + this.pronoun = pronoun; + lastPronounUpdate = System.currentTimeMillis(); + } + + public void updateFlags(Icon[] flags) { + this.flags = flags; + lastPronounUpdate = System.currentTimeMillis(); + } + + public String username() { + return websiteName; + } + + public String pronoun() { + return pronoun; + } +} diff --git a/core/src/main/java/com/funkeln/pronouns/utils/Pridetags.java b/core/src/main/java/com/funkeln/pronouns/utils/Pridetags.java deleted file mode 100644 index 4981ca1..0000000 --- a/core/src/main/java/com/funkeln/pronouns/utils/Pridetags.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.funkeln.pronouns.utils; - -import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; - -public final class Pridetags { - - public static Set profiles = new CopyOnWriteArraySet<>(); - - - - public static Set getProfiles() { - // return all profiles from the HashMap - StringBuilder sb = new StringBuilder(); - for (Profile profile : profiles) { - // put them into a big string - sb.append(profile.getUsername() + " : " + profile.getPronoun() + "\n"); - } - return profiles; - } - -} \ No newline at end of file diff --git a/core/src/main/java/com/funkeln/pronouns/utils/Profile.java b/core/src/main/java/com/funkeln/pronouns/utils/Profile.java deleted file mode 100644 index 1d8056e..0000000 --- a/core/src/main/java/com/funkeln/pronouns/utils/Profile.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.funkeln.pronouns.utils; - - -import net.labymod.api.client.gui.icon.Icon; - -/** - * @author https://github.com/PrincessAkira (Sarah) Today is the 9/8/2024 @2:39 AM This project is - * named labymod4-addon-template - * @description Another day of Insanity - */ -public class Profile { - - private final String username; - private final String pronoun; - - public static volatile Icon[] flags; - - public Profile(String username, String pronoun, Icon[] flags) { - this.username = username; - this.pronoun = pronoun; - this.flags = flags; - } - - public String getUsername() { return username; } - public String getPronoun() { return pronoun; } - public static Icon[] getFlags() { return flags; } - -} diff --git a/core/src/main/java/com/funkeln/pronouns/utils/PronounsAPI.java b/core/src/main/java/com/funkeln/pronouns/utils/PronounsAPI.java deleted file mode 100644 index 297bedb..0000000 --- a/core/src/main/java/com/funkeln/pronouns/utils/PronounsAPI.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.funkeln.pronouns.utils; - -import com.funkeln.pronouns.PronounAddon; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import net.labymod.api.Laby; -import net.labymod.api.client.gui.icon.Icon; - -import java.io.*; -import java.net.*; -import java.util.*; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.function.Consumer; - -public class PronounsAPI { - - public static final String API_URL = "https://en.pronouns.page/api/"; - public static final String FLAGS_URL = "https://en.pronouns.page/flags/"; - private static PronounsAPI instance; - - private static final Map listeners = new HashMap<>(); - - public static void addProfileFetchListener(String username, ProfileFetchListener listener) { - listeners.put(username, listener); - } - - public static PronounsAPI getInstance() { - if (instance == null) { - instance = new PronounsAPI(); - } - return instance; - } - - private static void fetchProfile(String name) { - new Thread(() -> { - try { - URL url = new URI(API_URL + "profile/get/" + name + "?version=2").toURL(); - JsonObject profile = null; - try (InputStream stream = url.openStream()) { - JsonElement element = JsonParser.parseReader(new InputStreamReader(stream)); - profile = element.getAsJsonObject(); - } - String pronoun = getPronoun(profile); - Icon[] flags = getFlags(profile); - Profile profileObj = new Profile(name, pronoun, flags); - Pridetags.profiles.add(profileObj); - - // Notify listener - ProfileFetchListener listener = listeners.get(name); - if (listener != null) { - listener.onProfileFetched(profileObj); - } - } catch (URISyntaxException | IOException e) { - // Notify listener of failure - ProfileFetchListener listener = listeners.get(name); - if (listener != null) { - listener.onProfileFetchFailed(name, e); - } - } - }).start(); - } - - public interface ProfileFetchListener { - void onProfileFetched(Profile profile); - void onProfileFetchFailed(String username, Exception e); - } - - - public static Profile getProfile(String name) { - Optional maybeProfile = Pridetags.profiles.stream() - .filter(profile -> profile.getUsername().equals(name)) - .findFirst(); - - if (maybeProfile.isPresent()) return maybeProfile.get(); - - fetchProfile(name); - return null; - } - - public static String getPronoun(JsonObject profile) { - JsonArray pronounsArray = profile.getAsJsonObject("profiles").getAsJsonObject("en").getAsJsonArray("pronouns"); - if (pronounsArray == null || pronounsArray.isEmpty()) return null; - return pronounsArray.get(0).getAsJsonObject().get("value").getAsString(); - } - - public static Icon[] getFlags(JsonObject profile) { - if (PronounAddon.getInstance().configuration().enabled().get()) { - JsonObject profiles = profile.getAsJsonObject("profiles"); - if (profiles == null) { - return null; - } - JsonObject enProfile = profiles.getAsJsonObject("en"); - if (enProfile == null) { - return null; - } - JsonArray flagsArray = enProfile.getAsJsonArray("flags"); - if (flagsArray == null || flagsArray.isEmpty()) { - return null; - } - List flagsList = new ArrayList<>(); - List flagNamesList = new ArrayList<>(); - for (JsonElement flag : flagsArray) { - String url = FLAGS_URL + flag.getAsString() + ".png"; - try { - URL iconURL = new URL(url); - Icon icon = Icon.url(String.valueOf(iconURL)); - flagsList.add(icon); - flagNamesList.add(flag.getAsString()); - } catch (Exception e) { - e.printStackTrace(); // Consider better error handling here - } - } - return flagsList.toArray(new Icon[0]); - } - return null; - } - }