diff options
author | Eryk Ruta <70776766+kingstefan26@users.noreply.github.com> | 2022-11-01 15:51:30 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-01 23:51:30 +0900 |
commit | 292fbd05e13271ca3ad99ebe00ae4302e04848f3 (patch) | |
tree | 2a7aeb12ab95ff688479a4727f76e3e4152c30b5 /src/main/java/kr/syeyoung/dungeonsguide/mod/party/PartyManager.java | |
parent | dd7a4209752715db544b2fef804da9762c532cdc (diff) | |
download | Skyblock-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.java | 626 |
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; + } +} |