aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/kr/syeyoung/dungeonsguide/mod/party/PartyManager.java
diff options
context:
space:
mode:
authorEryk Ruta <70776766+kingstefan26@users.noreply.github.com>2022-11-01 15:51:30 +0100
committerGitHub <noreply@github.com>2022-11-01 23:51:30 +0900
commit292fbd05e13271ca3ad99ebe00ae4302e04848f3 (patch)
tree2a7aeb12ab95ff688479a4727f76e3e4152c30b5 /src/main/java/kr/syeyoung/dungeonsguide/mod/party/PartyManager.java
parentdd7a4209752715db544b2fef804da9762c532cdc (diff)
downloadSkyblock-Dungeons-Guide-292fbd05e13271ca3ad99ebe00ae4302e04848f3.tar.gz
Skyblock-Dungeons-Guide-292fbd05e13271ca3ad99ebe00ae4302e04848f3.tar.bz2
Skyblock-Dungeons-Guide-292fbd05e13271ca3ad99ebe00ae4302e04848f3.zip
3rd time is the charm (#70)
* Updated some dependencies, used my crusty skytils forgegradle fork + removed the IRRELEVANT hytils fixes. generally made the thing build * made the logs less annoying * temp fix so it doesn't throw an exception * FAT REFACTOR General refactor on Authenticator.java DungeonsGuide.java Main.java removed unnecessary imports where not needed to be removed DGInterface.java (no real reason to exist) in DungeonsGuide.java made the retry stomp a singe-thread executor, so it doesn't leak when offline added an "offline mode" so it doesn't just error when server down TODO: move auth to DungeonsGuide.java and make it retry when network down on launch * New auth implementation that should replace the old one: does all the things the old one did removed progressBar cuz it would make the impl 3x more complicated in the name of a splash screen added a token changed event (so now it supports re-logging with a different account) code is (should) be more readable / extensible TODO: surgically replace Authenticator.java with new impl AND support re-logging * Made the chat processor logger name less obnoxious * implemented my implementation of an implementation of auth can and is very buggy, essentially the loading of the remote classes but the mod works so idk TODO: MAKE STOMP NOT DO STUFF TILL STOMPCONNECTED IS EMITTED * fix for stomp client null bc forge events not going tru on pre-init TODO: make work and test the web loadable classes, then make all the stuff that relies on stomp not throw exceptions when stomp is not connected * move the create auth method into AuthProvider interface, so we don't clutter AuthManager with implementation details * Decouple AuthProviderUtil and DgAuth, move some stuff around and make it more readable * moved AuthUtil to make more sense * de-clutter the tree a little bit * Inline StompClientStatus.java / refactor * inline the useless interface * refactoringgg * fix ahUtils exeption spam * small StompClient refactor * fix GLCursors exeption spam + logger * make sure we are authenticated when downloading resources * new .destination("value") instead of .header("destination", "value") * StompMessageHandler -> StompMessageSubscription * Introduced StompManager * fix dungeon map not showing ppl heads * ehhh * wip (commit cuz im chekig out) * fix player profile not never loading in chat * remove this specific line * fix player profile not never loading in chat * cut out hychat like a cancer * ApiFetchur now caches whole players not single profiles, added a switch profile button in gui * ugh git * Revert "cut out hychat like a cancer" This reverts commit 2ee11afa * ugh git x2 * I tried, good luck maintaining this * forgot to uncomment hychat fix * make my new party ready work and look ok * change the look and add some "somewhere" locations * make stomp connection "null safe" * i hate git * introduce callbacks on parameter change for cleaner code add one example * impl new system, half way done * now shows which profile is now selected put button on top a lil refactor * fix player profile sometimes not loading * add players knowing who is using dg (try to) * announcing that we are a dg user will get reworked in the future * update deps * make it not spam logs * sanity check for premium features so it doesn't 403 * add YoMamaOutdated that checks if you are using outdated dg * hychat?? anyone * try catch in FeatureRegistry * added Ether transmission ability * chat shredder borken, disabled for now * party deserves its own folder * dungeon stuff in dungeon folder * events folders moved * fix score data collection hanging forever if stomp is not connected * fix stomp never connecting * re-add the removed * fix wonky rendering * server side implementation is not ready, canning this for a future release * attempt to fix heads loading on main thread * discord * me when sonar lint * new consumer based stomp subscriptions * replace old with new subscriptions * remove the remains of StompSubscription and replace CloseListener with a forge event * StompSubscription is now a functional interface * remove unnecessary event message chains, feature logic should be in the feature * fix events being set up wrongly * Revert "fix events being set up wrongly" This reverts commit e6ea7efa557a5f5c8a3ea33be998717bc024b8cb. * Revert "remove unnecessary event message chains," This reverts commit 96f508bae85b33cdcef6be19226c00fc52a1439b. * fix stomp client sending payload object instead of the actual payload * fix null pointer on empty party * fix players with cosmetics name being white in tab * added message when not connected to dg changed YoMamaOutdated to use CloudFlare workers added client sided message queue * the mod doesn't init when outdated * mcmod.info * dont busy wait in authmenager * test pepole crusty tests * chill out the authmanager * name the thread pool in auth manager * clear most compiler warnings * make outdated check allow to play without the mod initialized * make first startup VERY noticeable, move config creation to main * major dungeon package refactor * refactor checkpoint * refactor checkpoint #1 * final refactor checkpoint #2 * remove the player if from version check, made the version check not nesssery for playing Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * remove trap room fix that didnt fix anything Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * make secret beacons optional Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * make the checkmarks on map align with the rest of everyone Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * removed debug function Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move the menus to make more sense + make destination text on secrets optional Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * improve dungeonMap performance by ~90% temporarly disabled 9 slot map player location due to bugs fix DungeonContext not getting player from ScoreBoard Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * add epic countdown on dungeon start (still wip) Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * added a option to cache blockstaes Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * added TabListUtil Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * fixed epic countdown Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * (i want to sleep) made all the dungeon room detection async TODO: fix ol the bugs i created by doing that Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * stuff still broken but almost playable, unlike last commit Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * upload build jar to discord Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * cache the deps for the love of god Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * who needs linux and 32bit windows anyway Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * only upload to discord on beta branch Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * added "kick" when a member joins party Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move stuff that sends chat to player into a separate class Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * use our chat queue instead of calling `thePlayer.addChatMessage` to proxy ourselves from 1.8 code Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * Added and implemented MortDetector2000.java Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * extract duplicate + make more readable Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * added dummy support in FeatureDebugTrap Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * gradle now puts version in mcmod.info Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * remove side effects from DgAuth.java Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move debug commands into debug CommandDgDebug.java Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * fix key being wrong Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move epic countdown to dungeon huds, clean up Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * Revert "who needs linux and 32bit windows anyway" This reverts commit 0f3c2d544a70fc799cd3215dad5e997c0c8b6c06. * make FeatureRegistry not static initialise to get rid of "ClassNotDefined" errors Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * null check on Exception since it threw NullPointers Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * finish up progress bar in DungeonsGuide.java Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * warn about null features Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move stuff around in SkyblockStatus, move the stuff that updates status into SkyblockStatus from DungeonListener Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * rename DungeonGodObject.java to DungeonFacade.java Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * add cleanChat clause in FeatureEpicCountdown Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * implement getPreRequisites and isComplete in ActionBreakWithSuperBoom Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * clean up FeatureParameter Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * eliminate possible state inconsistency in DungeonListener Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move percentage from DungeonFacade to DungeonContext Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move `purge` and `partymax` back into CommandDungeonsGuide Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * stop repeating ReceiveChatQueue in ChatTransmitter Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * Clean up DungeonsGuide Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move `sendDebugChat` to `ChatTransmitter.java` Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * change CommandDgDebug into a `else if` from an `switch` because some bigot decided its better Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * duplicate code since it currently doesn't make sense, to be reworked Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * fix typo Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * remove the trycatch so we fail fast Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * fix null pointer when trying to get fontRenderer before minecraft is initialised Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * broken checkpoint 0 Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * broken checkpoint 1 Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * Revert "broken checkpoint 1" This reverts commit 64985e6287c7b5650b509668e42b9803e25c419c. * Revert "broken checkpoint 0" This reverts commit 5f62e1345d9c8e7f66f1e5792004a05027913d92. * Revert "fix null pointer when trying to get fontRenderer before minecraft is initialised" This reverts commit 57d92a78d31c410f699b58c8995c94055d57e2a4. * Revert "remove the trycatch so we fail fast" This reverts commit 12772255ed575e411fb99edf37ec16d0e5f42924. * Revert "fix typo" This reverts commit aa96cc2436d3ead42d53ead78f3334fac5100713. * Revert "duplicate code since it currently doesn't make sense, to be reworked" This reverts commit 6d71b88e3102d23bcfd90d85e8996327776fd52f. * Revert "change CommandDgDebug into a `else if` from an `switch` because some bigot decided its better" This reverts commit ffea84d9b5fd4adbe034a88249bc920eafa7c53a. * Revert "move `sendDebugChat` to `ChatTransmitter.java`" This reverts commit 5b8b2e22fff33768134a01c15c7650100ebb9257. * Revert "Clean up DungeonsGuide" This reverts commit 2069ad3ebc4344eb1e778954dc1d8f6c9303de69. * fix typo Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> (cherry picked from commit aa96cc2436d3ead42d53ead78f3334fac5100713) * duplicate code since it currently doesn't make sense, to be reworked Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> (cherry picked from commit 6d71b88e3102d23bcfd90d85e8996327776fd52f) * change CommandDgDebug into a `else if` from an `switch` because some bigot decided its better Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> (cherry picked from commit ffea84d9b5fd4adbe034a88249bc920eafa7c53a) * move debug chat into ChatTransmitter Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * null pointer in SkyblockStatus bc context was not initialised yet Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move dungeon starting door detection up the tree since it was a duplicate in both children, inline MortDetector2000 Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move dungeon name to DungeonContext Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * clean up Main Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * separate the "loader" and "mod" Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * separate DungeonsGuide and Main even more Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * change singleton implementation of DungeonsGuide Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move classes since their paths are hardcoded into roomdatas Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * create CatacombsDataProvider.java and implement it Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * remove unnecessary `DungeonsGuide.getDungeonsGuide();` (IntelliJ refactor bug) Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move `help` text in commands Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * a certain someone hates switch statements Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * remove my version check, since we have to wait for out lord and savior to make his own Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * make `Main` and `DungeonsGuide` compatible with supported jar classloading Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * make the beta upload action run on push since it didnt get the secret on pull request and failed anyway, TODO: make the jar name not hardcoded Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * upload all jar Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> Co-authored-by: syeyoung <42869671+cyoung06@users.noreply.github.com>
Diffstat (limited to 'src/main/java/kr/syeyoung/dungeonsguide/mod/party/PartyManager.java')
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/mod/party/PartyManager.java626
1 files changed, 626 insertions, 0 deletions
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/party/PartyManager.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/party/PartyManager.java
new file mode 100644
index 00000000..6e5d9aa9
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/party/PartyManager.java
@@ -0,0 +1,626 @@
+/*
+ * 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.mod.party;
+
+import kr.syeyoung.dungeonsguide.mod.chat.ChatProcessResult;
+import kr.syeyoung.dungeonsguide.mod.chat.ChatProcessor;
+import kr.syeyoung.dungeonsguide.mod.chat.ChatSubscriber;
+import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter;
+import kr.syeyoung.dungeonsguide.mod.events.impl.HypixelJoinedEvent;
+import kr.syeyoung.dungeonsguide.mod.events.impl.StompConnectedEvent;
+import kr.syeyoung.dungeonsguide.mod.features.impl.advanced.FeatureTestPepole;
+import kr.syeyoung.dungeonsguide.mod.stomp.*;
+import kr.syeyoung.dungeonsguide.mod.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 {
+ 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(new ChatSubscriber() {
+ @Override
+ public ChatProcessResult process(String str, Map<String, Object> 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.startsWith("§cYou are not in a party")
+ || str.startsWith("§eYou have been kicked from the party by ")) {
+ PartyManager.this.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(new ChatSubscriber() {
+ @Override
+ public ChatProcessResult process(String str, Map<String, Object> a) {
+ if (str.endsWith("§aenabled All Invite§r")) {
+ PartyManager.this.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")) {
+ PartyManager.this.getPartyContext(true).setAllInvite(false);
+ a.put("type", "allinvite_off");
+ PartyManager.this.potentialInvitenessChange();
+ }
+ 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.startsWith("§9§m---------------------------")) {
+ 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();
+ }
+ potentialInvitenessChange();
+ }
+ }
+ return ChatProcessResult.NONE;
+ }
+ });
+ // Player party join / leave
+ cp.subscribe(new ChatSubscriber() {
+ @Override
+ public ChatProcessResult process(String str, Map<String, Object> 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) {
+ PartyManager.this.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) {
+ PartyManager.this.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 (PartyManager.this.getPartyContext().hasMember(inviter)) {
+ PartyManager.this.getPartyContext().setAllInvite(true);
+ }
+ }
+ PartyManager.this.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 && PartyManager.this.getPartyContext().hasMember(username)) {
+ PartyManager.this.getPartyContext().setAllInvite(true);
+ }
+ }
+ return ChatProcessResult.NONE;
+ }
+ });
+ // Promotion
+ cp.subscribe(new ChatSubscriber() {
+ @Override
+ public ChatProcessResult process(String str, Map<String, Object> 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;
+ boolean left = false;
+ if (str.endsWith("§r§eleft§r")) {
+ oldLeader = messageSplit[messageSplit.length - 2];
+ left = true;
+ } else {
+ oldLeader = messageSplit[messageSplit.length - 1];
+ }
+
+ if (oldLeader != null && newLeader != null) {
+ PartyManager.this.getPartyContext(true).setPartyOwner(newLeader);
+ if (left)
+ PartyManager.this.getPartyContext(true).removeFromParty(oldLeader);
+ else
+ PartyManager.this.getPartyContext(true).addPartyModerator(oldLeader);
+ }
+ a.put("type", "party_transfer");
+ PartyManager.this.potentialInvitenessChange();
+ } 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) {
+ PartyManager.this.getPartyContext(true).setPartyOwner(newLeader);
+ PartyManager.this.getPartyContext(true).addPartyModerator(oldLeader);
+ }
+ a.put("type", "party_transfer");
+ PartyManager.this.potentialInvitenessChange();
+ } 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) {
+ PartyManager.this.getPartyContext(true).setPartyOwner(oldLeader);
+ PartyManager.this.getPartyContext(true).addPartyModerator(newModerator);
+ }
+ a.put("type", "party_promotion");
+ PartyManager.this.potentialInvitenessChange();
+ } 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) {
+ PartyManager.this.getPartyContext(true).setPartyOwner(oldLeader);
+ PartyManager.this.getPartyContext(true).addPartyMember(newMember);
+ }
+ a.put("type", "party_demotion");
+ PartyManager.this.potentialInvitenessChange();
+ }
+ 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.startsWith("§9§m---------------------------") && joined) {
+ joined = false;
+ getPartyContext().setRawMemberComplete(true);
+ joinedParty();
+ potentialInvitenessChange();
+ }
+ return ChatProcessResult.NONE;
+ }});
+ // Player Join Dungon
+ cp.subscribe(new ChatSubscriber() {
+ @Override
+ public ChatProcessResult process(String str, Map<String, Object> 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();
+ PartyManager.this.requestPartyList((str2) -> {
+ PartyManager.this.potentialInvitenessChange();
+ });
+ } else {
+ PartyManager.this.getPartyContext(true).setMemberComplete(false);
+ PartyManager.this.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();
+
+ StompManager.getInstance().send(new StompPayload().payload(new JSONObject().put("secret", askToJoinSecret).toString()).destination("/app/party.setjoinsecret"));
+ }
+
+ public static ChatSubscriber dashShredder() {
+ return (str, a) -> (int)a.get("removed") == 0 && str.startsWith("§9§m---------------------------") ? 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());
+ StompManager.getInstance().send(new StompPayload().payload(object.toString()).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);
+ StompManager.getInstance().send(new StompPayload().payload(object.toString()).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);
+
+ @SubscribeEvent
+ public void stompConnect(StompConnectedEvent event) {
+
+ event.getStompInterface().subscribe("/user/queue/party.resp", (stompClient ,payload) -> {
+ JSONObject object = new JSONObject(payload);
+
+ 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);
+ }
+ });
+
+ event.getStompInterface().subscribe("/user/queue/party.check", (stompClient ,payload) -> {
+ JSONObject object = new JSONObject(payload);
+ String playerName = object.getString("player");
+ String token = object.getString("token");
+ if (partyContext == null) {
+ requestPartyList((pc) -> {
+ boolean contains = pc.getPartyRawMembers().contains(playerName);
+ if (!contains) {
+ StompManager.getInstance().send(new StompPayload().payload(new JSONObject().put("status", "failure").put("token", token).toString()).destination("/app/party.check.resp"));
+ } else {
+ StompManager.getInstance().send(new StompPayload().payload(new JSONObject().put("status", "success").put("token", token).toString()).destination("/app/party.check.resp"));
+ }
+ });
+ } else {
+ if (getPartyContext().getPartyRawMembers().contains(playerName)) {
+ StompManager.getInstance().send(new StompPayload().payload(new JSONObject().put("status", "success").put("token", token).toString()).destination("/app/party.check.resp"));
+ } else if (getPartyContext().isMemberComplete() && getPartyContext().isModeratorComplete() && getPartyContext().getPartyOwner() != null) {
+ StompManager.getInstance().send(new StompPayload().payload(new JSONObject().put("status", "failure").put("token", token).toString()).destination("/app/party.check.resp"));
+ } else {
+ requestPartyList((pc) -> {
+ boolean contains = pc.getPartyRawMembers().contains(playerName);
+ if (!contains) {
+ StompManager.getInstance().send(new StompPayload().payload(new JSONObject().put("status", "failure").put("token", token).toString()).destination("/app/party.check.resp"));
+ } else {
+ StompManager.getInstance().send(new StompPayload().payload(new JSONObject().put("status", "success").put("token", token).toString()).destination("/app/party.check.resp"));
+ }
+ });
+ }
+ }
+ });
+ event.getStompInterface().subscribe("/user/queue/party.broadcast", (stompClient ,payload) -> {
+ String broadCastPlayload = new JSONObject(payload).getString("payload");
+ System.out.println("Received broadcast");
+ if(broadCastPlayload.startsWith("C:")) {
+ FeatureTestPepole.handlePartyBroadCast(broadCastPlayload);
+ }else {
+ try {
+ ChatTransmitter.addToQueue(new ChatComponentText("§eDungeons Guide §7:: Message Broadcasted from player:: \n" + new JSONObject(payload).getString("payload")));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ event.getStompInterface().subscribe("/user/queue/party.join", (stompClient ,payload) -> {
+ JSONObject object = new JSONObject(payload);
+ 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);
+ }
+ });
+ event.getStompInterface().subscribe("/user/queue/party.askedtojoin.resp", (stompClient ,payload) -> {
+ JSONObject object = new JSONObject(payload);
+ 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;
+ });
+ });
+
+
+ }
+
+ private String lastToken;
+ public void joinWithToken(String secret) {
+ lastToken = secret;
+ if (partyContext != null && getPartyContext().isPartyExistHypixel())
+ ChatProcessor.INSTANCE.addToChatQueue("/p leave", () -> {}, true);
+ StompManager.getInstance().send(new StompPayload().method(StompHeader.SEND)
+ .destination("/app/party.askedtojoin")
+ .payload(new JSONObject().put("token", secret).toString()));
+ }
+
+ private void potentialInvitenessChange() {
+ if (askToJoinSecret != null && !canInvite()) askToJoinSecret = null;
+ }
+}