diff options
Diffstat (limited to 'src/main/java/de/cowtipper/cowlection/handler')
-rw-r--r-- | src/main/java/de/cowtipper/cowlection/handler/FriendsHandler.java | 89 | ||||
-rw-r--r-- | src/main/java/de/cowtipper/cowlection/handler/PlayerCache.java | 5 |
2 files changed, 79 insertions, 15 deletions
diff --git a/src/main/java/de/cowtipper/cowlection/handler/FriendsHandler.java b/src/main/java/de/cowtipper/cowlection/handler/FriendsHandler.java index ae1467a..6229e0e 100644 --- a/src/main/java/de/cowtipper/cowlection/handler/FriendsHandler.java +++ b/src/main/java/de/cowtipper/cowlection/handler/FriendsHandler.java @@ -2,13 +2,15 @@ package de.cowtipper.cowlection.handler; import com.google.gson.JsonParseException; import com.google.gson.reflect.TypeToken; +import com.mojang.realmsclient.util.Pair; import de.cowtipper.cowlection.Cowlection; import de.cowtipper.cowlection.command.exception.ApiContactException; import de.cowtipper.cowlection.command.exception.MooCommandException; import de.cowtipper.cowlection.data.Friend; -import de.cowtipper.cowlection.util.ApiUtils; -import de.cowtipper.cowlection.util.GsonUtils; +import de.cowtipper.cowlection.data.HyPlayerData; +import de.cowtipper.cowlection.util.*; import io.netty.util.internal.ConcurrentSet; +import net.minecraft.client.Minecraft; import net.minecraft.command.PlayerNotFoundException; import net.minecraft.event.ClickEvent; import net.minecraft.event.HoverEvent; @@ -16,14 +18,14 @@ import net.minecraft.util.ChatComponentText; import net.minecraft.util.ChatStyle; import net.minecraft.util.EnumChatFormatting; import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.time.DurationFormatUtils; import java.io.File; import java.io.IOException; import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; -import java.util.Set; -import java.util.TreeSet; -import java.util.UUID; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; @@ -33,13 +35,16 @@ public class FriendsHandler { private final Cowlection main; private final Set<Friend> bestFriends = new ConcurrentSet<>(); private final File bestFriendsFile; - private final AtomicInteger bestFriendQueue = new AtomicInteger(); + private final AtomicInteger bestFriendNameCheckingQueue = new AtomicInteger(); + private final AtomicInteger bestFriendOnlineStatusQueue = new AtomicInteger(); + private final Set<String> bestFriendsOnlineStatusWithApiErrors = new ConcurrentSet<>(); + private long nextBestFriendOnlineCheck = 0; public FriendsHandler(Cowlection main, File friendsFile) { this.main = main; this.bestFriendsFile = friendsFile; loadBestFriends(); - updateBestFriends(); + doBestFriendsNameChangeCheck(); } public boolean isBestFriend(String playerName, boolean ignoreCase) { @@ -90,15 +95,15 @@ public class FriendsHandler { return bestFriends.stream().filter(friend -> friend.getUuid().equals(uuid)).findFirst().orElse(Friend.FRIEND_NOT_FOUND); } - public void updateBestFriends() { + public void doBestFriendsNameChangeCheck() { bestFriends.stream().filter(friend -> System.currentTimeMillis() - friend.getLastChecked() > UPDATE_FREQUENCY_DEFAULT) .forEach(friend1 -> { - bestFriendQueue.incrementAndGet(); - updateBestFriend(friend1, false); + bestFriendNameCheckingQueue.incrementAndGet(); + doBestFriendNameChangeCheck(friend1, false); }); } - public void updateBestFriend(Friend friend, boolean isCommandTriggered) { + public void doBestFriendNameChangeCheck(Friend friend, boolean isCommandTriggered) { ApiUtils.fetchCurrentName(friend, newName -> { if (newName == null) { // skipping friend, something went wrong with API request @@ -132,7 +137,7 @@ public class FriendsHandler { if (isCommandTriggered) { saveBestFriends(); } else { - int remainingFriendsToCheck = bestFriendQueue.decrementAndGet(); + int remainingFriendsToCheck = bestFriendNameCheckingQueue.decrementAndGet(); if (remainingFriendsToCheck == 0) { // we're done with checking for name changes, save updates to file! saveBestFriends(); @@ -141,6 +146,66 @@ public class FriendsHandler { }); } + public void runBestFriendsOnlineCheck(boolean isCommandTriggered) { + long now = System.currentTimeMillis(); + int delay = (isCommandTriggered ? 5 : 1) * 60000; + if (nextBestFriendOnlineCheck < now) { + // ^ prevent too frequent checks + nextBestFriendOnlineCheck = now + delay; + bestFriendOnlineStatusQueue.set(0); + bestFriendsOnlineStatusWithApiErrors.clear(); + final Map<String, HyPlayerData> onlineBestFriends = new ConcurrentHashMap<>(); + + main.getLogger().info("Checking best friends online status... (might take a bit)"); + + for (Friend bestFriend : bestFriends) { + bestFriendOnlineStatusQueue.incrementAndGet(); + ApiUtils.fetchHyPlayerDetails(bestFriend, hyPlayerData -> { + if (hyPlayerData != null && hyPlayerData.getLastLogin() > hyPlayerData.getLastLogout()) { + // online & not hiding their online status + main.getPlayerCache().addBestFriend(bestFriend.getName()); + + onlineBestFriends.put(bestFriend.getName(), hyPlayerData); + } + + int remainingFriendsToCheck = bestFriendOnlineStatusQueue.decrementAndGet(); + if (remainingFriendsToCheck == 0 && Minecraft.getMinecraft().thePlayer != null) { + // we're done with checking for online status + MooChatComponent bestFriendsComponent = new MooChatComponent("⬤ Online best friends (" + + EnumChatFormatting.DARK_GREEN + onlineBestFriends.size() + EnumChatFormatting.GREEN + "/" + EnumChatFormatting.DARK_GREEN + bestFriends.size() + EnumChatFormatting.GREEN + "): ").green(); + if (onlineBestFriends.isEmpty()) { + bestFriendsComponent.appendText("none..."); + } else { + TreeMap<String, HyPlayerData> onlineBestFriendsSorted = new TreeMap<>(onlineBestFriends); + for (Map.Entry<String, HyPlayerData> bestFriendData : onlineBestFriendsSorted.entrySet()) { + if (bestFriendsComponent.getSiblings().size() > 0) { + bestFriendsComponent.appendSibling(new MooChatComponent(", ").green()); + } + HyPlayerData hyBestFriendData = bestFriendData.getValue(); + Pair<String, String> lastOnline = Utils.getDurationAsWords(hyBestFriendData.getLastLogin()); + bestFriendsComponent.appendSibling(new MooChatComponent(bestFriendData.getKey()).darkGreen() + .setHover(new MooChatComponent(hyBestFriendData.getLastGame()).yellow().appendFreshSibling(new MooChatComponent("Online for " + (lastOnline.second() != null ? lastOnline.second() : lastOnline.first())).white()))); + } + } + if (bestFriendsOnlineStatusWithApiErrors.size() > 0) { + String bestFriendsWithApiErrors = String.join(EnumChatFormatting.RED + ", " + EnumChatFormatting.DARK_RED, bestFriendsOnlineStatusWithApiErrors); + bestFriendsComponent.appendFreshSibling(new MooChatComponent("Failed to check " + EnumChatFormatting.DARK_RED + bestFriendsOnlineStatusWithApiErrors.size() + EnumChatFormatting.RED + " best friends' online status due to Hypixel API errors: " + EnumChatFormatting.DARK_RED + bestFriendsWithApiErrors).red()); + bestFriendsOnlineStatusWithApiErrors.clear(); + } + main.getChatHelper().sendMessage(bestFriendsComponent); + } + }); + } + } else { + new TickDelay(() -> main.getChatHelper().sendMessage(EnumChatFormatting.RED, "Couldn't check best friends online status because it has not been long enough since the last check. Next check via " + EnumChatFormatting.WHITE + "/moo online" + EnumChatFormatting.RED + " available in " + DurationFormatUtils.formatDurationWords(nextBestFriendOnlineCheck - System.currentTimeMillis(), true, true)) + , isCommandTriggered ? 1 : 100); + } + } + + public void addErroredApiRequest(String playerName) { + bestFriendsOnlineStatusWithApiErrors.add(playerName); + } + public synchronized void saveBestFriends() { try { String bestFriendsJsonZoned = GsonUtils.toJson(this.bestFriends); diff --git a/src/main/java/de/cowtipper/cowlection/handler/PlayerCache.java b/src/main/java/de/cowtipper/cowlection/handler/PlayerCache.java index 2206473..0092670 100644 --- a/src/main/java/de/cowtipper/cowlection/handler/PlayerCache.java +++ b/src/main/java/de/cowtipper/cowlection/handler/PlayerCache.java @@ -6,11 +6,10 @@ import de.cowtipper.cowlection.Cowlection; import java.util.SortedSet; import java.util.TreeSet; +@SuppressWarnings("UnstableApiUsage") public class PlayerCache { - @SuppressWarnings("UnstableApiUsage") private final EvictingQueue<String> nameCache = EvictingQueue.create(50); - @SuppressWarnings("UnstableApiUsage") - private final EvictingQueue<String> bestFriendCache = EvictingQueue.create(50); + private final EvictingQueue<String> bestFriendCache = EvictingQueue.create(100); private final Cowlection main; public PlayerCache(Cowlection main) { |