aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de/cowtipper/cowlection/handler
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/de/cowtipper/cowlection/handler')
-rw-r--r--src/main/java/de/cowtipper/cowlection/handler/DungeonCache.java52
-rw-r--r--src/main/java/de/cowtipper/cowlection/handler/FriendsHandler.java176
-rw-r--r--src/main/java/de/cowtipper/cowlection/handler/PlayerCache.java47
3 files changed, 275 insertions, 0 deletions
diff --git a/src/main/java/de/cowtipper/cowlection/handler/DungeonCache.java b/src/main/java/de/cowtipper/cowlection/handler/DungeonCache.java
new file mode 100644
index 0000000..7cef4cd
--- /dev/null
+++ b/src/main/java/de/cowtipper/cowlection/handler/DungeonCache.java
@@ -0,0 +1,52 @@
+package de.cowtipper.cowlection.handler;
+
+import de.cowtipper.cowlection.Cowlection;
+import de.cowtipper.cowlection.util.TickDelay;
+import net.minecraft.util.EnumChatFormatting;
+
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class DungeonCache {
+ private boolean isInDungeon;
+ private final Map<String, Integer> deathCounter;
+ private final Cowlection main;
+
+ public DungeonCache(Cowlection main) {
+ this.main = main;
+ deathCounter = new HashMap<>();
+ }
+
+ public void onDungeonEntered() {
+ isInDungeon = true;
+ deathCounter.clear();
+ }
+
+ public void onDungeonLeft() {
+ isInDungeon = false;
+ deathCounter.clear();
+ }
+
+ public void addDeath(String playerName) {
+ int previousPlayerDeaths = deathCounter.getOrDefault(playerName, 0);
+ deathCounter.put(playerName, previousPlayerDeaths + 1);
+
+ new TickDelay(this::sendDeathCounts, 1);
+ }
+
+ public boolean isInDungeon() {
+ return isInDungeon;
+ }
+
+ public void sendDeathCounts() {
+ if (deathCounter.isEmpty()) {
+ main.getChatHelper().sendMessage(EnumChatFormatting.GOLD, "☠ Deaths: " + EnumChatFormatting.WHITE + "none \\o/");
+ } else {
+ String deaths = deathCounter.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).map(deathEntry -> " " + EnumChatFormatting.WHITE + deathEntry.getKey() + ": " + EnumChatFormatting.LIGHT_PURPLE + deathEntry.getValue())
+ .collect(Collectors.joining("\n"));
+ main.getChatHelper().sendMessage(EnumChatFormatting.RED, "☠ " + EnumChatFormatting.BOLD + "Deaths:\n" + deaths);
+ }
+ }
+}
diff --git a/src/main/java/de/cowtipper/cowlection/handler/FriendsHandler.java b/src/main/java/de/cowtipper/cowlection/handler/FriendsHandler.java
new file mode 100644
index 0000000..ae1467a
--- /dev/null
+++ b/src/main/java/de/cowtipper/cowlection/handler/FriendsHandler.java
@@ -0,0 +1,176 @@
+package de.cowtipper.cowlection.handler;
+
+import com.google.gson.JsonParseException;
+import com.google.gson.reflect.TypeToken;
+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 io.netty.util.internal.ConcurrentSet;
+import net.minecraft.command.PlayerNotFoundException;
+import net.minecraft.event.ClickEvent;
+import net.minecraft.event.HoverEvent;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.ChatStyle;
+import net.minecraft.util.EnumChatFormatting;
+import org.apache.commons.io.FileUtils;
+
+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.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+public class FriendsHandler {
+ private static final long UPDATE_FREQUENCY_DEFAULT = TimeUnit.HOURS.toMillis(10);
+ private final Cowlection main;
+ private final Set<Friend> bestFriends = new ConcurrentSet<>();
+ private final File bestFriendsFile;
+ private final AtomicInteger bestFriendQueue = new AtomicInteger();
+
+ public FriendsHandler(Cowlection main, File friendsFile) {
+ this.main = main;
+ this.bestFriendsFile = friendsFile;
+ loadBestFriends();
+ updateBestFriends();
+ }
+
+ public boolean isBestFriend(String playerName, boolean ignoreCase) {
+ if (ignoreCase) {
+ return bestFriends.stream().map(Friend::getName).anyMatch(playerName::equalsIgnoreCase);
+ } else {
+ return bestFriends.stream().map(Friend::getName).anyMatch(playerName::equals);
+ }
+ }
+
+ public void addBestFriend(String name) {
+ if (name.isEmpty()) {
+ return;
+ }
+
+ ApiUtils.fetchFriendData(name, friend -> {
+ if (friend == null) {
+ throw new ApiContactException("Mojang", "didn't add " + name + " as a best friend.");
+ } else if (friend.equals(Friend.FRIEND_NOT_FOUND)) {
+ throw new PlayerNotFoundException("There is no player with the name " + EnumChatFormatting.DARK_RED + name + EnumChatFormatting.RED + ".");
+ } else {
+ boolean added = bestFriends.add(friend);
+ if (added) {
+ main.getChatHelper().sendMessage(EnumChatFormatting.GREEN, "Added " + EnumChatFormatting.DARK_GREEN + friend.getName() + EnumChatFormatting.GREEN + " as best friend.");
+ saveBestFriends();
+ }
+ }
+ });
+ }
+
+ public boolean removeBestFriend(String name) {
+ boolean removed = bestFriends.removeIf(friend -> friend.getName().equalsIgnoreCase(name));
+ if (removed) {
+ saveBestFriends();
+ }
+ return removed;
+ }
+
+ public Set<String> getBestFriends() {
+ return bestFriends.stream().map(Friend::getName).collect(Collectors.toCollection(TreeSet::new));
+ }
+
+ public Friend getBestFriend(String name) {
+ return bestFriends.stream().filter(friend -> friend.getName().equalsIgnoreCase(name)).findFirst().orElse(Friend.FRIEND_NOT_FOUND);
+ }
+
+ private Friend getBestFriend(UUID uuid) {
+ return bestFriends.stream().filter(friend -> friend.getUuid().equals(uuid)).findFirst().orElse(Friend.FRIEND_NOT_FOUND);
+ }
+
+ public void updateBestFriends() {
+ bestFriends.stream().filter(friend -> System.currentTimeMillis() - friend.getLastChecked() > UPDATE_FREQUENCY_DEFAULT)
+ .forEach(friend1 -> {
+ bestFriendQueue.incrementAndGet();
+ updateBestFriend(friend1, false);
+ });
+ }
+
+ public void updateBestFriend(Friend friend, boolean isCommandTriggered) {
+ ApiUtils.fetchCurrentName(friend, newName -> {
+ if (newName == null) {
+ // skipping friend, something went wrong with API request
+ if (isCommandTriggered) {
+ throw new ApiContactException("Mojang", "couldn't check " + EnumChatFormatting.DARK_RED + friend.getName() + EnumChatFormatting.RED + " (possible) new player name");
+ }
+ } else if (newName.equals(ApiUtils.UUID_NOT_FOUND)) {
+ throw new PlayerNotFoundException("How did you manage to get a unique id on your best friends list that has no name attached to it?");
+ } else if (newName.equals(friend.getName())) {
+ // name hasn't changed, only updating lastChecked timestamp
+ Friend bestFriend = getBestFriend(friend.getUuid());
+ if (!bestFriend.equals(Friend.FRIEND_NOT_FOUND)) {
+ bestFriend.setLastChecked(System.currentTimeMillis());
+ if (isCommandTriggered) {
+ throw new MooCommandException(friend.getName() + " hasn't changed his name");
+ }
+ }
+ } else {
+ // name has changed
+ main.getChatHelper().sendMessage(new ChatComponentText("Your best friend " + EnumChatFormatting.DARK_GREEN + friend.getName() + EnumChatFormatting.GREEN + " changed the name to " + EnumChatFormatting.DARK_GREEN + newName + EnumChatFormatting.GREEN + ".").setChatStyle(new ChatStyle()
+ .setColor(EnumChatFormatting.GREEN)
+ .setChatClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://namemc.com/search?q=" + newName))
+ .setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText(EnumChatFormatting.YELLOW + "View " + EnumChatFormatting.GOLD + newName + EnumChatFormatting.YELLOW + "'s name history on namemc.com")))));
+
+ Friend bestFriend = getBestFriend(friend.getUuid());
+ if (!bestFriend.equals(Friend.FRIEND_NOT_FOUND)) {
+ bestFriend.setName(newName);
+ bestFriend.setLastChecked(System.currentTimeMillis());
+ }
+ }
+ if (isCommandTriggered) {
+ saveBestFriends();
+ } else {
+ int remainingFriendsToCheck = bestFriendQueue.decrementAndGet();
+ if (remainingFriendsToCheck == 0) {
+ // we're done with checking for name changes, save updates to file!
+ saveBestFriends();
+ }
+ }
+ });
+ }
+
+ public synchronized void saveBestFriends() {
+ try {
+ String bestFriendsJsonZoned = GsonUtils.toJson(this.bestFriends);
+ FileUtils.writeStringToFile(this.bestFriendsFile, bestFriendsJsonZoned, StandardCharsets.UTF_8);
+ } catch (IOException e) {
+ main.getLogger().error("Couldn't save best friends", e);
+ }
+ }
+
+ private void loadBestFriends() {
+ try {
+ boolean createdNewFile = this.bestFriendsFile.createNewFile();
+
+ this.bestFriends.clear();
+ if (!createdNewFile) {
+ String bestFriendsData = FileUtils.readFileToString(this.bestFriendsFile, StandardCharsets.UTF_8);
+ if (bestFriendsData.length() > 0) {
+ this.bestFriends.addAll(parseJson(bestFriendsData));
+ }
+ }
+ } catch (IOException e) {
+ main.getLogger().error("Couldn't read best friends file " + this.bestFriendsFile, e);
+ } catch (JsonParseException e) {
+ main.getLogger().error("Couldn't parse best friends file " + this.bestFriendsFile, e);
+ }
+ }
+
+ private Set<Friend> parseJson(String bestFriendsData) {
+ Type collectionType = new TypeToken<Set<Friend>>() {
+ }.getType();
+ return GsonUtils.fromJson(bestFriendsData, collectionType);
+ }
+}
diff --git a/src/main/java/de/cowtipper/cowlection/handler/PlayerCache.java b/src/main/java/de/cowtipper/cowlection/handler/PlayerCache.java
new file mode 100644
index 0000000..2206473
--- /dev/null
+++ b/src/main/java/de/cowtipper/cowlection/handler/PlayerCache.java
@@ -0,0 +1,47 @@
+package de.cowtipper.cowlection.handler;
+
+import com.google.common.collect.EvictingQueue;
+import de.cowtipper.cowlection.Cowlection;
+
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+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 Cowlection main;
+
+ public PlayerCache(Cowlection main) {
+ this.main = main;
+ }
+
+ public void add(String name) {
+ // remove old entry (if exists) to 'push' name to the end of the queue
+ nameCache.remove(name);
+ nameCache.add(name);
+ }
+
+ public void addBestFriend(String name) {
+ // remove old entry (if exists) to 'push' name to the end of the queue
+ bestFriendCache.remove(name);
+ bestFriendCache.add(name);
+ }
+
+ public void removeBestFriend(String name) {
+ bestFriendCache.remove(name);
+ }
+
+ public SortedSet<String> getAllNamesSorted() {
+ SortedSet<String> nameList = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
+ nameList.addAll(bestFriendCache);
+ nameList.addAll(nameCache);
+ return nameList;
+ }
+
+ public void clearAllCaches() {
+ nameCache.clear();
+ bestFriendCache.clear();
+ }
+}