From 12bba40a991420585419332170eb7d9614194ca7 Mon Sep 17 00:00:00 2001 From: in1tiate Date: Thu, 15 Apr 2021 10:25:25 -0500 Subject: [PATCH 1/5] implement case announcements --- include/aoclient.h | 29 ++++++++++++++++ src/aoclient.cpp | 1 + src/packets.cpp | 83 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 111 insertions(+), 2 deletions(-) diff --git a/include/aoclient.h b/include/aoclient.h index 29eab62..a99c8e6 100644 --- a/include/aoclient.h +++ b/include/aoclient.h @@ -218,6 +218,27 @@ class AOClient : public QObject { {"SUPER", ~0ULL }, }; + + /** + * @brief A structure for storing the client's casing alert preferences. + */ + struct CasingPreferences { + QString caselist = ""; //!< The list of cases this user is willing to host (assuming they are also willing to CM) (unused) + bool cm = false; //!< If the user is willing to host cases (unused) + bool defense = false; //!< If the user is willing to defend a case / play as a defense attorney (or a co-defense attorney) + bool prosecution = false; //!< If the user is willing to prosecute a case / play as a prosecutor (or a co-prosecutor) + bool judge = false; //!< If the user is willing to judge a case + bool jury = false; //!< If the user is willing to be a member of the jury in a case + bool stenographer = false; //!< If the user is willing to be the stenographer of a case + }; + + /** + * @brief The client's casing alert preferences. + * + * @see The struct itself for more details. + */ + CasingPreferences casing_preferences; + /** * @brief If true, the client's in-character messages will have their word order randomised. */ @@ -472,6 +493,12 @@ class AOClient : public QObject { /// Implements [editing evidence](https://github.com/AttorneyOnline/docs/blob/master/docs/development/network.md#edit). void pktEditEvidence(AreaData* area, int argc, QStringList argv, AOPacket packet); + /// Implements [updating casing preferences](https://github.com/AttorneyOnline/docs/blob/master/docs/development/network.md#case-preferences-update). + void pktSetCase(AreaData* area, int argc, QStringList argv, AOPacket packet); + + /// Implements [announcing a case](https://github.com/AttorneyOnline/docs/blob/master/docs/development/network.md#case-alert). + void pktAnnounceCase(AreaData* area, int argc, QStringList argv, AOPacket packet); + ///@} /** @@ -622,6 +649,8 @@ class AOClient : public QObject { {"PE", {ACLFlags.value("NONE"), 3, &AOClient::pktAddEvidence }}, {"DE", {ACLFlags.value("NONE"), 1, &AOClient::pktRemoveEvidence }}, {"EE", {ACLFlags.value("NONE"), 4, &AOClient::pktEditEvidence }}, + {"SETCASE", {ACLFlags.value("NONE"), 7, &AOClient::pktSetCase }}, + {"CASEA", {ACLFlags.value("NONE"), 6, &AOClient::pktAnnounceCase }}, }; /** diff --git a/src/aoclient.cpp b/src/aoclient.cpp index 762d99f..4baacec 100644 --- a/src/aoclient.cpp +++ b/src/aoclient.cpp @@ -311,6 +311,7 @@ bool AOClient::checkAuth(unsigned long long acl_mask) return true; } + QString AOClient::getIpid() { return ipid; } Server* AOClient::getServer() { return server; }; diff --git a/src/packets.cpp b/src/packets.cpp index 51b32c3..221fa56 100644 --- a/src/packets.cpp +++ b/src/packets.cpp @@ -344,6 +344,87 @@ void AOClient::pktEditEvidence(AreaData* area, int argc, QStringList argv, AOPac sendEvidenceList(area); } +void AOClient::pktSetCase(AreaData* area, int argc, QStringList argv, AOPacket packet) +{ + casing_preferences.caselist = argv[0]; + QList prefs_list; + for (int i = 1; i <=6; i++) { + bool is_int = false; + bool pref = argv[i].toInt(&is_int); + if (!is_int) + return; + prefs_list.append(pref); + } + casing_preferences.cm = prefs_list[0]; + casing_preferences.defense = prefs_list[1]; + casing_preferences.prosecution = prefs_list[2]; + casing_preferences.judge = prefs_list[3]; + casing_preferences.jury = prefs_list[4]; + casing_preferences.stenographer = prefs_list[5]; + + qDebug() << casing_preferences.cm << casing_preferences.defense << casing_preferences.prosecution << casing_preferences.judge << casing_preferences.jury << casing_preferences.stenographer; +} + +void AOClient::pktAnnounceCase(AreaData* area, int argc, QStringList argv, AOPacket packet) +{ + // the following is an example of the type of code AO2 makes me write + // you may wish to do something more pleasant rather than read this garbage + // taking a bath in battery acid, for instance + QString case_title = argv[0]; + QStringList needed_roles; + QList needs_list; + for (int i = 1; i <=5; i++) { + bool is_int = false; + bool need = argv[i].toInt(&is_int); + if (!is_int) + return; + needs_list.append(need); + } + // this is stupid stupid stupid i hate this + if (needs_list[0]) { + needed_roles.append("defense attorney"); + } + if (needs_list[1]) { + needed_roles.append("prosecutor"); + } + if (needs_list[2]) { + needed_roles.append("judge"); + } + if (needs_list[3]) { + needed_roles.append("jurors"); + } + if (needs_list[4]) { + needed_roles.append("stenographer"); + } + if (needed_roles.isEmpty()) { + return; + } + + QString message = "=== Case Announcement ===\r\n" + ooc_name + " needs " + needed_roles.join(", ") + " for " + case_title + "!"; + + QList clients_to_alert; + // this is morton the indented if statement + // please do not feed morton + for (AOClient* client : server->clients) { + if (((client->casing_preferences.defense && needed_roles.contains("defense attorney")) || + (client->casing_preferences.prosecution && needed_roles.contains("prosecutor")) || + (client->casing_preferences.judge && needed_roles.contains("judge")) || + (client->casing_preferences.jury && needed_roles.contains("jurors")) || + (client->casing_preferences.stenographer && needed_roles.contains("stenographer"))) + && !clients_to_alert.contains(client)) + clients_to_alert.append(client); + } + // morton is a little ugly but we love him anyway + + for (AOClient* client : clients_to_alert) { + client->sendPacket(AOPacket("CASEA", {message, argv[1], argv[2], argv[3], argv[4], argv[5], "1"})); + // you may be thinking, "hey wait a minute the network protocol documentation doesn't mention that last argument!" + // if you are in fact thinking that, you are correct! it is not in the documentation! + // however for some inscrutable reason Attorney Online 2 will outright reject a CASEA packet that does not have + // at least 7 arguments despite only using the first 6. Cera, i kneel. you have truly broken me. + } +} + void AOClient::sendEvidenceList(AreaData* area) { for (AOClient* client : server->clients) { @@ -719,6 +800,4 @@ void AOClient::updateJudgeLog(AreaData* area, AOClient* client, QString action) area->judgelog.append(logmessage); } else area->judgelog.append(logmessage); - - } From c9700f236f9de518c1ac609ee0ef2ffcf0df36c3 Mon Sep 17 00:00:00 2001 From: in1tiate Date: Thu, 15 Apr 2021 10:26:46 -0500 Subject: [PATCH 2/5] more cleanly handle empty input, snip debug call --- src/packets.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/packets.cpp b/src/packets.cpp index 221fa56..15823cb 100644 --- a/src/packets.cpp +++ b/src/packets.cpp @@ -361,8 +361,6 @@ void AOClient::pktSetCase(AreaData* area, int argc, QStringList argv, AOPacket p casing_preferences.judge = prefs_list[3]; casing_preferences.jury = prefs_list[4]; casing_preferences.stenographer = prefs_list[5]; - - qDebug() << casing_preferences.cm << casing_preferences.defense << casing_preferences.prosecution << casing_preferences.judge << casing_preferences.jury << casing_preferences.stenographer; } void AOClient::pktAnnounceCase(AreaData* area, int argc, QStringList argv, AOPacket packet) @@ -400,7 +398,7 @@ void AOClient::pktAnnounceCase(AreaData* area, int argc, QStringList argv, AOPac return; } - QString message = "=== Case Announcement ===\r\n" + ooc_name + " needs " + needed_roles.join(", ") + " for " + case_title + "!"; + QString message = "=== Case Announcement ===\r\n" + ooc_name == "" ? current_char : ooc_name + " needs " + needed_roles.join(", ") + " for " + case_title == "" ? "a case" : case_title + "!"; QList clients_to_alert; // this is morton the indented if statement From 122e993a8bda2b02a631b4f95abe8ea684662d2b Mon Sep 17 00:00:00 2001 From: in1tiate Date: Thu, 15 Apr 2021 13:49:27 -0500 Subject: [PATCH 3/5] condense some overly long code (ty marisa) --- src/packets.cpp | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/src/packets.cpp b/src/packets.cpp index 15823cb..c2f77e0 100644 --- a/src/packets.cpp +++ b/src/packets.cpp @@ -378,25 +378,13 @@ void AOClient::pktAnnounceCase(AreaData* area, int argc, QStringList argv, AOPac return; needs_list.append(need); } - // this is stupid stupid stupid i hate this - if (needs_list[0]) { - needed_roles.append("defense attorney"); + QStringList roles = {"defense attorney", "prosecutor", "judge", "jurors", "stenographer"}; + for (int i = 0; i < 5; i++) { + if (needs_list[i]) + needed_roles.append(roles[i]); } - if (needs_list[1]) { - needed_roles.append("prosecutor"); - } - if (needs_list[2]) { - needed_roles.append("judge"); - } - if (needs_list[3]) { - needed_roles.append("jurors"); - } - if (needs_list[4]) { - needed_roles.append("stenographer"); - } - if (needed_roles.isEmpty()) { + if (needed_roles.isEmpty()) return; - } QString message = "=== Case Announcement ===\r\n" + ooc_name == "" ? current_char : ooc_name + " needs " + needed_roles.join(", ") + " for " + case_title == "" ? "a case" : case_title + "!"; From b1dfeec8f5a92c89bc77c6ba0b8e5de01ab76254 Mon Sep 17 00:00:00 2001 From: in1tiate Date: Thu, 15 Apr 2021 13:58:41 -0500 Subject: [PATCH 4/5] euthanize morton, code cleanup --- include/aoclient.h | 19 ++----------------- src/packets.cpp | 25 +++++-------------------- 2 files changed, 7 insertions(+), 37 deletions(-) diff --git a/include/aoclient.h b/include/aoclient.h index a99c8e6..79bcbf1 100644 --- a/include/aoclient.h +++ b/include/aoclient.h @@ -220,24 +220,9 @@ class AOClient : public QObject { /** - * @brief A structure for storing the client's casing alert preferences. + * @brief A list of 5 casing preferences (def, pro, judge, jury, steno) */ - struct CasingPreferences { - QString caselist = ""; //!< The list of cases this user is willing to host (assuming they are also willing to CM) (unused) - bool cm = false; //!< If the user is willing to host cases (unused) - bool defense = false; //!< If the user is willing to defend a case / play as a defense attorney (or a co-defense attorney) - bool prosecution = false; //!< If the user is willing to prosecute a case / play as a prosecutor (or a co-prosecutor) - bool judge = false; //!< If the user is willing to judge a case - bool jury = false; //!< If the user is willing to be a member of the jury in a case - bool stenographer = false; //!< If the user is willing to be the stenographer of a case - }; - - /** - * @brief The client's casing alert preferences. - * - * @see The struct itself for more details. - */ - CasingPreferences casing_preferences; + QList casing_preferences = {false, false, false, false, false}; /** * @brief If true, the client's in-character messages will have their word order randomised. diff --git a/src/packets.cpp b/src/packets.cpp index c2f77e0..9790289 100644 --- a/src/packets.cpp +++ b/src/packets.cpp @@ -346,28 +346,19 @@ void AOClient::pktEditEvidence(AreaData* area, int argc, QStringList argv, AOPac void AOClient::pktSetCase(AreaData* area, int argc, QStringList argv, AOPacket packet) { - casing_preferences.caselist = argv[0]; QList prefs_list; - for (int i = 1; i <=6; i++) { + for (int i = 2; i <=6; i++) { bool is_int = false; bool pref = argv[i].toInt(&is_int); if (!is_int) return; prefs_list.append(pref); } - casing_preferences.cm = prefs_list[0]; - casing_preferences.defense = prefs_list[1]; - casing_preferences.prosecution = prefs_list[2]; - casing_preferences.judge = prefs_list[3]; - casing_preferences.jury = prefs_list[4]; - casing_preferences.stenographer = prefs_list[5]; + casing_preferences = prefs_list; } void AOClient::pktAnnounceCase(AreaData* area, int argc, QStringList argv, AOPacket packet) { - // the following is an example of the type of code AO2 makes me write - // you may wish to do something more pleasant rather than read this garbage - // taking a bath in battery acid, for instance QString case_title = argv[0]; QStringList needed_roles; QList needs_list; @@ -389,18 +380,12 @@ void AOClient::pktAnnounceCase(AreaData* area, int argc, QStringList argv, AOPac QString message = "=== Case Announcement ===\r\n" + ooc_name == "" ? current_char : ooc_name + " needs " + needed_roles.join(", ") + " for " + case_title == "" ? "a case" : case_title + "!"; QList clients_to_alert; - // this is morton the indented if statement - // please do not feed morton + // here lies morton, RIP for (AOClient* client : server->clients) { - if (((client->casing_preferences.defense && needed_roles.contains("defense attorney")) || - (client->casing_preferences.prosecution && needed_roles.contains("prosecutor")) || - (client->casing_preferences.judge && needed_roles.contains("judge")) || - (client->casing_preferences.jury && needed_roles.contains("jurors")) || - (client->casing_preferences.stenographer && needed_roles.contains("stenographer"))) - && !clients_to_alert.contains(client)) + QSet matches = client->casing_preferences.toSet().intersect(needs_list.toSet()); + if (matches.isEmpty() && !clients_to_alert.contains(client)) clients_to_alert.append(client); } - // morton is a little ugly but we love him anyway for (AOClient* client : clients_to_alert) { client->sendPacket(AOPacket("CASEA", {message, argv[1], argv[2], argv[3], argv[4], argv[5], "1"})); From 38d73d92289303c5af79955cb4e97be85cb42b78 Mon Sep 17 00:00:00 2001 From: in1tiate Date: Thu, 15 Apr 2021 14:10:53 -0500 Subject: [PATCH 5/5] cleanup --- src/packets.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/packets.cpp b/src/packets.cpp index 9790289..6ddce8a 100644 --- a/src/packets.cpp +++ b/src/packets.cpp @@ -377,13 +377,14 @@ void AOClient::pktAnnounceCase(AreaData* area, int argc, QStringList argv, AOPac if (needed_roles.isEmpty()) return; - QString message = "=== Case Announcement ===\r\n" + ooc_name == "" ? current_char : ooc_name + " needs " + needed_roles.join(", ") + " for " + case_title == "" ? "a case" : case_title + "!"; + QString message = "=== Case Announcement ===\r\n" + (ooc_name == "" ? current_char : ooc_name) + " needs " + needed_roles.join(", ") + " for " + (case_title == "" ? "a case" : case_title) + "!"; QList clients_to_alert; // here lies morton, RIP + QSet needs_set = needs_list.toSet(); for (AOClient* client : server->clients) { - QSet matches = client->casing_preferences.toSet().intersect(needs_list.toSet()); - if (matches.isEmpty() && !clients_to_alert.contains(client)) + QSet matches = client->casing_preferences.toSet().intersect(needs_set); + if (!matches.isEmpty() && !clients_to_alert.contains(client)) clients_to_alert.append(client); }