aboutsummaryrefslogtreecommitdiff
path: root/mod/src/main/java/kr/syeyoung/dungeonsguide
diff options
context:
space:
mode:
authorsyeyoung <42869671+cyoung06@users.noreply.github.com>2023-10-20 16:01:22 +0900
committerGitHub <noreply@github.com>2023-10-20 16:01:22 +0900
commit4a38331c9742a39348e0c21dd861314b19fcf391 (patch)
tree82d319e43fee38342fbb11b2e2e83bc096b3413d /mod/src/main/java/kr/syeyoung/dungeonsguide
parent1164a7259d7bf8eef332bbb48bc141e08a22b780 (diff)
downloadSkyblock-Dungeons-Guide-4a38331c9742a39348e0c21dd861314b19fcf391.tar.gz
Skyblock-Dungeons-Guide-4a38331c9742a39348e0c21dd861314b19fcf391.tar.bz2
Skyblock-Dungeons-Guide-4a38331c9742a39348e0c21dd861314b19fcf391.zip
Multi Language support for Party context detection (#427)
* - Automatic Party Control Message collection for 25 languages Signed-off-by: syeyoung <cyoung06@naver.com> * - Processing generated file Signed-off-by: syeyoung <cyoung06@naver.com> * - Processing generated file, and add script for "transfering because leader left" message - Change how message detection is done to regex Maybe implement aho-corasick later. :D Signed-off-by: syeyoung <cyoung06@naver.com> * - update party messages Signed-off-by: syeyoung <cyoung06@naver.com> --------- Signed-off-by: syeyoung <cyoung06@naver.com>
Diffstat (limited to 'mod/src/main/java/kr/syeyoung/dungeonsguide')
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/mod/chat/ChatProcessor.java2
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/mod/chat/ChatRoutine.java209
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDgDebug.java195
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/mod/party/MessageMatcher.java73
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/mod/party/PartyManager.java213
5 files changed, 577 insertions, 115 deletions
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/chat/ChatProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/chat/ChatProcessor.java
index 206aed96..6a2295d9 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/chat/ChatProcessor.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/chat/ChatProcessor.java
@@ -75,7 +75,7 @@ public class ChatProcessor {
Minecraft.getMinecraft().thePlayer.sendChatMessage(tuple.getFirst());
if (tuple.getSecond() != null)
tuple.getSecond().run();
- minimumNext = System.currentTimeMillis() + 200;
+ minimumNext = System.currentTimeMillis() + 700;
ChatTransmitter.sendDebugChat(new ChatComponentText("Sending " + tuple.getFirst() + " Secretly"));
}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/chat/ChatRoutine.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/chat/ChatRoutine.java
new file mode 100644
index 00000000..5339cb2f
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/chat/ChatRoutine.java
@@ -0,0 +1,209 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2023 cyoung06 (syeyoung)
+ *
+ * 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.chat;
+
+import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
+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.annotations.EventHandlerRegistry;
+import lombok.AllArgsConstructor;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiMainMenu;
+import net.minecraft.client.gui.GuiMultiplayer;
+import net.minecraft.client.multiplayer.WorldClient;
+import net.minecraft.realms.RealmsBridge;
+
+import java.net.HttpURLConnection;
+import java.net.ProtocolException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+
+public class ChatRoutine {
+ List<Action> actions = new ArrayList<>();
+
+ public static interface Action {
+ void execute(Runnable next);
+ }
+ @AllArgsConstructor
+ public static class ActionSay implements Action {
+ String str;
+
+ @Override
+ public void execute(Runnable next) {
+ ChatProcessor.INSTANCE.addToChatQueue(str, next, false);
+ }
+ }
+ @AllArgsConstructor
+ public static class ActionOtherSay implements Action {
+ String str;
+
+ @Override
+ public void execute(Runnable next) {
+ try {
+ HttpURLConnection huc = (HttpURLConnection) new URL("http://localhost:3000/").openConnection();
+ huc.setDoOutput(true);
+ huc.setRequestMethod("POST");
+ huc.getOutputStream().write(str.getBytes());
+ huc.connect();
+ huc.getResponseCode();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ next.run();
+ }
+ }
+
+ @AllArgsConstructor
+ public static class ActionListen implements Action{
+ Consumer<List<String>> callback;
+
+ @Override
+ public void execute(Runnable next) {
+ ChatProcessor.INSTANCE.subscribe(new ChatSubscriber() {
+ int state = 0;
+ List<String> lol = new ArrayList<>();
+ @Override
+ public ChatProcessResult process(String txt, Map<String, Object> context) {
+ if (txt.startsWith("§9§m----------")) {
+ state++;
+ }
+ if (state > 0) {
+ lol.add(txt);
+ }
+ if (state == 2){
+ callback.accept(lol);
+ Minecraft.getMinecraft().addScheduledTask(next);
+ return ChatProcessResult.REMOVE_LISTENER;
+ }
+ return ChatProcessResult.NONE;
+ }
+ });
+ }
+ }
+
+ @AllArgsConstructor
+ public static class ActionListen2 implements Action{
+ Predicate<String> starting;
+ Consumer<String> callback;
+
+ @Override
+ public void execute(Runnable next) {
+ ChatProcessor.INSTANCE.subscribe(new ChatSubscriber() {
+ @Override
+ public ChatProcessResult process(String txt, Map<String, Object> context) {
+ if (starting.test(txt)) {
+ callback.accept(txt);
+ Minecraft.getMinecraft().addScheduledTask(next);
+ return ChatProcessResult.REMOVE_LISTENER;
+ }
+ return ChatProcessResult.NONE;
+ }
+ });
+ }
+ }
+ private static final ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(DungeonsGuide.THREAD_FACTORY);
+
+ public static class ActionRejoinHypickle implements Action {
+
+ @Override
+ public void execute(Runnable next) {
+ Minecraft.getMinecraft().theWorld.sendQuittingDisconnectingPacket();
+ Minecraft.getMinecraft().loadWorld((WorldClient)null);
+ GuiMultiplayer guiMultiplayer;
+ Minecraft.getMinecraft().displayGuiScreen(guiMultiplayer = new GuiMultiplayer(new GuiMainMenu()));
+ ses.schedule(() -> {
+ Minecraft.getMinecraft().addScheduledTask(() -> {
+ guiMultiplayer.selectServer(0);
+ guiMultiplayer.connectToSelected();
+
+ ses.schedule(() -> {
+ Minecraft.getMinecraft().addScheduledTask(next::run);
+ }, 10, TimeUnit.SECONDS);
+ });
+ }, 3, TimeUnit.SECONDS);
+ }
+ }
+
+ @AllArgsConstructor
+ public static class ActionRun implements Action {
+ private Runnable runnable;
+ @Override
+ public void execute(Runnable next) {
+ runnable.run();
+ next.run();
+ }
+ }
+ @AllArgsConstructor
+ public static class ActionWait implements Action {
+ private int ms;
+
+ @Override
+ public void execute(Runnable next) {
+ ses.schedule(() -> {
+ Minecraft.getMinecraft().addScheduledTask(next);
+ }, ms, TimeUnit.MILLISECONDS);
+ }
+ }
+
+ public void run() {
+
+ }
+
+ public void say(String a) {
+ actions.add(new ActionSay(a));
+ }
+ public void otherSay(String a) {
+ actions.add(new ActionOtherSay(a));
+ }
+ public void justRun(Runnable runnable) {
+ actions.add(new ActionRun(runnable));
+ }
+ public void waitForPartyMessage(Consumer<List<String>> callback) {
+ actions.add(new ActionListen(callback));
+ }
+ public void waitForSingleMessageMatching(Predicate<String> matcher, Consumer<String> callback) {
+ actions.add(new ActionListen2(matcher, callback));
+ }
+ public void justWait(int ms) {
+ actions.add(new ActionWait(ms));
+ }
+
+ public void rejoinHypickle() {
+ actions.add(new ActionRejoinHypickle());
+ }
+ Iterator<Action> iterator;
+ private void next() {
+ iterator.next().execute(this::next);
+ }
+ public void execute() {
+ run();
+ iterator = actions.iterator();
+ next();
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDgDebug.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDgDebug.java
index ad917532..28a702d3 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDgDebug.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDgDebug.java
@@ -25,6 +25,7 @@ import kr.syeyoung.dungeonsguide.dungeon.mechanics.dunegonmechanic.DungeonMechan
import kr.syeyoung.dungeonsguide.launcher.Main;
import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
import kr.syeyoung.dungeonsguide.mod.SkyblockStatus;
+import kr.syeyoung.dungeonsguide.mod.chat.ChatRoutine;
import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter;
import kr.syeyoung.dungeonsguide.mod.dungeon.DungeonContext;
import kr.syeyoung.dungeonsguide.mod.dungeon.events.DungeonEventHolder;
@@ -67,6 +68,7 @@ import java.security.*;
import java.security.cert.CertificateException;
import java.util.List;
import java.util.*;
+import java.util.function.Consumer;
public class CommandDgDebug extends CommandBase {
@Override
@@ -106,7 +108,8 @@ public class CommandDgDebug extends CommandBase {
"clearprofile",
"fullbright",
"gimmebright",
- "pfall"
+ "pfall",
+ "partycollection"
};
@Override
@@ -202,6 +205,9 @@ public class CommandDgDebug extends CommandBase {
case "reloadshader":
ShaderManager.onResourceReload();
break;
+ case "partycollection":
+ partyCollectionCommand(args[1], args[2], args[3]);
+ break;
default:
ChatTransmitter.addToQueue(new ChatComponentText("ain't gonna find much anything here"));
ChatTransmitter.addToQueue(new ChatComponentText("§eDungeons Guide §7:: §e/dg loadrooms §7-§f Reloads dungeon roomdata."));
@@ -685,4 +691,191 @@ public class CommandDgDebug extends CommandBase {
t.printStackTrace();
}
}
+
+ private void partyCollectionCommand(String otherPlayerName, String fragbot, String offline) {
+
+ String sourcePlayer = Minecraft.getMinecraft().thePlayer.getName();
+ String targetPlayer = otherPlayerName;
+ String thirdPlayer = fragbot;
+ String offlinePlayer = offline;
+ StringBuilder sb = new StringBuilder();
+ Consumer writer = (obj) -> {
+ sb.append("\n***************************\n");
+ if (obj instanceof List) {
+ for (Object obj2: (List) obj) {
+ sb.append("\n> ");
+ sb.append(obj2);
+ }
+ } else {
+ sb.append("\n> ");
+ sb.append(obj);
+ }
+ sb.append("\n");
+ };
+
+ new ChatRoutine() {
+ @Override
+ public void run() {
+ String langs = "ENGLISH, GERMAN, FRENCH, DUTCH, SPANISH, ITALIAN, CHINESE_SIMPLIFIED, CHINESE_TRADITIONAL, PORTUGUESE_BR, RUSSIAN, KOREAN, POLISH, JAPANESE, PIRATE, NORWEGIAN, PORTUGUESE_PT, SWEDISH, TURKISH, DANISH, CZECH, FINNISH, GREEK, UKRAINIAN, ROMANIAN, HUNGARIAN";
+ for (String s : langs.split(",")) {
+ say("/lang "+s.trim());
+ waitForSingleMessageMatching(a -> a.startsWith("§r§a"), (a) -> {});
+ justWait(500);
+ justRun(() -> writer.accept("\n\n$$LANGUAGE$$: "+s+"\n\n"));
+ rejoinHypickle();
+
+ say("/p leave");
+ say("/chat a");
+
+ otherSay("/p "+sourcePlayer);
+ waitForSingleMessageMatching(a -> a.startsWith("§9§m-----------------------------------------------------§r§9"), (a) -> {});
+ say("/p accept "+targetPlayer);
+ waitForPartyMessage((a) -> {});
+
+ otherSay("/p promote "+sourcePlayer);
+ waitForPartyMessage((a) -> {});
+ otherSay("/p "+thirdPlayer);
+ waitForPartyMessage((a) -> {});
+ waitForPartyMessage((a) -> {});
+
+ otherSay("/p leave");
+ waitForPartyMessage(writer);
+
+ say("/p disband");
+ //~ §ehas disbanded the party!§r
+ waitForPartyMessage(writer);
+
+
+ say("/p settings allinvite");
+ // §cYou are not currently in a party.§r
+ waitForPartyMessage(writer);
+ say("/p mute");
+ // §cYou are not in a party!§r
+ waitForPartyMessage(writer);
+ say("/p disband");
+ // §cYou are not in a party right now.§r
+ waitForPartyMessage(writer);
+ say("/chat p");
+ // §cYou must be in a party to join the party channel!§r
+ waitForPartyMessage(writer);
+
+
+
+ say("/p "+targetPlayer);
+ // §b[MVP§r§a+§r§b] syeyoung §r§einvited §r§b[MVP§r§0+§r§b] Azael_Nya §r§eto the party! They have §r§c60 §r§eseconds to accept.§r
+ waitForPartyMessage(writer);
+ justWait(500);
+
+ otherSay("/p accept syeyoung");
+ // §b[MVP§r§0+§r§b] Azael_Nya §r§ejoined the party.§r
+ waitForPartyMessage(writer);
+
+ say("/chat p");
+ // §aYou are now in the §r§6PARTY§r§a channel§r
+ waitForSingleMessageMatching((a) -> a.startsWith("§a") || a.startsWith("§6"), writer);
+
+
+ say("/p settings allinvite");
+ // §b[MVP§r§a+§r§b] syeyoung §r§aenabled All Invite§r
+ waitForPartyMessage(writer);
+ say("/p settings allinvite");
+ // §b[MVP§r§a+§r§b] syeyoung §r§cdisabled All Invite§r
+ waitForPartyMessage(writer);
+
+ say("/p 99999999999999999");
+ // §cCouldn't find a player with that name!§r
+ waitForPartyMessage(writer);
+ say("/p "+offlinePlayer);
+ // §cYou cannot invite that player since they're not online.
+ waitForPartyMessage(writer);
+
+
+ say("/p promote "+targetPlayer);
+ // §b[MVP§r§f+§r§b] apotato321§r§e has promoted §r§a[VIP§r§6+§r§a] syeyoung §r§eto Party Moderator§r
+ waitForPartyMessage(writer);
+ say("/p promote "+targetPlayer);
+ // §a[VIP§r§6+§r§a] syeyoung§r§e has promoted §r§b[MVP§r§f+§r§b] apotato321 §r§eto Party Leader§r
+ waitForPartyMessage(writer);
+ otherSay("/p demote "+sourcePlayer);
+ // §b[MVP§r§a+§r§b] syeyoung§r§e has demoted §r§b[MVP§r§0+§r§b] Azael_Nya §r§eto Party Member§r
+ waitForPartyMessage(writer);
+ otherSay("/p transfer "+sourcePlayer);
+ // §eThe party was transferred to §r§b[MVP§r§f+§r§b] apotato321 §r§eby §r§a[VIP§r§6+§r§a] syeyoung§r
+ waitForPartyMessage(writer);
+
+ // leaves
+ otherSay("/p leave");
+ // §b[MVP§r§0+§r§b] Azael_Nya §r§ehas left the party.§r
+ waitForPartyMessage(writer);
+
+ otherSay("/p "+thirdPlayer);
+ // §cThe party was disbanded because all invites expired and the party was empty.§r
+ waitForPartyMessage(writer);
+
+ say("smth");
+ // §cYou are not in a party and were moved to the ALL channel.§r
+ waitForPartyMessage(writer);
+
+ otherSay("/p "+sourcePlayer);
+ // §r§b[MVP§r§0+§r§b] Azael_Nya §r§ehas invited you to join their party!
+ // §r§eYou have §r§c60 §r§eseconds to accept. §r§6Click here to join!§r§9
+ waitForSingleMessageMatching(a -> a.startsWith("§9§m-----------------------------------------------------§r§9"), writer);
+
+ justWait(1000);
+
+ say("/p "+targetPlayer);
+ // §eYou have joined §r§b[MVP§r§0+§r§b] Azael_Nya's §r§eparty!§r
+ waitForPartyMessage(writer);
+
+ say("/p "+offlinePlayer);
+ // §cYou are not allowed to invite players.§r
+ waitForPartyMessage(writer);
+
+ otherSay("/p kick "+thirdPlayer);
+ // §ehas been removed from the party.§r
+ waitForPartyMessage(writer);
+ otherSay("/p kick "+sourcePlayer);
+ // §eYou have been kicked from the party by
+ waitForPartyMessage(writer);
+
+ // invite
+ say("/p "+targetPlayer);
+ waitForPartyMessage((a) -> {});
+ justWait(500);
+ otherSay("/p accept "+sourcePlayer);
+ waitForPartyMessage((a) -> {});
+
+ say("/pl");
+ // §6Party Members
+ waitForPartyMessage(writer);
+ say("/p leave");
+ // §eYou left the party.§r
+ waitForPartyMessage(writer);
+ // --disbanded--
+ waitForPartyMessage((a) -> {});
+
+ justRun(() -> {
+
+ try {
+ String total = sb.toString();
+ FileOutputStream fos = new FileOutputStream("partymessages.txt");
+ fos.write(total.getBytes());
+ fos.flush();
+ fos.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ });
+
+ }
+
+ say("/lang ENGLISH");
+
+ }
+ }.execute();
+
+
+
+ }
}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/party/MessageMatcher.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/party/MessageMatcher.java
new file mode 100644
index 00000000..822af607
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/party/MessageMatcher.java
@@ -0,0 +1,73 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2023 cyoung06 (syeyoung)
+ *
+ * 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 lombok.AllArgsConstructor;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class MessageMatcher {
+ List<String> simpleEquals = new ArrayList<>();
+ List<PatternData> regexPatterns = new ArrayList<>();
+
+ @AllArgsConstructor
+ public static class PatternData {
+ Pattern pattern;
+ int flags;
+ }
+
+ public MessageMatcher(List<String> patterns) {
+ for (String pattern : patterns) {
+ if (pattern.startsWith("=")) simpleEquals.add(pattern.substring(1));
+ else regexPatterns.add(new PatternData(Pattern.compile(pattern.substring(1), Pattern.DOTALL | Pattern.MULTILINE),
+ (pattern.contains("<p0>") ? 1 : 0) |
+ (pattern.contains("<p1>") ? 2 : 0) |
+ (pattern.contains("<p2>") ? 4 : 0)
+ ));
+ }
+ }
+
+ public boolean match(String str, Map<String, String> matchGroups) {
+ if (matchGroups != null)
+ matchGroups.clear();
+ for (String simpleEqual : simpleEquals) {
+ if (simpleEqual.equals(str)) return true;
+ }
+
+ for (PatternData regexPattern : regexPatterns) {
+ Matcher m = regexPattern.pattern.matcher(str);
+ if (m.matches()) {
+ if (matchGroups != null) {
+ if ((regexPattern.flags & 4) > 0)
+ matchGroups.put("2", m.group("p2"));
+ if ((regexPattern.flags & 2) > 0)
+ matchGroups.put("1", m.group("p1"));
+ if ((regexPattern.flags & 1) > 0)
+ matchGroups.put("0", m.group("p0"));
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/party/PartyManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/party/PartyManager.java
index 3a5d1f58..51d374d3 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/party/PartyManager.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/party/PartyManager.java
@@ -18,6 +18,7 @@
package kr.syeyoung.dungeonsguide.mod.party;
+import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
import kr.syeyoung.dungeonsguide.mod.chat.ChatProcessResult;
import kr.syeyoung.dungeonsguide.mod.chat.ChatProcessor;
import kr.syeyoung.dungeonsguide.mod.chat.ChatSubscriber;
@@ -34,12 +35,15 @@ import lombok.Setter;
import net.minecraft.client.Minecraft;
import net.minecraft.util.ChatComponentText;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import org.apache.commons.io.IOUtils;
import org.json.JSONArray;
import org.json.JSONObject;
+import java.io.IOException;
import java.security.SecureRandom;
import java.util.*;
import java.util.function.Consumer;
+import java.util.stream.Collectors;
public class PartyManager {
public static final PartyManager INSTANCE = new PartyManager();
@@ -65,21 +69,69 @@ public class PartyManager {
private Set<Consumer<PartyContext>> partyBuiltCallback = new HashSet<>();
+
+ private final MessageMatcher NOT_IN_PARTY;
+ private final MessageMatcher PARTY_CHANNEL;
+ private final MessageMatcher TRANSFER_LEFT;
+ private final MessageMatcher ALL_INVITE_ON;
+ private final MessageMatcher ALL_INVITE_OFF;
+ private final MessageMatcher PARTY_JOIN;
+ private final MessageMatcher PARTY_LEAVE;
+ private final MessageMatcher INVITED;
+ private final MessageMatcher INVITE_PERM;
+ private final MessageMatcher TRANSFER;
+ private final MessageMatcher PROMOTE_LEADER;
+ private final MessageMatcher PROMOTE_MODERATOR;
+ private final MessageMatcher MEMBER;
+ private final MessageMatcher ACCEPT_INVITE_LEADER;
+ private final MessageMatcher ACCEPT_INVITE_MEMBERS;
+
+ private MessageMatcher createMatcher(JSONObject object, String key) {
+ return new MessageMatcher(object.getJSONArray(key).toList().stream()
+ .filter(a -> a instanceof String)
+ .map(a -> (String) a)
+ .collect(Collectors.toList()));
+ }
+
+ private String processName(String name) {
+ String username = null;
+ for (String s : TextUtils.stripColor(name).split(" ")) {
+ if (s.startsWith("[")) continue;
+ username = s;
+ break;
+ }
+ return username;
+ }
+
public PartyManager() {
+ try {
+ JSONObject jsonObject = new JSONObject(IOUtils.toString(Objects.requireNonNull(DungeonsGuide.class.getResourceAsStream("/party_languages.json"))));
+ NOT_IN_PARTY = createMatcher(jsonObject, "not_in_party");
+ PARTY_CHANNEL = createMatcher(jsonObject, "party_channel");
+ ALL_INVITE_ON = createMatcher(jsonObject, "all_invite_on");
+ ALL_INVITE_OFF = createMatcher(jsonObject, "all_invite_off");
+ PARTY_JOIN = createMatcher(jsonObject, "party_join");
+ PARTY_LEAVE = createMatcher(jsonObject, "party_leave");
+ INVITED = createMatcher(jsonObject, "invited");
+ INVITE_PERM = createMatcher(jsonObject, "invite_perm");
+ TRANSFER = createMatcher(jsonObject, "transfer");
+ TRANSFER_LEFT = createMatcher(jsonObject, "transfer_left");
+ PROMOTE_LEADER = createMatcher(jsonObject, "promote_leader");
+ PROMOTE_MODERATOR = createMatcher(jsonObject, "promote_moderator");
+ MEMBER = createMatcher(jsonObject, "member");
+ ACCEPT_INVITE_LEADER = createMatcher(jsonObject, "accept_invite_leader");
+ ACCEPT_INVITE_MEMBERS = createMatcher(jsonObject, "accept_invite_members");
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+
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 ")) {
+ if (NOT_IN_PARTY.match(str, null)) {
PartyManager.this.leaveParty();
for (Consumer<PartyContext> partyContextConsumer : partyBuiltCallback) {
@@ -99,11 +151,10 @@ public class PartyManager {
cp.subscribe(new ChatSubscriber() {
@Override
public ChatProcessResult process(String str, Map<String, Object> a) {
- if (str.endsWith("§aenabled All Invite§r")) {
+ if (ALL_INVITE_ON.match(str, null)) {
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")) {
+ } else if (ALL_INVITE_OFF.match(str, null)) {
PartyManager.this.getPartyContext(true).setAllInvite(false);
a.put("type", "allinvite_off");
PartyManager.this.potentialInvitenessChange();
@@ -183,39 +234,23 @@ public class PartyManager {
});
// Player party join / leave
cp.subscribe(new ChatSubscriber() {
+ Map<String, String> matches = new HashMap<>();
@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 (PARTY_JOIN.match(str, matches)) {
+ String username = processName(matches.get("1"));
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;
- }
+ } else if (PARTY_LEAVE.match(str, matches)) {
+ String username = processName(matches.getOrDefault("1", matches.get("2")));
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;
- }
+ } else if (INVITED.match(str, matches)) {
+ String inviter = processName(matches.get("0"));
if (inviter != null && partyContext != null) {
if (PartyManager.this.getPartyContext().hasMember(inviter)) {
PartyManager.this.getPartyContext().setAllInvite(true);
@@ -223,7 +258,7 @@ public class PartyManager {
}
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.")) {
+ } else if (INVITE_PERM.match(str, null)) {
a.put("type", "party_invite_noexist");
String username = Minecraft.getMinecraft().getSession().getUsername();
if (partyContext != null && PartyManager.this.getPartyContext().hasMember(username)) {
@@ -235,51 +270,32 @@ public class PartyManager {
});
// Promotion
cp.subscribe(new ChatSubscriber() {
+ Map<String, String> matches = new HashMap<>();
@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 (TRANSFER.match(str, matches)) {
+ String newLeader = processName(matches.get("0"));
+ String oldLeader = processName(matches.get("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);
+ 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;
+ } else if (TRANSFER_LEFT.match(str, matches)) {
+ String newLeader = processName(matches.get("0"));
+ String oldLeader = processName(matches.get("1"));
+
+ if (oldLeader != null && newLeader != null) {
+ PartyManager.this.getPartyContext(true).setPartyOwner(newLeader);
+ PartyManager.this.getPartyContext(true).removeFromParty(oldLeader);
}
+ a.put("type", "party_transfer");
+ PartyManager.this.potentialInvitenessChange();
+ } else if (PROMOTE_LEADER.match(str, matches)) {
+ String oldLeader = processName(matches.get("0"));
+ String newLeader = processName(matches.get("1"));
if (oldLeader != null && newLeader != null) {
PartyManager.this.getPartyContext(true).setPartyOwner(newLeader);
@@ -287,22 +303,9 @@ public class PartyManager {
}
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;
- }
+ } else if (PROMOTE_MODERATOR.match(str, matches)) {
+ String oldLeader = processName(matches.get("0"));
+ String newModerator = processName(matches.get("1"));
if (oldLeader != null && newModerator != null) {
PartyManager.this.getPartyContext(true).setPartyOwner(oldLeader);
@@ -310,21 +313,9 @@ public class PartyManager {
}
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;
- }
+ } else if (MEMBER.match(str, matches)) {
+ String oldLeader = processName(matches.get("1"));
+ String newMember = processName(matches.get("0"));
if (oldLeader != null && newMember != null) {
PartyManager.this.getPartyContext(true).setPartyOwner(oldLeader);
@@ -339,24 +330,20 @@ public class PartyManager {
// Player Join
cp.subscribe(new ChatSubscriber() {
boolean joined;
+ Map<String, String> matches = new HashMap<>();
@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;
- }
+ if (ACCEPT_INVITE_LEADER.match(str, matches)) {
+ String leader = processName(matches.get("1"));
+
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(" ");
+ } else if (ACCEPT_INVITE_MEMBERS.match(str, matches)) {
+ String[] players = TextUtils.stripColor(matches.get("2")).split(" ");
for (String player : players) {
if (player.startsWith("[")) continue;
getPartyContext().addRawMember(player);