diff options
| author | syeyoung <cyoung06@naver.com> | 2021-11-27 23:19:16 +0900 |
|---|---|---|
| committer | syeyoung <cyoung06@naver.com> | 2021-11-27 23:19:16 +0900 |
| commit | d239ae4d4748fc4867ab45a5cc7d42bfb5ac547c (patch) | |
| tree | 39118080fafa68e896c10cee03f8c1cda9f0defd /src/main/java/kr | |
| parent | 7c22f439db227552d88d4df20e0cce6da947a2d0 (diff) | |
| download | Skyblock-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')
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); + |
