aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/kr
diff options
context:
space:
mode:
authorsyeyoung <cyoung06@naver.com>2021-11-27 23:19:16 +0900
committersyeyoung <cyoung06@naver.com>2021-11-27 23:19:16 +0900
commitd239ae4d4748fc4867ab45a5cc7d42bfb5ac547c (patch)
tree39118080fafa68e896c10cee03f8c1cda9f0defd /src/main/java/kr
parent7c22f439db227552d88d4df20e0cce6da947a2d0 (diff)
downloadSkyblock-Dungeons-Guide-d239ae4d4748fc4867ab45a5cc7d42bfb5ac547c.tar.gz
Skyblock-Dungeons-Guide-d239ae4d4748fc4867ab45a5cc7d42bfb5ac547c.tar.bz2
Skyblock-Dungeons-Guide-d239ae4d4748fc4867ab45a5cc7d42bfb5ac547c.zip
- Deadlock on ApiFetchur (Waits until lilyweight data and lilyweight data fetcher waits for other tasks to finish)
- New PartyManager - ChatProcessor now manages all automatic chat messages and msot chat parsing - PartyFinderSetting now contains option to leave party - Log StompPayload when debug enabled
Diffstat (limited to 'src/main/java/kr')
-rwxr-xr-xsrc/main/java/kr/syeyoung/dungeonsguide/DungeonsGuide.java5
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/chat/ChatProcessResult.java31
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/chat/ChatProcessor.java115
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/chat/ChatSubscriber.java26
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/chat/PartyContext.java89
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/chat/PartyManager.java581
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/commands/CommandDungeonsGuide.java32
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/features/FeatureRegistry.java2
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/FeaturePartyList.java97
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/ApiFetchur.java29
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/PanelPartyFinder.java5
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/PanelPartyFinderSettings.java17
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/FeatureViewPlayerOnJoin.java37
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/party/PartyManager.java451
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/rpc/RichPresenceManager.java18
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/stomp/StompPayload.java3
16 files changed, 1027 insertions, 511 deletions
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/DungeonsGuide.java b/src/main/java/kr/syeyoung/dungeonsguide/DungeonsGuide.java
index 2a0d73e0..e8f3ada5 100755
--- a/src/main/java/kr/syeyoung/dungeonsguide/DungeonsGuide.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/DungeonsGuide.java
@@ -19,6 +19,8 @@
package kr.syeyoung.dungeonsguide;
import com.google.common.collect.Sets;
+import kr.syeyoung.dungeonsguide.chat.ChatProcessor;
+import kr.syeyoung.dungeonsguide.chat.PartyManager;
import kr.syeyoung.dungeonsguide.commands.*;
import kr.syeyoung.dungeonsguide.config.Config;
import kr.syeyoung.dungeonsguide.cosmetics.CosmeticsManager;
@@ -28,7 +30,6 @@ import kr.syeyoung.dungeonsguide.eventlistener.FeatureListener;
import kr.syeyoung.dungeonsguide.eventlistener.PacketListener;
import kr.syeyoung.dungeonsguide.events.StompConnectedEvent;
import kr.syeyoung.dungeonsguide.features.FeatureRegistry;
-import kr.syeyoung.dungeonsguide.party.PartyManager;
import kr.syeyoung.dungeonsguide.resources.DGTexturePack;
import kr.syeyoung.dungeonsguide.rpc.RichPresenceManager;
import kr.syeyoung.dungeonsguide.stomp.CloseListener;
@@ -119,6 +120,8 @@ public class DungeonsGuide implements DGInterface, CloseListener {
MinecraftForge.EVENT_BUS.register(new PacketListener());
MinecraftForge.EVENT_BUS.register(new Keybinds());
+// MinecraftForge.EVENT_BUS.register(PartyManager.INSTANCE);
+ MinecraftForge.EVENT_BUS.register(ChatProcessor.INSTANCE);
MinecraftForge.EVENT_BUS.register(PartyManager.INSTANCE);
MinecraftForge.EVENT_BUS.register(StaticResourceCache.INSTANCE);
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/chat/ChatProcessResult.java b/src/main/java/kr/syeyoung/dungeonsguide/chat/ChatProcessResult.java
new file mode 100644
index 00000000..94bafa95
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/chat/ChatProcessResult.java
@@ -0,0 +1,31 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.chat;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+@Getter
+public enum ChatProcessResult {
+ NONE(false, false), REMOVE_LISTENER(true, false), REMOVE_LISTENER_AND_CHAT(true, true), REMOVE_CHAT(false, true);
+
+ private boolean removeListener;
+ private boolean removeChat;
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/chat/ChatProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/chat/ChatProcessor.java
new file mode 100644
index 00000000..5fc666e2
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/chat/ChatProcessor.java
@@ -0,0 +1,115 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.chat;
+
+import kr.syeyoung.dungeonsguide.DungeonsGuide;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiNewChat;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.Tuple;
+import net.minecraftforge.client.event.ClientChatReceivedEvent;
+import net.minecraftforge.fml.common.eventhandler.Event;
+import net.minecraftforge.fml.common.eventhandler.EventPriority;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.simple.SimpleLogger;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+public class ChatProcessor {
+ public static final ChatProcessor INSTANCE = new ChatProcessor();
+
+ private static final Logger logger = LogManager.getLogger();
+ private ChatProcessor() {
+ Logger l = LogManager.getLogger(GuiNewChat.class);
+ if (l instanceof SimpleLogger) {
+ ((SimpleLogger) l).setLevel(Level.OFF);
+ } else if (l instanceof org.apache.logging.log4j.core.Logger) {
+ ((org.apache.logging.log4j.core.Logger) l).setLevel(Level.OFF);
+ }
+ }
+
+ private Queue<ChatSubscriber> chatSubscriberQueue = new ConcurrentLinkedQueue<>();
+ private Queue<Tuple<String, Runnable>> chatQueue = new ConcurrentLinkedQueue<>();
+
+ public void subscribe(ChatSubscriber chatSubscribed) {
+ chatSubscriberQueue.add(chatSubscribed);
+ }
+ public void addToChatQueue(String chat, Runnable onSend, boolean noDupe) {
+ if (noDupe && chatQueue.stream().anyMatch(a -> a.getFirst().trim().equalsIgnoreCase(chat.trim()))) return;
+ chatQueue.add(new Tuple<>(chat, onSend));
+ }
+
+
+ private long minimumNext = 0;
+
+ @SubscribeEvent
+ public void onTick(TickEvent.ClientTickEvent clientTickEvent) {
+ try {
+ if (clientTickEvent.phase == TickEvent.Phase.START && Minecraft.getMinecraft().thePlayer != null && minimumNext < System.currentTimeMillis()) {
+ if (!chatQueue.isEmpty()) {
+ Tuple<String, Runnable> tuple = chatQueue.poll();
+ Minecraft.getMinecraft().thePlayer.sendChatMessage(tuple.getFirst());
+ if (tuple.getSecond() != null)
+ tuple.getSecond().run();
+ minimumNext = System.currentTimeMillis() + 200;
+ DungeonsGuide.sendDebugChat(new ChatComponentText("Sending " + tuple.getFirst() + " Secretly"));
+ }
+ }
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ @SubscribeEvent(priority = EventPriority.HIGHEST, receiveCanceled = true)
+ public void onMessage(ClientChatReceivedEvent chatReceivedEvent) {
+ if (chatReceivedEvent.type == 2) return;
+ String txt = chatReceivedEvent.message.getFormattedText();
+ logger.log(Level.INFO, "[CHAT] "+txt);
+
+ int processed = 0;
+ int listenened = 0;
+ Map<String, Object> context = new HashMap<>();
+ Iterator<ChatSubscriber> it = chatSubscriberQueue.iterator();
+ while (it.hasNext()) {
+ ChatSubscriber chatSubscribed = it.next();
+ context.put("removed", processed);
+ context.put("onceListenered", listenened);
+ ChatProcessResult chatProcessResult = chatSubscribed.process(txt, context);
+ if (chatProcessResult.isRemoveChat()) processed++;
+ if (chatProcessResult.isRemoveListener()) listenened++;
+
+ if (chatProcessResult.isRemoveChat()) chatReceivedEvent.setResult(Event.Result.DENY);
+ if (chatProcessResult.isRemoveListener()) it.remove();
+ }
+ }
+
+
+ @SubscribeEvent(priority = EventPriority.LOWEST)
+ public void cancelMessage(ClientChatReceivedEvent chatReceivedEvent) {
+ if (chatReceivedEvent.getResult() == Event.Result.DENY)
+ chatReceivedEvent.setCanceled(true);
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/chat/ChatSubscriber.java b/src/main/java/kr/syeyoung/dungeonsguide/chat/ChatSubscriber.java
new file mode 100644
index 00000000..72879eb0
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/chat/ChatSubscriber.java
@@ -0,0 +1,26 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.chat;
+
+import java.util.Map;
+
+@FunctionalInterface
+public interface ChatSubscriber {
+ ChatProcessResult process(String txt, Map<String, Object> context);
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/chat/PartyContext.java b/src/main/java/kr/syeyoung/dungeonsguide/chat/PartyContext.java
new file mode 100644
index 00000000..87d1a264
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/chat/PartyContext.java
@@ -0,0 +1,89 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.chat;
+
+import lombok.Data;
+import net.minecraft.client.Minecraft;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TreeSet;
+
+
+@Data
+public class PartyContext {
+ private String partyID;
+
+ private String partyOwner;
+ private Set<String> partyModerator; private boolean isModeratorComplete;
+ private Set<String> partyMember; private boolean isMemberComplete;
+
+ private Set<String> partyRawMembers = new HashSet<>(); private boolean isRawMemberComplete;
+
+ private Boolean allInvite;
+
+ private boolean partyExistHypixel = true;
+
+ public void setPartyOwner(String partyOwner) {
+ this.partyOwner = partyOwner;
+ if (partyMember != null) partyMember.remove(partyOwner);
+ if (partyModerator != null) partyModerator.remove(partyOwner);
+ addRawMember(partyOwner);
+ }
+ public void addPartyModerator(String partyModerator) {
+ if (partyModerator.equalsIgnoreCase(partyOwner)) partyOwner = null;
+ if (partyMember != null) partyMember.remove(partyModerator);
+
+ if (this.partyModerator == null) this.partyModerator = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
+ this.partyModerator.add(partyModerator);
+ addRawMember(partyModerator);
+ }
+ public void addPartyMember(String partyMember) {
+ if (partyMember.equalsIgnoreCase(partyOwner)) partyOwner = null;
+ if (partyModerator != null) partyModerator.remove(partyMember);
+
+ if (this.partyMember == null) this.partyMember = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
+ this.partyMember.add(partyMember);
+ addRawMember(partyMember);
+ }
+ public void addRawMember(String partyMember){
+ partyRawMembers.add(partyMember);
+ }
+ public void removeFromParty(String username) {
+ if (username.equalsIgnoreCase(partyOwner)) {
+ partyOwner = null;
+ }
+ if (partyModerator != null) partyModerator.remove(username);
+ if (partyMember != null) partyMember.remove(username);
+ partyRawMembers.remove(username);
+ }
+
+ public boolean hasModerator(String username) {
+ return partyModerator != null && partyModerator.contains(username);
+ }
+ public boolean hasMember(String username) {
+ return partyMember != null && partyMember.contains(username);
+ }
+ public boolean hasLeader(String username) {
+ return username.equalsIgnoreCase(partyOwner);
+ }
+ public boolean isSelfSolo() {
+ return hasLeader(Minecraft.getMinecraft().getSession().getUsername()) && getPartyRawMembers().size() == 1;
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/chat/PartyManager.java b/src/main/java/kr/syeyoung/dungeonsguide/chat/PartyManager.java
new file mode 100644
index 00000000..2a2207f0
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/chat/PartyManager.java
@@ -0,0 +1,581 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.chat;
+
+import kr.syeyoung.dungeonsguide.DungeonsGuide;
+import kr.syeyoung.dungeonsguide.events.HypixelJoinedEvent;
+import kr.syeyoung.dungeonsguide.events.StompConnectedEvent;
+import kr.syeyoung.dungeonsguide.stomp.*;
+import kr.syeyoung.dungeonsguide.utils.TextUtils;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.client.Minecraft;
+import net.minecraft.util.ChatComponentText;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.security.SecureRandom;
+import java.util.*;
+import java.util.function.Consumer;
+
+public class PartyManager implements StompMessageHandler {
+ public static final PartyManager INSTANCE = new PartyManager();
+ @Getter
+ private PartyContext partyContext;
+
+ public PartyContext getPartyContext(boolean createIfNeeded) {
+ PartyContext pc = partyContext == null && createIfNeeded ? partyContext = new PartyContext() : partyContext;
+ if (createIfNeeded)
+ pc.addRawMember(Minecraft.getMinecraft().getSession().getUsername());
+ return pc;
+ }
+
+ @Getter
+ @Setter
+ private int maxParty = 5;
+ @Getter
+ private String askToJoinSecret = null;
+
+ private static final SecureRandom random = new SecureRandom();
+ private static final String validChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
+
+
+ private Set<Consumer<PartyContext>> partyBuiltCallback = new HashSet<>();
+
+ public PartyManager() {
+ ChatProcessor cp = ChatProcessor.INSTANCE;
+ // Not in Party
+ cp.subscribe((str, a) -> {
+ if (str.equals("§cYou are not currently in a party.§r")
+ || str.equals("§eYou left the party.§r")
+ || str.equals("§cYou must be in a party to join the party channel!§r")
+ || str.equals("§cThe party was disbanded because all invites expired and the party was empty§r")
+ || str.equals("§cYou are not in a party and were moved to the ALL channel.§r")
+ || str.startsWith("§cThe party was disbanded")
+ || str.endsWith("§ehas disbanded the party!§r")
+ || str.endsWith("§cYou are not in a party")) {
+ leaveParty();
+
+ for (Consumer<PartyContext> partyContextConsumer : partyBuiltCallback) {
+ try {
+ partyContextConsumer.accept(null);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ partyBuiltCallback.clear();
+ a.put("type", "notinparty");
+ }
+ return ChatProcessResult.NONE;
+ });
+ // All invite
+ cp.subscribe((str, a) -> {
+ if (str.endsWith("§aenabled All Invite§r")) {
+ getPartyContext(true).setAllInvite(true);
+ a.put("type", "allinvite_on");
+ } else if (str.endsWith("§cdisabled All Invite§r")
+ || str.equals("§cYou are not allowed to invite players.§r")) {
+ getPartyContext(true).setAllInvite(false);
+ a.put("type", "allinvite_off");
+ }
+ return ChatProcessResult.NONE;
+ });
+ // Member building
+ cp.subscribe(new ChatSubscriber() {
+ boolean memberExpected;
+ PartyContext partyContext = new PartyContext();
+ @Override
+ public ChatProcessResult process(String txt, Map<String, Object> context) {
+ if (txt.startsWith("§6Party Members ")) {
+ memberExpected = true;
+ partyContext = new PartyContext();
+ partyContext.setPartyModerator(new TreeSet<>(String.CASE_INSENSITIVE_ORDER));
+ partyContext.setPartyMember(new TreeSet<>(String.CASE_INSENSITIVE_ORDER));
+ context.put("type", "member_start");
+ } else if (txt.startsWith("§eParty ") && txt.contains(":")){
+ String role = txt.split(":")[0];
+ String playerNames = TextUtils.stripColor(txt.split(":")[1]);
+ for (String s : playerNames.split(" ")) {
+ if (s.isEmpty()) continue;
+ if (s.equals("●")) continue;
+ if (s.startsWith("[")) continue;
+ partyContext.addRawMember(s);
+ if (role.contains("Moder")) partyContext.addPartyModerator(s);
+ if (role.contains("Member")) partyContext.addPartyMember(s);
+ if (role.contains("Leader")) partyContext.setPartyOwner(s);
+ }
+ if (role.contains("Moder")) {
+ partyContext.setModeratorComplete(true);
+ context.put("type", "member_moder");
+ }
+ if (role.contains("Member")) {
+ partyContext.setMemberComplete(true);
+ context.put("type", "member_member");
+ }
+ if (role.contains("Leader")) {
+ context.put("type", "member_leader");
+ }
+ } else if (txt.equals("§9§m-----------------------------§r")) {
+ if (memberExpected) {
+ PartyContext old = getPartyContext(true);
+ old.setPartyOwner(partyContext.getPartyOwner());
+ old.setPartyModerator(partyContext.getPartyModerator());
+ old.setPartyMember(partyContext.getPartyMember());
+ old.setPartyRawMembers(new TreeSet<>(String.CASE_INSENSITIVE_ORDER));
+ old.getPartyRawMembers().addAll(old.getPartyMember());
+ old.getPartyRawMembers().addAll(old.getPartyModerator());
+ old.getPartyRawMembers().add(old.getPartyOwner());
+ old.setModeratorComplete(true); old.setMemberComplete(true);
+ old.setRawMemberComplete(true);
+ old.setPartyExistHypixel(true);
+
+ memberExpected = false;
+ context.put("type", "member_end");
+
+ for (Consumer<PartyContext> partyContextConsumer : partyBuiltCallback) {
+ try {
+ partyContextConsumer.accept(partyContext);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ partyBuiltCallback.clear();
+
+ if (old.getPartyID() == null) {
+ joinedParty();
+ }
+ }
+ }
+ return ChatProcessResult.NONE;
+ }
+ });
+ // Player party join / leave
+ cp.subscribe((str ,a) -> {
+ if (str.endsWith("§ejoined the party.§r")) {
+ String username = null;
+ for (String s : TextUtils.stripColor(str).split(" ")) {
+ if (s.startsWith("[")) continue;
+ username = s;
+ break;
+ }
+ if (username != null) {
+ getPartyContext(true).addPartyMember(username);
+ }
+ a.put("type", "party_join");
+ } else if (str.endsWith("§ehas been removed from the party.§r")
+ || str.endsWith("§ehas left the party.§r")) {
+ String username = null;
+ for (String s : TextUtils.stripColor(str).split(" ")) {
+ if (s.startsWith("[")) continue;
+ username = s;
+ break;
+ }
+ if (username != null && partyContext != null) {
+ getPartyContext().removeFromParty(username);
+ }
+ a.put("type", "party_leave");
+ } else if (str.endsWith(" They have §r§c60 §r§eseconds to accept.§r")) {
+ String[] messageSplit = TextUtils.stripColor(str).split(" ");
+ String inviter = null;
+ for (String s : messageSplit) {
+ if (s.startsWith("[")) continue;
+ inviter = s;
+ break;
+ }
+ if (inviter != null && partyContext != null) {
+ if (getPartyContext().hasMember(inviter)) {
+ getPartyContext().setAllInvite(true);
+ }
+ }
+ getPartyContext(true).setPartyExistHypixel(true);
+ a.put("type", "party_invite_exist");
+ } else if (str.equals("§cCouldn't find a player with that name!§r") || str.equals("§cYou cannot invite that player since they're not online.")) {
+ a.put("type", "party_invite_noexist");
+ String username = Minecraft.getMinecraft().getSession().getUsername();
+ if (partyContext != null && getPartyContext().hasMember(username)) {
+ getPartyContext().setAllInvite(true);
+ }
+ }
+ return ChatProcessResult.NONE;
+ });
+ // Promotion
+ cp.subscribe((str, a) -> {
+ if (str.startsWith("§eThe party was transferred to ")) {
+ // §eThe party was transferred to §r§b[MVP§r§f+§r§b] apotato321 §r§eby §r§a[VIP§r§6+§r§a] syeyoung§r
+ String[] messageSplit = TextUtils.stripColor(str.substring(31)).split(" ");
+ String newLeader = null;
+ for (String s : messageSplit) {
+ if (s.startsWith("[")) continue;
+ newLeader = s;
+ break;
+ }
+ String oldLeader = messageSplit[messageSplit.length-1];
+
+ if (oldLeader != null && newLeader != null ) {
+ getPartyContext(true).setPartyOwner(newLeader);
+ getPartyContext(true).addPartyModerator(oldLeader);
+ }
+ a.put("type", "party_transfer");
+ } else if (str.endsWith("§eto Party Leader§r")) {
+ // §a[VIP§r§6+§r§a] syeyoung§r§e has promoted §r§b[MVP§r§f+§r§b] apotato321 §r§eto Party Leader§r
+ String[] messageSplit = TextUtils.stripColor(str).split(" ");
+ String oldLeader = null;
+ for (String s : messageSplit) {
+ if (s.startsWith("[")) continue;
+ oldLeader = s;
+ break;
+ }
+ messageSplit = TextUtils.stripColor(str.substring(str.indexOf("has promoted") + 13)).split(" ");
+ String newLeader = null;
+ for (String s : messageSplit) {
+ if (s.startsWith("[")) continue;
+ newLeader = s;
+ break;
+ }
+
+ if (oldLeader != null && newLeader != null) {
+ getPartyContext(true).setPartyOwner(newLeader);
+ getPartyContext(true).addPartyModerator(oldLeader);
+ }
+ a.put("type", "party_transfer");
+ } else if (str.endsWith("§r§eto Party Moderator§r")) {
+ // §b[MVP§r§f+§r§b] apotato321§r§e has promoted §r§a[VIP§r§6+§r§a] syeyoung §r§eto Party Moderator§r
+ String[] messageSplit = TextUtils.stripColor(str).split(" ");
+ String oldLeader = null;
+ for (String s : messageSplit) {
+ if (s.startsWith("[")) continue;
+ oldLeader = s;
+ break;
+ }
+ messageSplit = TextUtils.stripColor(str.substring(str.indexOf("has promoted") + 13)).split(" ");
+ String newModerator = null;
+ for (String s : messageSplit) {
+ if (s.startsWith("[")) continue;
+ newModerator = s;
+ break;
+ }
+
+ if (oldLeader != null && newModerator != null) {
+ getPartyContext(true).setPartyOwner(oldLeader);
+ getPartyContext(true).addPartyModerator(newModerator);
+ }
+ a.put("type", "party_promotion");
+ } else if (str.endsWith("§r§eto Party Member§r")) {
+ String[] messageSplit = TextUtils.stripColor(str).split(" ");
+ String oldLeader = null;
+ for (String s : messageSplit) {
+ if (s.startsWith("[")) continue;
+ oldLeader = s;
+ break;
+ }
+ messageSplit = TextUtils.stripColor(str.substring(str.indexOf("has demoted") + 12)).split(" ");
+ String newMember = null;
+ for (String s : messageSplit) {
+ if (s.startsWith("[")) continue;
+ newMember = s;
+ break;
+ }
+
+ if (oldLeader != null && newMember != null) {
+ getPartyContext(true).setPartyOwner(oldLeader);
+ getPartyContext(true).addPartyMember(newMember);
+ }
+ a.put("type", "party_demotion");
+ }
+ return ChatProcessResult.NONE;
+ });
+ // Player Join
+ cp.subscribe(new ChatSubscriber() {
+ boolean joined;
+ @Override
+ public ChatProcessResult process(String str, Map<String, Object> context) {
+ if (str.startsWith("§eYou have joined ")) {
+ String[] messageSplit = TextUtils.stripColor(str.substring(18)).split(" ");
+ String leader = null;
+ for (String s : messageSplit) {
+ if (s.startsWith("[")) continue;
+ leader = s;
+ break;
+ }
+ leader = leader.substring(0, leader.length()-2); // remove 's
+ partyContext = new PartyContext();
+ getPartyContext().setPartyOwner(leader);
+ getPartyContext().addPartyMember(Minecraft.getMinecraft().getSession().getUsername());
+ context.put("type", "party_selfjoin_leader");
+ joined= true;
+ } else if (str.startsWith("§eYou'll be partying with: ")) {
+ String[] players = TextUtils.stripColor(str.substring(27)).split(" ");
+ for (String player : players) {
+ if (player.startsWith("[")) continue;
+ getPartyContext().addRawMember(player);
+ }
+ context.put("type", "party_selfjoin_players");
+ } else if (str.equals("§9§m-----------------------------§r") && joined) {
+ joined = false;
+ getPartyContext().setRawMemberComplete(true);
+ joinedParty();
+ }
+ return ChatProcessResult.NONE;
+ }});
+ // Player Join Dungon
+ cp.subscribe((str, a)-> {
+ if (str.contains("§r§ejoined the dungeon group! (§r§b")) {
+ String username = TextUtils.stripColor(str).split(" ")[3];
+ if (username.equalsIgnoreCase(Minecraft.getMinecraft().getSession().getUsername())) {
+ partyContext = new PartyContext();
+ requestPartyList((str2) -> {});
+ } else {
+ getPartyContext(true).setMemberComplete(false);
+ requestPartyList((str2) -> {});
+ }
+ }
+ return ChatProcessResult.NONE;
+ });
+ }
+
+ public void toggleAllowAskToJoin() {
+ if (canInvite()) {
+ if (askToJoinSecret != null) askToJoinSecret = null;
+ else {
+ updateAskToJoin();
+ }
+ }
+ }
+
+ public void updateAskToJoin() {
+ StringBuilder secretBuilder = new StringBuilder();
+ for (int i = 0; i < 20; i++) {
+ secretBuilder.append(validChars.charAt(random.nextInt(validChars.length())));
+ }
+ askToJoinSecret = secretBuilder.toString();
+
+ StompInterface stompInterface = DungeonsGuide.getDungeonsGuide().getStompConnection();
+ stompInterface.send(new StompPayload().payload(new JSONObject().put("secret", askToJoinSecret).toString()).header("destination", "/app/party.setjoinsecret"));
+ }
+
+ public static ChatSubscriber dashShredder() {
+ return (str, a) -> (int)a.get("removed") == 0 && str.equals("§9§m-----------------------------§r") ? ChatProcessResult.REMOVE_LISTENER_AND_CHAT : ChatProcessResult.NONE;
+ }
+
+ public static ChatSubscriber typeShredder(boolean end, String... types) {
+ return (str, a) -> (int)a.get("removed") == 0 &&Arrays.stream(types).anyMatch(s -> s.equals(a.getOrDefault("type", null))) ? (end ? ChatProcessResult.REMOVE_LISTENER_AND_CHAT : ChatProcessResult.REMOVE_CHAT) : ChatProcessResult.NONE;
+ }
+
+ public static ChatSubscriber combinedShredder(ChatSubscriber... chatSubscribers) {
+ return (str, a) -> {
+ boolean removeChat = false;
+ boolean removeListener = false;
+ for (ChatSubscriber chatSubscriber : chatSubscribers) {
+ ChatProcessResult chatProcessResult = chatSubscriber.process(str, a);
+ if (chatProcessResult.isRemoveChat()) removeChat = true;
+ if (chatProcessResult.isRemoveListener()) removeListener = true;
+ }
+ return (removeChat && removeListener) ? ChatProcessResult.REMOVE_LISTENER_AND_CHAT : (removeChat ? ChatProcessResult.REMOVE_CHAT : (removeListener ? ChatProcessResult.REMOVE_LISTENER : ChatProcessResult.NONE));
+ };
+ }
+
+ @SubscribeEvent
+ public void onHypixelJoin(HypixelJoinedEvent skyblockJoinedEvent) {
+ partyContext = null;
+ requestPartyList((a) -> {
+ if (a == null) return;
+ if (isLeader() || isModerator()) return;
+ if (a.getAllInvite() != null) return;
+ requestAllInvite();
+ });
+ }
+
+ private void leaveParty() {
+ if (partyContext != null) {
+ getPartyContext().setPartyExistHypixel(false);
+ if (getPartyContext().isSelfSolo()) return;
+ if (getPartyContext().getPartyID() != null) {
+ JSONObject object = new JSONObject();
+ object.put("partyid", getPartyContext().getPartyID());
+ StompInterface stompInterface = DungeonsGuide.getDungeonsGuide().getStompConnection();
+ stompInterface.send(new StompPayload().payload(object.toString()).header("destination", "/app/party.leave"));
+ }
+ }
+
+ partyContext = new PartyContext();
+ playerInvAntiSpam.clear();
+
+ getPartyContext().setPartyExistHypixel(false);
+ getPartyContext().setPartyOwner(Minecraft.getMinecraft().getSession().getUsername());
+ getPartyContext().setPartyModerator(new TreeSet<>(String.CASE_INSENSITIVE_ORDER)); getPartyContext().setMemberComplete(true);
+ getPartyContext().setPartyMember(new TreeSet<>(String.CASE_INSENSITIVE_ORDER)); getPartyContext().setModeratorComplete(true);
+ getPartyContext().setAllInvite(false);
+ joinedParty();
+ }
+ private void joinedParty() {
+ JSONArray jsonArray = new JSONArray();
+ for (String member : getPartyContext().getPartyRawMembers()) {
+ jsonArray.put(member);
+ }
+ JSONObject object = new JSONObject();
+ object.put("members", jsonArray);
+ StompInterface stompInterface = DungeonsGuide.getDungeonsGuide().getStompConnection();
+ stompInterface.send(new StompPayload().payload(object.toString()).header("destination", "/app/party.join"));
+
+ getPartyContext().setPartyID("!@#!@#!@#..........FETCHING..........$!@$!@$!@$"+UUID.randomUUID().toString());
+ }
+
+ public boolean isLeader() {
+ return partyContext != null && getPartyContext().hasLeader(Minecraft.getMinecraft().getSession().getUsername()); // "getUsername"
+ }
+ public boolean isModerator() {
+ return partyContext != null && getPartyContext().hasModerator(Minecraft.getMinecraft().getSession().getUsername());
+ }
+ public boolean canInvite() {
+ return isLeader() || isModerator() || (partyContext != null && getPartyContext().getAllInvite() != null && getPartyContext().getAllInvite());
+ }
+
+ private boolean requested = false;
+ public void requestPartyList(Consumer<PartyContext> onPartyCallback) {
+ if (requested) {
+ partyBuiltCallback.add(onPartyCallback);
+ return;
+ }
+ requested = true;
+
+ ChatProcessor.INSTANCE.addToChatQueue("/pl", () -> {
+ ChatProcessor.INSTANCE.subscribe(dashShredder());
+ ChatProcessor.INSTANCE.subscribe(combinedShredder(typeShredder(true, "member_end"), dashShredder(), typeShredder(false,"notinparty", "member_start", "member_moder", "member_leader", "member_member")));
+ }, true);
+ partyBuiltCallback.add(onPartyCallback);
+ partyBuiltCallback.add(pc -> requested=false);
+ }
+
+ public void requestAllInvite() {
+ if (isLeader() || isModerator()) return;
+ if (partyContext != null && getPartyContext().getAllInvite() != null) return;
+
+ ChatProcessor.INSTANCE.addToChatQueue("/p invite -", () -> {
+ ChatProcessor.INSTANCE.subscribe(dashShredder());
+ ChatProcessor.INSTANCE.subscribe(typeShredder(true, "notinparty", "allinvite_off", "party_invite_noexist"));
+ ChatProcessor.INSTANCE.subscribe(dashShredder());
+ }, true);
+ }
+
+ private Map<String, Long> playerInvAntiSpam = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+
+ @Override
+ public void handle(StompInterface stompInterface, StompPayload stompPayload) {
+ JSONObject object = new JSONObject(stompPayload.payload());
+ if ("/user/queue/party.check".equals(stompPayload.headers().get("destination"))) {
+ String playerName = object.getString("player");
+ String token = object.getString("token");
+ if (partyContext == null) {
+ requestPartyList((pc) -> {
+ boolean contains = pc.getPartyRawMembers().contains(playerName);
+ if (!contains) {
+ DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().payload(new JSONObject().put("status", "failure").put("token", token).toString()).header("destination", "/app/party.check.resp"));
+ } else {
+ DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().payload(new JSONObject().put("status", "success").put("token", token).toString()).header("destination", "/app/party.check.resp"));
+ }
+ });
+ } else {
+ if (getPartyContext().getPartyRawMembers().contains(playerName)) {
+ DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().payload(new JSONObject().put("status", "success").put("token", token).toString()).header("destination", "/app/party.check.resp"));
+ } else if (getPartyContext().isMemberComplete() && getPartyContext().isModeratorComplete() && getPartyContext().getPartyOwner() != null) {
+ DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().payload(new JSONObject().put("status", "failure").put("token", token).toString()).header("destination", "/app/party.check.resp"));
+ } else {
+ requestPartyList((pc) -> {
+ boolean contains = pc.getPartyRawMembers().contains(playerName);
+ if (!contains) {
+ DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().payload(new JSONObject().put("status", "failure").put("token", token).toString()).header("destination", "/app/party.check.resp"));
+ } else {
+ DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().payload(new JSONObject().put("status", "success").put("token", token).toString()).header("destination", "/app/party.check.resp"));
+ }
+ });
+ }
+ }
+ } else if ("/user/queue/party.broadcast".equals(stompPayload.headers().get("destination"))) {
+ try {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: Message Broadcasted from player:: \n" + new JSONObject(stompPayload.payload()).getString("payload")));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ } else if ("/user/queue/party.join".equals(stompPayload.headers().get("destination"))) {
+ String playerName = object.getString("player");
+ String secret = object.getString("secret");
+ if (secret.equals(askToJoinSecret) && partyContext != null && getPartyContext().getPartyRawMembers().size() < maxParty && playerInvAntiSpam.getOrDefault(playerName, 0L) < System.currentTimeMillis() - 5000) {
+ playerInvAntiSpam.put(playerName, System.currentTimeMillis());
+ ChatProcessor.INSTANCE.addToChatQueue("/p invite "+playerName,() -> {}, true);
+ }
+ } else if ("/user/queue/party.askedtojoin.resp".equals(stompPayload.headers().get("destination"))) {
+ String invFrom = object.getString("username");
+ String token2 = object.getString("token");
+ if (!token2.equals(lastToken)) return;
+ lastToken = null;
+ ChatProcessor.INSTANCE.addToChatQueue("/p accept "+invFrom, () -> {}, true);
+ long end = System.currentTimeMillis() + 3000;
+ ChatProcessor.INSTANCE.subscribe((str, a) -> {
+ if (!str.contains("§r§ehas invited you to join their party!")) return System.currentTimeMillis() > end ? ChatProcessResult.REMOVE_LISTENER : ChatProcessResult.NONE;
+ String[] messageSplit = TextUtils.stripColor(str).split(" ");
+ String inviter = null;
+ for (String s : messageSplit) {
+ if (s.startsWith("[")) continue;
+ if (s.startsWith("-")) continue;;
+ inviter = s;
+ break;
+ }
+ if (invFrom.equalsIgnoreCase(inviter)) {
+ ChatProcessor.INSTANCE.addToChatQueue("/p accept "+invFrom, () -> {}, true);
+ }
+ return ChatProcessResult.NONE;
+ });
+ } else {
+ String str = object.getString("status");
+ if ("success".equals(str) && partyContext != null) {
+ getPartyContext().setPartyID(object.getString("partyId"));
+ if (askToJoinSecret != null) {
+ updateAskToJoin();
+ }
+ } else if (partyContext != null){
+ getPartyContext().setPartyID(null);
+ }
+ }
+ }
+
+ @SubscribeEvent
+ public void stompConnect(StompConnectedEvent stompConnectedEvent) {
+ stompConnectedEvent.getStompInterface().subscribe(StompSubscription.builder()
+ .stompMessageHandler(this).ackMode(StompSubscription.AckMode.AUTO).destination("/user/queue/party.resp").build());
+ stompConnectedEvent.getStompInterface().subscribe(StompSubscription.builder()
+ .stompMessageHandler(this).ackMode(StompSubscription.AckMode.AUTO).destination("/user/queue/party.check").build());
+ stompConnectedEvent.getStompInterface().subscribe(StompSubscription.builder()
+ .stompMessageHandler(this).ackMode(StompSubscription.AckMode.AUTO).destination("/user/queue/party.broadcast").build());
+ stompConnectedEvent.getStompInterface().subscribe(StompSubscription.builder()
+ .stompMessageHandler(this).ackMode(StompSubscription.AckMode.AUTO).destination("/user/queue/party.join").build());
+ stompConnectedEvent.getStompInterface().subscribe(StompSubscription.builder()
+ .stompMessageHandler(this).ackMode(StompSubscription.AckMode.AUTO).destination("/user/queue/party.askedtojoin.resp").build());
+ }
+
+ private String lastToken;
+ public void joinWithToken(String secret) {
+ lastToken = secret;
+ if (partyContext != null && getPartyContext().isPartyExistHypixel())
+ ChatProcessor.INSTANCE.addToChatQueue("/p leave", () -> {}, true);
+ DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().method(StompHeader.SEND)
+ .header("destination", "/app/party.askedtojoin")
+ .payload(new JSONObject().put("token", secret).toString()));
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandDungeonsGuide.java b/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandDungeonsGuide.java
index d5fe082e..914ca8e8 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandDungeonsGuide.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandDungeonsGuide.java
@@ -20,7 +20,8 @@ package kr.syeyoung.dungeonsguide.commands;
import com.google.gson.JsonObject;
import kr.syeyoung.dungeonsguide.DungeonsGuide;
-import kr.syeyoung.dungeonsguide.pathfinding.JPSPathfinder;
+import kr.syeyoung.dungeonsguide.chat.PartyContext;
+import kr.syeyoung.dungeonsguide.chat.PartyManager;
import kr.syeyoung.dungeonsguide.rpc.RichPresenceManager;
import kr.syeyoung.dungeonsguide.SkyblockStatus;
import kr.syeyoung.dungeonsguide.config.guiconfig.GuiConfigV2;
@@ -41,7 +42,6 @@ import kr.syeyoung.dungeonsguide.features.AbstractFeature;
import kr.syeyoung.dungeonsguide.features.FeatureRegistry;
import kr.syeyoung.dungeonsguide.features.impl.party.playerpreview.FeatureViewPlayerOnJoin;
import kr.syeyoung.dungeonsguide.features.impl.party.api.ApiFetchur;
-import kr.syeyoung.dungeonsguide.party.PartyManager;
import kr.syeyoung.dungeonsguide.roomedit.EditingContext;
import kr.syeyoung.dungeonsguide.roomedit.gui.GuiDungeonRoomEdit;
import kr.syeyoung.dungeonsguide.roomprocessor.GeneralRoomProcessor;
@@ -263,17 +263,23 @@ public class CommandDungeonsGuide extends CommandBase {
t.printStackTrace();
}
} else if (args[0].equalsIgnoreCase("pvall")) {
- PartyManager.INSTANCE.getRunOnMembersReceived().add((e) -> {
- for (String s : e) {
- ApiFetchur.fetchUUIDAsync(s)
+ PartyManager.INSTANCE.requestPartyList((context) -> {
+ if (context == null) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cNot in Party"));
+ return;
+ }
+ for (String member : context.getPartyRawMembers()) {
+ ApiFetchur.fetchUUIDAsync(member)
.thenAccept(a -> {
- if (a == null) return;
- ApiFetchur.fetchMostRecentProfileAsync(a.get(), FeatureRegistry.PARTYKICKER_APIKEY.getAPIKey());
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e" + s + "§f's Profile ").appendSibling(new ChatComponentText("§7view").setChatStyle(new ChatStyle().setChatHoverEvent(new FeatureViewPlayerOnJoin.HoverEventRenderPlayer(a.orElse(null))))));
+ if (a == null) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e"+member+"§f's Profile §cCouldn't fetch uuid"));
+ } else {
+ ApiFetchur.fetchMostRecentProfileAsync(a.get(), FeatureRegistry.PARTYKICKER_APIKEY.getAPIKey());
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e" + member + "§f's Profile ").appendSibling(new ChatComponentText("§7view").setChatStyle(new ChatStyle().setChatHoverEvent(new FeatureViewPlayerOnJoin.HoverEventRenderPlayer(a.orElse(null))))));
+ }
});
}
});
- PartyManager.INSTANCE.requestPartyRetrieval();
// } else if (args[0].equals("fixschematic")) {
// File root = new File(e.getDungeonsGuide().getConfigDir(), "schematics");
// Method method = null;
@@ -315,11 +321,11 @@ public class CommandDungeonsGuide extends CommandBase {
sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cDiscord GameSDK has been disabled, or it failed to load!"));
return;
}
- if (!PartyManager.INSTANCE.isCanInvite()) {
+ if (!PartyManager.INSTANCE.canInvite()) {
sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cYou don't have perms in the party to invite people!"));
} else {
PartyManager.INSTANCE.toggleAllowAskToJoin();
- sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fToggled Ask to join to " + (PartyManager.INSTANCE.isAllowAskToJoin() ? "§eon" : "§coff")));
+ sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fToggled Ask to join to " + (PartyManager.INSTANCE.getAskToJoinSecret() != null ? "§eon" : "§coff")));
}
if (!FeatureRegistry.DISCORD_RICHPRESENCE.isEnabled()) {
@@ -347,7 +353,7 @@ public class CommandDungeonsGuide extends CommandBase {
}
}
} else if (args[0].equals("partyid")) {
- sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fInternal Party id: " + PartyManager.INSTANCE.getPartyID()));
+ sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fInternal Party id: " + Optional.ofNullable(PartyManager.INSTANCE.getPartyContext()).map(PartyContext::getPartyID).orElse(null)));
} else if (args[0].equalsIgnoreCase("loc")) {
sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fYou're in " + DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName()));
} else if (args[0].equalsIgnoreCase("saverun")) {
@@ -404,7 +410,7 @@ public class CommandDungeonsGuide extends CommandBase {
System.arraycopy(args, 1, payload, 0, payload.length);
String actualPayload = String.join(" ", payload).replace("$C$", "§");
DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().header("destination", "/app/party.broadcast").payload(
- new JSONObject().put("partyID", PartyManager.INSTANCE.getPartyID())
+ new JSONObject().put("partyID", PartyManager.INSTANCE.getPartyContext().getPartyID())
.put("payload", actualPayload).toString()
));
} catch (Exception e) {
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/features/FeatureRegistry.java b/src/main/java/kr/syeyoung/dungeonsguide/features/FeatureRegistry.java
index f87456fa..edb429df 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/features/FeatureRegistry.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/features/FeatureRegistry.java
@@ -33,6 +33,7 @@ import kr.syeyoung.dungeonsguide.features.impl.dungeon.*;
import kr.syeyoung.dungeonsguide.features.impl.etc.*;
import kr.syeyoung.dungeonsguide.features.impl.etc.ability.FeatureAbilityCooldown;
import kr.syeyoung.dungeonsguide.features.impl.party.APIKey;
+import kr.syeyoung.dungeonsguide.features.impl.party.FeaturePartyList;
import kr.syeyoung.dungeonsguide.features.impl.party.customgui.FeatureCustomPartyFinder;
import kr.syeyoung.dungeonsguide.features.impl.party.playerpreview.FeatureViewPlayerOnJoin;
import kr.syeyoung.dungeonsguide.features.impl.secret.*;
@@ -161,6 +162,7 @@ public class FeatureRegistry {
public static final APIKey PARTYKICKER_APIKEY = register(new APIKey());
public static final FeatureViewPlayerOnJoin PARTYKICKER_VIEWPLAYER = register(new FeatureViewPlayerOnJoin());
public static final FeatureCustomPartyFinder PARTYKICKER_CUSTOM = register(new FeatureCustomPartyFinder());
+ public static final FeaturePartyList PARTY_LIST = register(new FeaturePartyList());
public static final FeatureTooltipDungeonStat ETC_DUNGEONSTAT = register(new FeatureTooltipDungeonStat());
public static final FeatureTooltipPrice ETC_PRICE = register(new FeatureTooltipPrice());
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/FeaturePartyList.java b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/FeaturePartyList.java
new file mode 100644
index 00000000..0222b97b
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/FeaturePartyList.java
@@ -0,0 +1,97 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.features.impl.party;
+
+import kr.syeyoung.dungeonsguide.chat.PartyContext;
+import kr.syeyoung.dungeonsguide.chat.PartyManager;
+import kr.syeyoung.dungeonsguide.config.types.AColor;
+import kr.syeyoung.dungeonsguide.features.text.StyledText;
+import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature;
+import kr.syeyoung.dungeonsguide.features.text.TextStyle;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class FeaturePartyList extends TextHUDFeature {
+ public FeaturePartyList() {
+ super("Party","Party List", "Party List as GUI", "party.list", false, getFontRenderer().getStringWidth("Watcher finished spawning all mobs!"), getFontRenderer().FONT_HEIGHT);
+ getStyles().add(new TextStyle("name", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false));
+ getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false));
+ getStyles().add(new TextStyle("player", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false));
+ getStyles().add(new TextStyle("allinvite", new AColor(0xAA,0xAA,0xAA,255), new AColor(0, 0,0,0), false));
+ setEnabled(true);
+ }
+
+ @Override
+ public boolean isHUDViewable() {
+ return PartyManager.INSTANCE.getPartyContext() != null;
+ }
+
+ @Override
+ public java.util.List<String> getUsedTextStyle() {
+ return Arrays.asList("name" ,"separator", "player", "allinvite");
+ }
+
+ private static final List<StyledText> dummyText = new ArrayList<StyledText>();
+ static {
+ dummyText.add(new StyledText("\nLeader","name"));
+ dummyText.add(new StyledText(": ","separator"));
+ dummyText.add(new StyledText("syeyoung","player"));
+ dummyText.add(new StyledText("\nModerator","name"));
+ dummyText.add(new StyledText(": ","separator"));
+ dummyText.add(new StyledText("rioho, RaidShadowLegends, Tricked","player"));
+ dummyText.add(new StyledText("\nMember","name"));
+ dummyText.add(new StyledText(": ","separator"));
+ dummyText.add(new StyledText("Everyone","player"));
+ dummyText.add(new StyledText("\nAll invite Off","allinvite"));
+ }
+
+ @Override
+ public List<StyledText> getDummyText() {
+ return dummyText;
+ }
+
+ @Override
+ public boolean doesScaleWithHeight() {
+ return false;
+ }
+
+ @Override
+ public List<StyledText> getText() {
+ PartyContext pc = PartyManager.INSTANCE.getPartyContext();
+ List<StyledText> text= new ArrayList<>();
+ text.add(new StyledText("\nLeader","name"));
+ text.add(new StyledText(": ","separator"));
+ text.add(new StyledText(pc.getPartyOwner()+"","player"));
+ text.add(new StyledText("\nModerator","name"));
+ text.add(new StyledText(": ","separator"));
+ text.add(new StyledText(pc.getPartyModerator() == null ? "????" : String.join(", ", pc.getPartyModerator()) + (pc.isModeratorComplete() ? "" : " ?"),"player"));
+ text.add(new StyledText("\nMember","name"));
+ text.add(new StyledText(": ","separator"));
+ text.add(new StyledText(pc.getPartyMember() == null ? "????" : String.join(", ", pc.getPartyMember()) + (pc.isMemberComplete() ? "" : " ?"),"player"));
+ if (pc.getAllInvite() != null && !pc.getAllInvite())
+ text.add(new StyledText("\nAll invite Off","allinvite"));
+ else if (pc.getAllInvite() != null)
+ text.add(new StyledText("\nAll invite On","allinvite"));
+ else
+ text.add(new StyledText("\nAll invite Unknown","allinvite"));
+ return text;
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/ApiFetchur.java b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/ApiFetchur.java
index 046d9a8e..0d929697 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/ApiFetchur.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/ApiFetchur.java
@@ -64,8 +64,12 @@ public class ApiFetchur {
completableFutureMap3.clear();
completableFutureMap4.clear();
invalidKeys.clear();
- completableFutureMapLily= null;
constants = null;
+
+ ex.submit(ApiFetchur::getLilyWeightConstants);
+ }
+ static {
+ ex.submit(ApiFetchur::getLilyWeightConstants);
}
public static JsonObject getJson(String url) throws IOException {
@@ -81,25 +85,16 @@ public class ApiFetchur {
return gson.fromJson(new InputStreamReader(connection.getInputStream()), JsonArray.class);
}
- private static JsonObject constants;
- private static CompletableFuture<JsonObject> completableFutureMapLily;
- public static CompletableFuture<JsonObject> getLilyWeightConstants() {
- if (constants != null) return CompletableFuture.completedFuture(constants);
- if (completableFutureMapLily != null) return completableFutureMapLily;
- CompletableFuture<JsonObject> completableFuture = new CompletableFuture<>();
- completableFutureMapLily = completableFuture;
- ex.submit(() -> {
+ private static volatile JsonObject constants;
+ public static JsonObject getLilyWeightConstants() {
+ if (constants != null) return constants;
try {
JsonObject jsonObject = getJson("https://raw.githubusercontent.com/Antonio32A/lilyweight/master/lib/constants.json");
constants = jsonObject;
- completableFuture.complete(jsonObject);
- completableFutureMapLily= null;
} catch (Exception e) {
- completableFuture.completeExceptionally(e);
- completableFutureMapLily= null;
+ throw new RuntimeException(e);
}
- });
- return completableFuture;
+ return constants;
}
private static final Map<String, CompletableFuture<Optional<GameProfile>>> completableFutureMap4 = new ConcurrentHashMap<>();
@@ -174,7 +169,7 @@ public class ApiFetchur {
completableFutureMap.remove(uid);
invalidKeys.add(apiKey);
} else {
- completableFuture.complete(Optional.empty());
+ completableFuture.completeExceptionally(e);
completableFutureMap.remove(uid);
}
e.printStackTrace();
@@ -497,7 +492,7 @@ public class ApiFetchur {
}
private static void calculateLilyWeight(PlayerProfile playerProfile, JsonObject playerData) throws ExecutionException, InterruptedException {
- JsonObject constants = getLilyWeightConstants().get();
+ JsonObject constants = getLilyWeightConstants();
double[] slayerXP = new double[4];
if (playerData.has("slayer_bosses")) {
slayerXP[0] = getOrDefault(playerData.getAsJsonObject("slayer_bosses").getAsJsonObject("zombie"), "xp", 0);
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/PanelPartyFinder.java b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/PanelPartyFinder.java
index 23c8e253..eef360b2 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/PanelPartyFinder.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/PanelPartyFinder.java
@@ -18,13 +18,13 @@
package kr.syeyoung.dungeonsguide.features.impl.party.customgui;
+import kr.syeyoung.dungeonsguide.chat.PartyManager;
import kr.syeyoung.dungeonsguide.config.guiconfig.GuiConfigV2;
import kr.syeyoung.dungeonsguide.events.WindowUpdateEvent;
import kr.syeyoung.dungeonsguide.features.FeatureRegistry;
import kr.syeyoung.dungeonsguide.features.impl.discord.invteTooltip.MTooltipInvite;
import kr.syeyoung.dungeonsguide.gui.MPanel;
import kr.syeyoung.dungeonsguide.gui.elements.*;
-import kr.syeyoung.dungeonsguide.party.PartyManager;
import kr.syeyoung.dungeonsguide.rpc.RichPresenceManager;
import kr.syeyoung.dungeonsguide.utils.RenderUtils;
import lombok.Getter;
@@ -41,7 +41,6 @@ import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
-import net.minecraft.util.ChatComponentText;
import java.awt.*;
import java.util.HashMap;
@@ -122,7 +121,7 @@ public class PanelPartyFinder extends MPanel {
MModalMessage mTooltipInvite = new MModalMessage("Error", "Discord GameSDK has been disabled, or it failed to load", () -> {});
mTooltipInvite.setScale( new ScaledResolution(Minecraft.getMinecraft()).getScaleFactor());
mTooltipInvite.open(this);
- } else if (PartyManager.INSTANCE.isAllowAskToJoin()) {
+ } else if (PartyManager.INSTANCE.getAskToJoinSecret() != null) {
MTooltipInvite mTooltipInvite = new MTooltipInvite();
mTooltipInvite.setScale( new ScaledResolution(Minecraft.getMinecraft()).getScaleFactor());
mTooltipInvite.open(this);
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/PanelPartyFinderSettings.java b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/PanelPartyFinderSettings.java
index 8dad627c..46107ff8 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/PanelPartyFinderSettings.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/customgui/PanelPartyFinderSettings.java
@@ -18,8 +18,10 @@
package kr.syeyoung.dungeonsguide.features.impl.party.customgui;
+import kr.syeyoung.dungeonsguide.chat.ChatProcessor;
+import kr.syeyoung.dungeonsguide.chat.PartyManager;
import kr.syeyoung.dungeonsguide.features.FeatureRegistry;
-import kr.syeyoung.dungeonsguide.gui.MPanel;
+import kr.syeyoung.dungeonsguide.features.impl.party.api.ApiFetchur;
import kr.syeyoung.dungeonsguide.gui.elements.*;
import kr.syeyoung.dungeonsguide.utils.TextUtils;
import lombok.Getter;
@@ -53,22 +55,27 @@ public class PanelPartyFinderSettings extends MPanelScaledGUI {
boolean delistable = false;
public void setDelistable(boolean delistable) {
- createNew.setText(delistable ? "De-list" : "Create New");
this.delistable = delistable;
+ updateCreateNew();
+ }
+
+ public void updateCreateNew() {
+ createNew.setText((PartyManager.INSTANCE.getPartyContext() != null && !PartyManager.INSTANCE.isLeader()) ? "Leave Party" : (delistable ? "De-list" : "Create New"));
}
public PanelPartyFinderSettings(PanelPartyFinder panelPartyFinder) {
this.panelPartyFinder = panelPartyFinder;
- createNew.setText("Create New");
createNew.setOnActionPerformed(this::createNew);
createNew.setBackground(0xFF00838F);
createNew.setHover(0xFF00ACC1);
createNew.setClicked(0xFF0097A7);
add(createNew);
+ updateCreateNew();
refresh.setText("Refresh");
refresh.setOnActionPerformed(this::refresh);
add(refresh);
+
settings.setText("Search Settings");
settings.setOnActionPerformed(this::settings);
add(settings);
@@ -142,6 +149,10 @@ public class PanelPartyFinderSettings extends MPanelScaledGUI {
}
private void createNew() {
+ if (PartyManager.INSTANCE.getPartyContext() != null && !PartyManager.INSTANCE.isLeader()) {
+ ChatProcessor.INSTANCE.addToChatQueue("/p leave ", () -> {}, true);
+ return;
+ }
GuiChest chest = panelPartyFinder.getGuiCustomPartyFinder().getGuiChest();
if (delistable)
Minecraft.getMinecraft().playerController.windowClick(chest.inventorySlots.windowId, 9*5+7, 0, 0, Minecraft.getMinecraft().thePlayer);
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/FeatureViewPlayerOnJoin.java b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/FeatureViewPlayerOnJoin.java
index 21fb5d04..ceca0022 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/FeatureViewPlayerOnJoin.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/FeatureViewPlayerOnJoin.java
@@ -24,6 +24,8 @@ import io.github.moulberry.hychat.HyChat;
import io.github.moulberry.hychat.chat.ChatManager;
import io.github.moulberry.hychat.gui.GuiChatBox;
import kr.syeyoung.dungeonsguide.DungeonsGuide;
+import kr.syeyoung.dungeonsguide.chat.ChatProcessor;
+import kr.syeyoung.dungeonsguide.chat.PartyManager;
import kr.syeyoung.dungeonsguide.config.guiconfig.ConfigPanelCreator;
import kr.syeyoung.dungeonsguide.config.guiconfig.MFeatureEdit;
import kr.syeyoung.dungeonsguide.config.guiconfig.MParameterEdit;
@@ -38,7 +40,6 @@ import kr.syeyoung.dungeonsguide.features.listener.ChatListener;
import kr.syeyoung.dungeonsguide.features.listener.GuiClickListener;
import kr.syeyoung.dungeonsguide.features.listener.GuiPostRenderListener;
import kr.syeyoung.dungeonsguide.gui.MPanel;
-import kr.syeyoung.dungeonsguide.party.PartyManager;
import kr.syeyoung.dungeonsguide.utils.TextUtils;
import lombok.Getter;
import lombok.Setter;
@@ -416,10 +417,10 @@ public class FeatureViewPlayerOnJoin extends SimpleFeature implements GuiPostRen
if (Mouse.getEventButton() != -1 && Mouse.isButtonDown(Mouse.getEventButton())) {
if (new Rectangle(2, 195, 86, 23).contains(relX, relY)) {
// invite
- Minecraft.getMinecraft().thePlayer.sendChatMessage("/p invite " + ApiFetchur.fetchNicknameAsync(playerProfile.getMemberUID()).get().orElse("-"));
+ ChatProcessor.INSTANCE.addToChatQueue("/p invite " + ApiFetchur.fetchNicknameAsync(playerProfile.getMemberUID()).get().orElse("-"), () -> {}, true);
} else if (new Rectangle(2, 170, 86, 23).contains(relX, relY)) {
// kick
- Minecraft.getMinecraft().thePlayer.sendChatMessage("/p kick " + ApiFetchur.fetchNicknameAsync(playerProfile.getMemberUID()).get().orElse("-"));
+ ChatProcessor.INSTANCE.addToChatQueue("/p kick " + ApiFetchur.fetchNicknameAsync(playerProfile.getMemberUID()).get().orElse("-"), () -> {}, true);
} else if (new Rectangle(80,159,10,11).contains(relX, relY)) {
drawInv = true;
}
@@ -456,21 +457,31 @@ public class FeatureViewPlayerOnJoin extends SimpleFeature implements GuiPostRen
if (str.contains("§r§ejoined the dungeon group! (§r§b")) {
String username = TextUtils.stripColor(str).split(" ")[3];
if (username.equalsIgnoreCase(Minecraft.getMinecraft().getSession().getUsername())) {
- PartyManager.INSTANCE.getRunOnMembersReceived().add((e) -> {
- for (String s : e) {
- ApiFetchur.fetchUUIDAsync(s)
- .thenAccept(a -> {
- if (a == null) return;
- ApiFetchur.fetchMostRecentProfileAsync(a.get(), FeatureRegistry.PARTYKICKER_APIKEY.getAPIKey());
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e"+s+"§f's Profile ").appendSibling(new ChatComponentText("§7view").setChatStyle(new ChatStyle().setChatHoverEvent(new FeatureViewPlayerOnJoin.HoverEventRenderPlayer(a.orElse(null))))));
- });
+ PartyManager.INSTANCE.requestPartyList((context) -> {
+ if (context == null) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cBugged Dungeon Party "));
+ } else {
+
+ for (String member : context.getPartyRawMembers()) {
+ ApiFetchur.fetchUUIDAsync(member)
+ .thenAccept((a) -> {
+ if (a == null) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e"+member+"§f's Profile §cCouldn't fetch uuid"));
+ } else {
+ ApiFetchur.fetchMostRecentProfileAsync(a.get(), FeatureRegistry.PARTYKICKER_APIKEY.getAPIKey());
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e"+member+"§f's Profile ").appendSibling(new ChatComponentText("§7view").setChatStyle(new ChatStyle().setChatHoverEvent(new FeatureViewPlayerOnJoin.HoverEventRenderPlayer(a.orElse(null))))));
+ }
+ });
+ }
}
});
- PartyManager.INSTANCE.requestPartyRetrieval();
} else {
ApiFetchur.fetchUUIDAsync(username)
.thenAccept(a -> {
- if (a == null) return;
+ if (a == null) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e"+username+"§f's Profile §cCouldn't fetch uuid"));
+ return;
+ }
ApiFetchur.fetchMostRecentProfileAsync(a.get(), FeatureRegistry.PARTYKICKER_APIKEY.getAPIKey());
Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e"+username+"§f's Profile ").appendSibling(new ChatComponentText("§7view").setChatStyle(new ChatStyle().setChatHoverEvent(new FeatureViewPlayerOnJoin.HoverEventRenderPlayer(a.orElse(null))))));
});
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/party/PartyManager.java b/src/main/java/kr/syeyoung/dungeonsguide/party/PartyManager.java
deleted file mode 100644
index fdeab870..00000000
--- a/src/main/java/kr/syeyoung/dungeonsguide/party/PartyManager.java
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
- * Copyright (C) 2021 cyoung06
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-
-package kr.syeyoung.dungeonsguide.party;
-
-import kr.syeyoung.dungeonsguide.rpc.RichPresenceManager;
-import kr.syeyoung.dungeonsguide.DungeonsGuide;
-import kr.syeyoung.dungeonsguide.events.HypixelJoinedEvent;
-import kr.syeyoung.dungeonsguide.events.StompConnectedEvent;
-import kr.syeyoung.dungeonsguide.stomp.StompInterface;
-import kr.syeyoung.dungeonsguide.stomp.StompMessageHandler;
-import kr.syeyoung.dungeonsguide.stomp.StompPayload;
-import kr.syeyoung.dungeonsguide.stomp.StompSubscription;
-import kr.syeyoung.dungeonsguide.utils.TextUtils;
-import lombok.Getter;
-import lombok.Setter;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiNewChat;
-import net.minecraft.util.ChatComponentText;
-import net.minecraft.util.Tuple;
-import net.minecraftforge.client.event.ClientChatReceivedEvent;
-import net.minecraftforge.fml.common.eventhandler.EventPriority;
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
-import net.minecraftforge.fml.common.gameevent.TickEvent;
-import org.apache.logging.log4j.Level;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.simple.SimpleLogger;
-import org.json.JSONArray;
-import org.json.JSONObject;
-
-import java.security.SecureRandom;
-import java.util.*;
-import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.function.Consumer;
-
-public class PartyManager implements StompMessageHandler {
- public static final PartyManager INSTANCE = new PartyManager();
-
- @Getter
- private String partyID = "GENERATE_PARTYID_PLEASE_POG_THIS_IS_INVALID_ID_THAT_SHOULD_BE_REGENERATED";
- @Getter
- private String askToJoinSecret = null;
-
- private final SecureRandom random = new SecureRandom();
- private static final String validChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
-
- @Getter
- private boolean allowAskToJoin = false;
- @Getter
- private boolean canInvite = false;
- private int invitedDash =0;
-
- @Getter
- private final Queue<Consumer<Set<String>>> runOnMembersReceived = new LinkedList<>();
-
-
- @Getter
- @Setter
- private int maxParty = 5;
-
- private static final Logger logger = LogManager.getLogger();
-
-
- private PartyManager() {
- Logger l = LogManager.getLogger(GuiNewChat.class);
- if (l instanceof SimpleLogger) {
- ((SimpleLogger) l).setLevel(Level.OFF);
- } else if (l instanceof org.apache.logging.log4j.core.Logger) {
- ((org.apache.logging.log4j.core.Logger) l).setLevel(Level.OFF);
- }
- }
-
- public void toggleAllowAskToJoin() {
- if (canInvite) allowAskToJoin = !allowAskToJoin;
- if (allowAskToJoin) {
- generateNewAskToJoinSecret();
- }
- }
-
- public int getMemberCount() {
- return Math.max(1, members.size());
- }
-
- public void setPartyID(String partyID) {
- if (this.partyID != null && partyID == null) {
- JSONObject object = new JSONObject();
- object.put("members", new JSONArray());
- StompInterface stompInterface = DungeonsGuide.getDungeonsGuide().getStompConnection();
- stompInterface.send(new StompPayload().payload(object.toString()).header("destination", "/app/party.join"));
- }
-
- if (partyID != null && !partyID.equals(this.partyID)) {
- sendChat.add(new Tuple<>("/p invite -", () -> {invitedDash = 1;}));
- } else {
- canInvite = true;
- allowAskToJoin = false;
- }
- this.partyID = partyID;
- this.askToJoinSecret = null;
-
- if (allowAskToJoin && RichPresenceManager.INSTANCE.getLastSetupCode() != -9999) {
- generateNewAskToJoinSecret();
- }
- }
-
- public void generateNewAskToJoinSecret() {
- if (partyID == null) {
- JSONObject object = new JSONObject();
- object.put("members", new JSONArray());
- StompInterface stompInterface = DungeonsGuide.getDungeonsGuide().getStompConnection();
- stompInterface.send(new StompPayload().payload(object.toString()).header("destination", "/app/party.join"));
- }
-
- StringBuilder secretBuilder = new StringBuilder();
- for (int i = 0; i < 20; i++) {
- secretBuilder.append(validChars.charAt(random.nextInt(validChars.length())));
- }
- this.askToJoinSecret = secretBuilder.toString();
-
- StompInterface stompInterface = DungeonsGuide.getDungeonsGuide().getStompConnection();
- stompInterface.send(new StompPayload().payload(new JSONObject().put("secret", askToJoinSecret).toString()).header("destination", "/app/party.setjoinsecret"));
- }
-
- private int partyJoin =0;
- private final Set<String> members = new HashSet<>();
- private final Map<String, Long> recentlyJoined = new HashMap<>();
- @SubscribeEvent(priority = EventPriority.HIGHEST)
- public void onMessage(ClientChatReceivedEvent chatReceivedEvent) {
- if (chatReceivedEvent.type == 2) return;
-
- String str = chatReceivedEvent.message.getFormattedText();
- logger.log(Level.INFO, "[CHAT] "+str);
-
- try {
-
- if (str.startsWith("§eYou have joined ")) {
- members.clear();
- String[] strs = TextUtils.stripColor(str).split(" ");
- for (String s : strs) {
- if (s.endsWith("'s")) {
- members.add(s.substring(0, s.indexOf("'s")));
- break;
- }
- }
- members.add(Minecraft.getMinecraft().getSession().getUsername());
- partyJoin = 100;
- } else if (str.startsWith("§eYou'll be partying with: ")) {
- String[] players = TextUtils.stripColor(str.substring(27)).split(" ");
- for (String player : players) {
- if (player.startsWith("[")) continue;
- members.add(player);
- }
- } else if (str.equals("§9§m-----------------------------§r")) {
- if ((checkPlayer > 0 || partyJoin > 0) && partyJoin != 100) {
- chatReceivedEvent.setCanceled(true);
- }
- if (partyJoin == 2 || partyJoin == 100) {
- partyJoin = 0;
- // REQ PARTY JOIN
- Consumer<Set<String>> r;
- while ((r = runOnMembersReceived.poll()) != null){
- r.accept(members);
- }
-
- JSONArray jsonArray = new JSONArray();
- for (String member : members) {
- jsonArray.put(member);
- }
- JSONObject object = new JSONObject();
- object.put("members", jsonArray);
- StompInterface stompInterface = DungeonsGuide.getDungeonsGuide().getStompConnection();
- stompInterface.send(new StompPayload().payload(object.toString()).header("destination", "/app/party.join"));
- }
- if (checkPlayer == 3) {
- checkPlayer = 0;
- String playerName = theObject.getString("player");
- String token = theObject.getString("token");
- if (!members.contains(playerName)) {
- DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().payload(new JSONObject().put("status", "failure").put("token", token).toString()).header("destination", "/app/party.check.resp"));
- } else {
- DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().payload(new JSONObject().put("status", "success").put("token", token).toString()).header("destination", "/app/party.check.resp"));
- }
- }
- if (invitedDash == 1 || invitedDash == 3) {
- chatReceivedEvent.setCanceled(true);
- invitedDash++;
- }
- if (invitedDash == 4) invitedDash = 0;
- } else if (str.endsWith("§ejoined the party.§r")) {
- String asd = null;
- for (String s : TextUtils.stripColor(str).split(" ")) {
- if (s.startsWith("[")) continue;
- asd = s;
- break;
- }
- if (asd != null)
- members.add(asd);
- } else if (str.contains("§r§ejoined the dungeon group! (§r§b")) {
- String username = TextUtils.stripColor(str).split(" ")[3];
- if (username.equalsIgnoreCase(Minecraft.getMinecraft().getSession().getUsername())) {
- sendChat.add(new Tuple<>("/pl", () -> {partyJoin = 1;}));
- partyJoin = 1;
- } else {
- members.add(username);
- }
- } else if (str.endsWith("§ehas been removed from the party.§r")
- || str.endsWith("§ehas left the party.§r")) {
- String asd = null;
- for (String s : TextUtils.stripColor(str).split(" ")) {
- if (s.startsWith("[")) continue;
- asd = s;
- break;
- }
- if (asd != null)
- members.remove(asd);
- } else if ((str.equals("§eYou left the party.§r")
- || str.startsWith("§cThe party was disbanded")
- || str.endsWith("§ehas disbanded the party!§r"))
- ) {
- members.clear();
- setPartyID(null);
- } else if (str.startsWith("§6Party Members ")) {
- if (checkPlayer > 0 || partyJoin > 0) {
- chatReceivedEvent.setCanceled(true);
- }
- if (partyJoin == 1) partyJoin = 2;
- if (checkPlayer == 2) checkPlayer = 3;
- members.clear();
- } else if (str.startsWith("§cYou are not currently in a party.§r")) {
- members.clear();
- if (partyJoin > 0) {
- partyJoin = 2;
- chatReceivedEvent.setCanceled(true);
- }
- if (invitedDash > 0) invitedDash = 3;
- if (invitedDash > 0) chatReceivedEvent.setCanceled(true);
- setPartyID(null);
- } else if (TextUtils.stripColor(str).trim().isEmpty()) {
- if ((checkPlayer > 0 || partyJoin > 0) && partyJoin != 100) {
- chatReceivedEvent.setCanceled(true);
- }
- } else if (str.startsWith("§cYou are not in a party")) {
- members.clear();
- if (partyJoin > 0) {
- partyJoin = 2;
- chatReceivedEvent.setCanceled(true);
- }
- if (invitedDash > 0) invitedDash = 3;
- if (invitedDash > 0) chatReceivedEvent.setCanceled(true);
- setPartyID(null);
- } else if (str.startsWith("§eParty ") && str.contains(":")) {
- if (checkPlayer > 0 || partyJoin > 0) {
- chatReceivedEvent.setCanceled(true);
- }
- String playerNames = TextUtils.stripColor(str.split(":")[1]);
- for (String s : playerNames.split(" ")) {
- if (s.isEmpty()) continue;
- if (s.equals("●")) continue;
- if (s.startsWith("[")) continue;
- members.add(s);
- }
- } else if (str.equals("§cYou are not allowed to invite players.§r")) {
- if (invitedDash > 0) invitedDash = 3;
- if (invitedDash > 0) chatReceivedEvent.setCanceled(true);
- canInvite = false;
- allowAskToJoin = false;
- askToJoinSecret = "";
- } else if (str.equals("§cCouldn't find a player with that name!§r")) {
- canInvite = true;
- if (invitedDash > 0) invitedDash = 3;
- if (invitedDash > 0) chatReceivedEvent.setCanceled(true);
- } else if (str.equals("§cYou cannot invite that player since they're not online.")) {
- if (invitedDash > 0) invitedDash = 3;
- if (invitedDash > 0) chatReceivedEvent.setCanceled(true);
- canInvite = true;
- } else if (str.endsWith("§aenabled All Invite§r")) {
- canInvite = true;
- } else if (str.endsWith("§cdisabled All Invite§r")) {
- canInvite = false;
- allowAskToJoin = false;
- askToJoinSecret = "";
- sendChat.add(new Tuple<>("/p invite -", () -> {invitedDash = 1;}));
- } else if (str.endsWith("§r§eto Party Moderator§r")) {
- // §b[MVP§r§f+§r§b] apotato321§r§e has promoted §r§a[VIP§r§6+§r§a] syeyoung §r§eto Party Moderator§r
- String[] thetext = TextUtils.stripColor(str).split(" ");
- int seenThings = 0;
- for (String s : thetext) {
- if (s.equals("has") && seenThings == 0) seenThings = 1;
- else if (s.equals("promoted") && seenThings == 1) seenThings = 2;
- else if (s.equals("[")) continue;
- else if (seenThings == 2) {
- if (s.equals(Minecraft.getMinecraft().getSession().getUsername())) {
- canInvite = true;
- } else {
- sendChat.add(new Tuple<>("/p invite -", () -> {invitedDash = 1;}));
- break;
- }
- } else {
- seenThings = 0;
- }
- }
- } else if (str.startsWith("§eThe party was transferred to ")) {
- //§eThe party was transferred to §r§b[MVP§r§f+§r§b] apotato321 §r§eby §r§a[VIP§r§6+§r§a] syeyoung§r
- String[] thetext = TextUtils.stripColor(str.substring(31)).split(" ");
- String asd = null;
- for (String s : thetext) {
- if (s.startsWith("[")) continue;
- asd = s;
- break;
- }
- if (asd != null && Minecraft.getMinecraft().getSession().getUsername().equalsIgnoreCase(asd)) {
- canInvite = true;
- } else {
- sendChat.add(new Tuple<>("/p invite -", () -> {invitedDash = 1;}));
- }
- } else if (str.endsWith("§eto Party Leader§r")) {
- // §a[VIP§r§6+§r§a] syeyoung§r§e has promoted §r§b[MVP§r§f+§r§b] apotato321 §r§eto Party Leader§r
- String[] thetext = TextUtils.stripColor(str).split(" ");
- int seenThings = 0;
- for (String s : thetext) {
- if (s.equals("has") && seenThings == 0) seenThings = 1;
- else if (s.equals("promoted") && seenThings == 1) seenThings = 2;
- else if (s.equals("[")) continue;
- else if (seenThings == 2) {
- if (s.equals(Minecraft.getMinecraft().getSession().getUsername())) {
- canInvite = true;
- } else {
- sendChat.add(new Tuple<>("/p invite -", () -> {invitedDash = 1;}));
- break;
- }
- } else {
- seenThings = 0;
- }
- }
- } else if (str.endsWith("§r§eto Party Member§r")) {
- String[] thetext = TextUtils.stripColor(str).split(" ");
- int seenThings = 0;
- for (String s : thetext) {
- if (s.equals("has") && seenThings == 0) seenThings = 1;
- else if (s.equals("demoted") && seenThings == 1) seenThings = 2;
- else if (s.equals("[")) continue;
- else if (seenThings == 2) {
- if (s.equals(Minecraft.getMinecraft().getSession().getUsername())) {
- sendChat.add(new Tuple<>("/p invite -", () -> {invitedDash = 1;}));
- canInvite = false;
- break;
- }
- } else {
- seenThings = 0;
- }
- }
- }
- } catch (Exception ex) {ex.printStackTrace();
- DungeonsGuide.sendDebugChat(new ChatComponentText("ERRORRR!! on chat "+ ex));}
- }
- @SubscribeEvent
- public void onTick(TickEvent.ClientTickEvent clientTickEvent) {
- try {
- if (clientTickEvent.phase == TickEvent.Phase.START && Minecraft.getMinecraft().thePlayer != null && minimumNext < System.currentTimeMillis()) {
- if (checkPlayer == 1) {
- checkPlayer = -1;
- sendChat.add(new Tuple<>("/pl", () -> {
- checkPlayer = 2;
- }));
- }
- if (!sendChat.isEmpty()) {
- Tuple<String, Runnable> tuple = sendChat.poll();
- Minecraft.getMinecraft().thePlayer.sendChatMessage(tuple.getFirst());
- if (tuple.getSecond() != null)
- tuple.getSecond().run();
- minimumNext = System.currentTimeMillis() + 200;
- DungeonsGuide.sendDebugChat(new ChatComponentText("Sending " + tuple.getFirst() + " Secretly"));
- }
- }
- } catch (Throwable e) {
- e.printStackTrace();
- }
- }
-
- @SubscribeEvent
- public void onHypixelJoin(HypixelJoinedEvent skyblockJoinedEvent) {
- minimumNext = System.currentTimeMillis() + 1000;
- sendChat.add(new Tuple<>("/pl", () -> {partyJoin = 1;}));
- }
-
- public void requestPartyRetrieval() {
- sendChat.add(new Tuple<>("/pl", () -> {partyJoin = 1;}));
- }
-
- private int checkPlayer = 0;
- private JSONObject theObject;
- private long minimumNext = 0;
-
- public static Queue<Tuple<String, Runnable>> sendChat = new ConcurrentLinkedQueue<>();
-
- @Override
- public void handle(StompInterface stompInterface, StompPayload stompPayload) {
- JSONObject object = new JSONObject(stompPayload.payload());
- if ("/user/queue/party.check".equals(stompPayload.headers().get("destination"))) {
- checkPlayer = 1;
- theObject = object;
- } else if ("/user/queue/party.join".equals(stompPayload.headers().get("destination"))) {
- String playerName = object.getString("player");
- String secret = object.getString("secret");
- if (secret.equals(askToJoinSecret) && partyID != null) {
- sendChat .add(new Tuple<>("/p invite "+playerName, null));
- }
- } else if ("/user/queue/party.broadcast".equals(stompPayload.headers().get("destination"))) {
- try {
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: Message Broadcasted from player:: \n" + new JSONObject(stompPayload.payload()).getString("payload")));
- } catch (Exception e) {
- e.printStackTrace();
- }
- } else {
- String str = object.getString("status");
- if ("success".equals(str)) {
- setPartyID(object.getString("partyId"));
- } else {
- setPartyID(null);
- }
- }
- }
-
- @SubscribeEvent
- public void stompConnect(StompConnectedEvent stompConnectedEvent) {
- stompConnectedEvent.getStompInterface().subscribe(StompSubscription.builder()
- .stompMessageHandler(this).ackMode(StompSubscription.AckMode.AUTO).destination("/user/queue/party.resp").build());
- stompConnectedEvent.getStompInterface().subscribe(StompSubscription.builder()
- .stompMessageHandler(this).ackMode(StompSubscription.AckMode.AUTO).destination("/user/queue/party.check").build());
- stompConnectedEvent.getStompInterface().subscribe(StompSubscription.builder()
- .stompMessageHandler(this).ackMode(StompSubscription.AckMode.AUTO).destination("/user/queue/party.join").build());
- stompConnectedEvent.getStompInterface().subscribe(StompSubscription.builder()
- .stompMessageHandler(this).ackMode(StompSubscription.AckMode.AUTO).destination("/user/queue/party.broadcast").build());
- }
-}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/rpc/RichPresenceManager.java b/src/main/java/kr/syeyoung/dungeonsguide/rpc/RichPresenceManager.java
index 598b3e49..5ff9852b 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/rpc/RichPresenceManager.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/rpc/RichPresenceManager.java
@@ -23,6 +23,8 @@ import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;
import kr.syeyoung.dungeonsguide.DungeonsGuide;
import kr.syeyoung.dungeonsguide.SkyblockStatus;
+import kr.syeyoung.dungeonsguide.chat.PartyContext;
+import kr.syeyoung.dungeonsguide.chat.PartyManager;
import kr.syeyoung.dungeonsguide.dungeon.DungeonContext;
import kr.syeyoung.dungeonsguide.events.DiscordUserJoinRequestEvent;
import kr.syeyoung.dungeonsguide.events.DiscordUserUpdateEvent;
@@ -33,15 +35,13 @@ import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.*;
import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.*;
import kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct.*;
import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.*;
-import kr.syeyoung.dungeonsguide.party.PartyManager;
-import kr.syeyoung.dungeonsguide.stomp.StompHeader;
-import kr.syeyoung.dungeonsguide.stomp.StompPayload;
import lombok.Getter;
import net.minecraftforge.common.MinecraftForge;
-import org.json.JSONObject;
import java.util.HashMap;
import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
public class RichPresenceManager implements Runnable {
public static RichPresenceManager INSTANCE = new RichPresenceManager();
@@ -90,9 +90,7 @@ public class RichPresenceManager implements Runnable {
System.out.println("Received Join Request from "+user.id.longValue()+" ("+GameSDK.readString(user.username)+")");
};
callbacks.OnActivityJoin = (eventData, secret) -> {
- DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().method(StompHeader.SEND)
- .header("destination", "/app/party.askedtojoin")
- .payload(new JSONObject().put("token", secret).toString()));
+ PartyManager.INSTANCE.joinWithToken(secret);
System.out.println("Trying to join with token "+secret);
};
callbacks.OnActivityJoinRequest = (eventData, user) -> {
@@ -195,8 +193,8 @@ public class RichPresenceManager implements Runnable {
GameSDK.writeString(latestDiscordActivity.assets.large_text, "mort");
GameSDK.writeString(latestDiscordActivity.state, name);
- GameSDK.writeString(latestDiscordActivity.party.id, PartyManager.INSTANCE.getPartyID() == null ? "" : PartyManager.INSTANCE.getPartyID());
- latestDiscordActivity.party.discordActivityParty.current_size = new Int32(PartyManager.INSTANCE.getMemberCount());
+ GameSDK.writeString(latestDiscordActivity.party.id, Optional.ofNullable( PartyManager.INSTANCE.getPartyContext()).map(PartyContext::getPartyID).orElse(""));
+ latestDiscordActivity.party.discordActivityParty.current_size = new Int32(Optional.ofNullable(PartyManager.INSTANCE.getPartyContext()).map(PartyContext::getPartyRawMembers).map(Set::size).orElse(1));
latestDiscordActivity.party.discordActivityParty.max_size = new Int32(PartyManager.INSTANCE.getMaxParty());
if (skyblockStatus.getContext() != null) {
@@ -213,7 +211,7 @@ public class RichPresenceManager implements Runnable {
latestDiscordActivity.timestamps.start = new DiscordTimestamp(0);
GameSDK.writeString(latestDiscordActivity.details, "Dungeons Guide");
}
- if (PartyManager.INSTANCE.isAllowAskToJoin()) {
+ if (PartyManager.INSTANCE.getAskToJoinSecret() != null) {
GameSDK.writeString(latestDiscordActivity.secrets.join, PartyManager.INSTANCE.getAskToJoinSecret());
} else {
GameSDK.writeString(latestDiscordActivity.secrets.join, "");
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompPayload.java b/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompPayload.java
index 6bb45a84..27b1cdc9 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompPayload.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/stomp/StompPayload.java
@@ -53,10 +53,13 @@ public class StompPayload {
if (payload != null)
sb.append(payload);
sb.append((char) 0);
+ if (FeatureRegistry.DEBUG.isEnabled()) System.out.println("Sending.. "+sb.toString());
return sb.toString();
}
public static StompPayload parse(String payload) {
+ if (FeatureRegistry.DEBUG.isEnabled()) System.out.println("Receving.. "+payload);
+
Scanner scanner = new Scanner(payload);
StompPayload stompPayload = new StompPayload();
stompPayload.method = StompHeader.valueOf(scanner.nextLine());