From 7dca20efe573d332a7d19cb4b8a518c21eff70b0 Mon Sep 17 00:00:00 2001
From: MangosArentLiterature
<58055358+MangosArentLiterature@users.noreply.github.com>
Date: Thu, 15 Apr 2021 00:49:57 -0500
Subject: [PATCH 1/5] Splitting commands part 1, authentication
---
akashi.pro | 2 +
include/aoclient.h | 514 +++++++++++++++++---------------
src/commands.cpp | 236 ---------------
src/commands/authentication.cpp | 258 ++++++++++++++++
4 files changed, 530 insertions(+), 480 deletions(-)
create mode 100644 src/commands/authentication.cpp
diff --git a/akashi.pro b/akashi.pro
index 1766080..f176d52 100644
--- a/akashi.pro
+++ b/akashi.pro
@@ -31,6 +31,8 @@ SOURCES += src/advertiser.cpp \
src/aopacket.cpp \
src/area_data.cpp \
src/commands.cpp \
+ src/commands/areas.cpp \
+ src/commands/authentication.cpp \
src/config_manager.cpp \
src/db_manager.cpp \
src/logger.cpp \
diff --git a/include/aoclient.h b/include/aoclient.h
index d64c774..16b4cfd 100644
--- a/include/aoclient.h
+++ b/include/aoclient.h
@@ -624,44 +624,6 @@ class AOClient : public QObject {
{"EE", {ACLFlags.value("NONE"), 4, &AOClient::pktEditEvidence }},
};
- /**
- * @brief Literally just an invalid default command. That's it.
- *
- * @note Can be used as a base for future commands.
- *
- * @iscommand
- */
- void cmdDefault(int argc, QStringList argv);
-
- /**
- * @brief Lists all the commands that the caller client has the permissions to use.
- *
- * @details No arguments.
- *
- * @iscommand
- */
- void cmdHelp(int argc, QStringList argv);
-
- /**
- * @brief Gets or sets the server's Message Of The Day.
- *
- * @details If called without arguments, gets the MOTD.
- *
- * If it has any number of arguments, it is set as the **MOTD**.
- *
- * @iscommand
- */
- void cmdMOTD(int argc, QStringList argv);
-
- /**
- * @brief Gives a very brief description of Akashi.
- *
- * @details No arguments.
- *
- * @iscommand
- */
- void cmdAbout(int argc, QStringList argv);
-
/**
* @name Authentication
*/
@@ -921,13 +883,13 @@ class AOClient : public QObject {
void cmdStatus(int argc, QStringList argv);
/**
- * @brief Returns the currently playing music in the area, and who played it.
- *
- * @details No arguments.
- *
- * @iscommand
- */
- void cmdCurrentMusic(int argc, QStringList argv);
+ * @brief Sends an out-of-character message with the judgelog of an area.
+ *
+ * @details No arguments.
+ *
+ * @iscommand
+ */
+ void cmdJudgeLog(int argc, QStringList argv);
///@}
@@ -939,6 +901,35 @@ class AOClient : public QObject {
*/
///@{
+ /**
+ * @brief Lists all the commands that the caller client has the permissions to use.
+ *
+ * @details No arguments.
+ *
+ * @iscommand
+ */
+ void cmdHelp(int argc, QStringList argv);
+
+ /**
+ * @brief Gets or sets the server's Message Of The Day.
+ *
+ * @details If called without arguments, gets the MOTD.
+ *
+ * If it has any number of arguments, it is set as the **MOTD**.
+ *
+ * @iscommand
+ */
+ void cmdMOTD(int argc, QStringList argv);
+
+ /**
+ * @brief Gives a very brief description of Akashi.
+ *
+ * @details No arguments.
+ *
+ * @iscommand
+ */
+ void cmdAbout(int argc, QStringList argv);
+
/**
* @brief Lists the currently logged-in moderators on the server.
*
@@ -993,50 +984,6 @@ class AOClient : public QObject {
*/
void cmdKick(int argc, QStringList argv);
- /**
- * @brief Sends out a decorated global message, for announcements.
- *
- * @details The arguments are **the message** that the client wants to send.
- *
- * @iscommand
- *
- * @see AOClient::cmdG()
- */
- void cmdAnnounce(int argc, QStringList argv);
-
- /**
- * @brief Sends a message in the server-wide, moderator only chat.
- *
- * @details The arguments are **the message** that the client wants to send.
- *
- * @iscommand
- */
- void cmdM(int argc, QStringList argv);
-
- /**
- * @brief Sends out a global message that is marked with an `[M]` to mean it is coming from a moderator.
- *
- * @details The arguments are **the message** that the client wants to send.
- *
- * @iscommand
- *
- * @see AOClient::cmdG()
- */
- void cmdGM(int argc, QStringList argv);
-
- /**
- * @brief Sends out a local message that is marked with an `[M]` to mean it is coming from a moderator.
- *
- * @details The arguments are **the message** that the client wants to send.
- *
- * @iscommand
- *
- * @see AOClient::cmdLM()
- */
- void cmdLM(int argc, QStringList argv);
-
- // Casing/RP
-
/**
* @brief Mutes a client.
*
@@ -1081,28 +1028,6 @@ class AOClient : public QObject {
*/
void cmdOocUnMute(int argc, QStringList argv);
- /**
- * @brief DJ-blocks a client.
- *
- * @details The only argument is the **target client's user ID**.
- *
- * @iscommand
- *
- * @see #is_dj_blocked
- */
- void cmdBlockDj(int argc, QStringList argv);
-
- /**
- * @brief Removes the DJ-blocked status from a client.
- *
- * @details The only argument is the **target client's user ID**.
- *
- * @iscommand
- *
- * @see #is_dj_blocked
- */
- void cmdUnBlockDj(int argc, QStringList argv);
-
/**
* @brief WTCE-blocks a client.
*
@@ -1144,6 +1069,27 @@ class AOClient : public QObject {
*/
void cmdAllow_Blankposting(int argc, QStringList argv);
+ /**
+ * @brief Looks up info on a ban.
+ *
+ * @details If it is called with **one argument**, that argument is the ban ID to look up.
+ *
+ * If it is called with **two arguments**, then the first argument is either a ban ID, an IPID,
+ * or an HDID, and the the second argument specifies the ID type.
+ *
+ * @iscommand
+ */
+ void cmdBanInfo(int argc, QStringList argv);
+
+ /**
+ * @brief Reloads all server configuration files.
+ *
+ * @details No arguments.
+ *
+ * @iscommand
+ */
+ void cmdReload(int argc, QStringList argv);
+
///@}
/**
@@ -1154,28 +1100,6 @@ class AOClient : public QObject {
*/
///@{
- /**
- * @brief Plays music in the area.
- *
- * @details The arguments are **the song's filepath** originating from `base/sounds/music/`,
- * or **the song's URL** if it's a stream.
- *
- * As described above, this command can be used to play songs by URL (for clients at and above version 2.9),
- * but it can also be used to play songs locally available for the clients but not listed in the music list.
- *
- * @iscommand
- */
- void cmdPlay(int argc, QStringList argv);
-
- /**
- * @brief A global message expressing that the client needs something (generally: players for something).
- *
- * @details The arguments are **the message** that the client wants to send.
- *
- * @iscommand
- */
- void cmdNeed(int argc, QStringList argv);
-
/**
* @brief Flips a coin, returning heads or tails.
*
@@ -1206,24 +1130,6 @@ class AOClient : public QObject {
*/
void cmdRollP(int argc, QStringList argv);
- /**
- * @brief Sets the `/doc` to a custom text.
- *
- * @details The arguments are **the text** that the client wants to set the doc to.
- *
- * @iscommand
- */
- void cmdDoc(int argc, QStringList argv);
-
- /**
- * @brief Sets the `/doc` to `"No document."`.
- *
- * @details No arguments.
- *
- * @iscommand
- */
- void cmdClearDoc(int argc, QStringList argv);
-
/**
* @brief Gets or sets the global or one of the area-specific timers.
*
@@ -1245,29 +1151,6 @@ class AOClient : public QObject {
*/
void cmdTimer(int argc, QStringList argv);
- /**
- * @brief Changes the evidence mod in the area.
- *
- * @details The only argument is the **evidence mod** to change to.
- *
- * @iscommand
- *
- * @see AreaData::EvidenceMod
- */
- void cmdEvidenceMod(int argc, QStringList argv);
-
- /**
- * @brief Changes position of two pieces of evidence in the area.
- *
- * @details The two arguments are the indices of the evidence items you want to swap the position of.
- *
- * @iscommand
- *
- * @see Area::Evidence_Swap
- *
- */
- void cmdEvidence_Swap(int argc, QStringList argv);
-
/**
* @brief Changes the subtheme of the clients in the current area.
*
@@ -1305,51 +1188,13 @@ class AOClient : public QObject {
void cmdNoteCardClear(int argc, QStringList argv);
/**
- * @brief Sets are to PLAYBACK mode
+ * @brief Randomly selects an answer from 8ball.txt to a question.
*
- * @details Enables control over the stored testimony, prevent new messages to be added and
- * allows people to navigate trough it using > and <.
+ * @details The only argument is the question the client wants answered.
+ *
+ * @iscommand
*/
- void cmdExamine(int argc, QStringList argv);
-
- /**
- * @brief Enables the testimony recording functionality.
- *
- * @details Any IC-Message send after this command is issues will be recorded by the testimony recorder.
- */
- void cmdTestify(int argc, QStringList argv);
-
- /**
- * @brief Allows user to update the currently displayed IC-Message from the testimony replay.
- *
- * @details Using this command replaces the content of the current statement entirely. It does not append information.
- */
- void cmdUpdateStatement(int argc, QStringList argv);
-
- /**
- * @brief Deletes a statement from the testimony.
- *
- * @details Using this deletes the entire entry in the QVector and resizes it appropriately to prevent empty record indices.
- */
- void cmdDeleteStatement(int argc, QStringList argv);
-
- /**
- * @brief Pauses testimony playback.
- *
- * @details Disables the testimony playback controls.
- */
- void cmdPauseTestimony(int argc, QStringList argv);
-
-
- /**
- * @brief
- *
- * @details
- *
- */
- void cmdAddStatement(int argc, QStringList argv);
-
- // Messaging/Client
+ void cmd8Ball(int argc, QStringList argv);
///@}
@@ -1436,13 +1281,65 @@ class AOClient : public QObject {
void cmdPM(int argc, QStringList argv);
/**
- * @brief Randomly selects an answer from 8ball.txt to a question.
+ * @brief A global message expressing that the client needs something (generally: players for something).
*
- * @details The only argument is the question the client wants answered.
+ * @details The arguments are **the message** that the client wants to send.
*
* @iscommand
*/
- void cmd8Ball(int argc, QStringList argv);
+ void cmdNeed(int argc, QStringList argv);
+
+ /**
+ * @brief Sends out a decorated global message, for announcements.
+ *
+ * @details The arguments are **the message** that the client wants to send.
+ *
+ * @iscommand
+ *
+ * @see AOClient::cmdG()
+ */
+ void cmdAnnounce(int argc, QStringList argv);
+
+ /**
+ * @brief Sends a message in the server-wide, moderator only chat.
+ *
+ * @details The arguments are **the message** that the client wants to send.
+ *
+ * @iscommand
+ */
+ void cmdM(int argc, QStringList argv);
+
+ /**
+ * @brief Sends out a global message that is marked with an `[M]` to mean it is coming from a moderator.
+ *
+ * @details The arguments are **the message** that the client wants to send.
+ *
+ * @iscommand
+ *
+ * @see AOClient::cmdG()
+ */
+ void cmdGM(int argc, QStringList argv);
+
+ /**
+ * @brief Sends out a local message that is marked with an `[M]` to mean it is coming from a moderator.
+ *
+ * @details The arguments are **the message** that the client wants to send.
+ *
+ * @iscommand
+ *
+ * @see AOClient::cmdLM()
+ */
+ void cmdLM(int argc, QStringList argv);
+
+ ///@}
+
+ /**
+ * @name Fun
+ *
+ * @brief All functions that detail the actions of commands,
+ * that are related to various kinds of fun moderator commands.
+ */
+ ///@{
/**
* @brief Replaces a target client's in-character messages with strings randomly selected from gimp.txt.
@@ -1497,36 +1394,156 @@ class AOClient : public QObject {
* @iscommand
*/
void cmdUnShake(int argc, QStringList argv);
-
+
+ ///@}
+
/**
- * @brief Reloads all server configuration files.
+ * @name Casing
+ *
+ * @brief All functions that detail the actions of commands,
+ * that are related to casing.
+ */
+ ///@{
+
+ /**
+ * @brief Sets the `/doc` to a custom text.
+ *
+ * @details The arguments are **the text** that the client wants to set the doc to.
+ *
+ * @iscommand
+ */
+ void cmdDoc(int argc, QStringList argv);
+
+ /**
+ * @brief Sets the `/doc` to `"No document."`.
*
* @details No arguments.
- *
- * @iscommand
- */
- void cmdReload(int argc, QStringList argv);
-
- /**
- * @brief Sends an out-of-character message with the judgelog of an area.
- *
- * @details No arguments.
- *
- * @iscommand
- */
- void cmdJudgeLog(int argc, QStringList argv);
-
- /**
- * @brief Looks up info on a ban.
- *
- * @details If it is called with **one argument**, that argument is the ban ID to look up.
- *
- * If it is called with **two arguments**, then the first argument is either a ban ID, an IPID,
- * or an HDID, and the the second argument specifies the ID type.
*
* @iscommand
*/
- void cmdBanInfo(int argc, QStringList argv);
+ void cmdClearDoc(int argc, QStringList argv);
+
+ /**
+ * @brief Changes the evidence mod in the area.
+ *
+ * @details The only argument is the **evidence mod** to change to.
+ *
+ * @iscommand
+ *
+ * @see AreaData::EvidenceMod
+ */
+ void cmdEvidenceMod(int argc, QStringList argv);
+
+ /**
+ * @brief Changes position of two pieces of evidence in the area.
+ *
+ * @details The two arguments are the indices of the evidence items you want to swap the position of.
+ *
+ * @iscommand
+ *
+ * @see Area::Evidence_Swap
+ *
+ */
+ void cmdEvidence_Swap(int argc, QStringList argv);
+
+ /**
+ * @brief Sets are to PLAYBACK mode
+ *
+ * @details Enables control over the stored testimony, prevent new messages to be added and
+ * allows people to navigate trough it using > and <.
+ */
+ void cmdExamine(int argc, QStringList argv);
+
+ /**
+ * @brief Enables the testimony recording functionality.
+ *
+ * @details Any IC-Message send after this command is issues will be recorded by the testimony recorder.
+ */
+ void cmdTestify(int argc, QStringList argv);
+
+ /**
+ * @brief Allows user to update the currently displayed IC-Message from the testimony replay.
+ *
+ * @details Using this command replaces the content of the current statement entirely. It does not append information.
+ */
+ void cmdUpdateStatement(int argc, QStringList argv);
+
+ /**
+ * @brief Deletes a statement from the testimony.
+ *
+ * @details Using this deletes the entire entry in the QVector and resizes it appropriately to prevent empty record indices.
+ */
+ void cmdDeleteStatement(int argc, QStringList argv);
+
+ /**
+ * @brief Pauses testimony playback.
+ *
+ * @details Disables the testimony playback controls.
+ */
+ void cmdPauseTestimony(int argc, QStringList argv);
+
+ /**
+ * @brief Adds a statement to an existing testimony.
+ *
+ * @details Inserts new statement after the currently displayed recorded message. Increases the index by 1.
+ *
+ */
+ void cmdAddStatement(int argc, QStringList argv);
+
+ ///@}
+
+ /**
+ * @name Music
+ *
+ * @brief All functions that detail the actions of commands,
+ * that are also related to music in some way.
+ */
+ ///@{
+
+ /**
+ * @brief Plays music in the area.
+ *
+ * @details The arguments are **the song's filepath** originating from `base/sounds/music/`,
+ * or **the song's URL** if it's a stream.
+ *
+ * As described above, this command can be used to play songs by URL (for clients at and above version 2.9),
+ * but it can also be used to play songs locally available for the clients but not listed in the music list.
+ *
+ * @iscommand
+ */
+ void cmdPlay(int argc, QStringList argv);
+
+ /**
+ * @brief DJ-blocks a client.
+ *
+ * @details The only argument is the **target client's user ID**.
+ *
+ * @iscommand
+ *
+ * @see #is_dj_blocked
+ */
+ void cmdBlockDj(int argc, QStringList argv);
+
+ /**
+ * @brief Removes the DJ-blocked status from a client.
+ *
+ * @details The only argument is the **target client's user ID**.
+ *
+ * @iscommand
+ *
+ * @see #is_dj_blocked
+ */
+ void cmdUnBlockDj(int argc, QStringList argv);
+
+ /**
+ * @brief Returns the currently playing music in the area, and who played it.
+ *
+ * @details No arguments.
+ *
+ * @iscommand
+ */
+ void cmdCurrentMusic(int argc, QStringList argv);
+
///@}
@@ -1539,6 +1556,15 @@ class AOClient : public QObject {
*/
///@{
+ /**
+ * @brief Literally just an invalid default command. That's it.
+ *
+ * @note Can be used as a base for future commands.
+ *
+ * @iscommand
+ */
+ void cmdDefault(int argc, QStringList argv);
+
/**
* @brief Returns a textual representation of the time left in an area's Timer.
*
diff --git a/src/commands.cpp b/src/commands.cpp
index e6dd316..4742d2a 100644
--- a/src/commands.cpp
+++ b/src/commands.cpp
@@ -25,55 +25,6 @@ void AOClient::cmdDefault(int argc, QStringList argv)
return;
}
-void AOClient::cmdLogin(int argc, QStringList argv)
-{
- if (authenticated) {
- sendServerMessage("You are already logged in!");
- return;
- }
-
- if (server->auth_type == "simple") {
- if (server->modpass == "") {
- sendServerMessage("No modpass is set! Please set a modpass before authenticating.");
- }
- else if(argv[0] == server->modpass) {
- sendPacket("AUTH", {"1"}); // Client: "You were granted the Disable Modcalls button."
- sendServerMessage("Logged in as a moderator."); // pre-2.9.1 clients are hardcoded to display the mod UI when this string is sent in OOC
- authenticated = true;
- }
- else {
- sendPacket("AUTH", {"0"}); // Client: "Login unsuccessful."
- sendServerMessage("Incorrect password.");
- }
- server->areas.value(current_area)->logger->logLogin(this, authenticated, "moderator");
- }
- else if (server->auth_type == "advanced") {
- if (argc < 2) {
- sendServerMessage("You must specify a username and a password");
- return;
- }
- QString username = argv[0];
- QString password = argv[1];
- if (server->db_manager->authenticate(username, password)) {
- moderator_name = username;
- authenticated = true;
- sendPacket("AUTH", {"1"}); // Client: "You were granted the Disable Modcalls button."
- if (version.release <= 2 && version.major <= 9 && version.minor <= 0)
- sendServerMessage("Logged in as a moderator."); // pre-2.9.1 clients are hardcoded to display the mod UI when this string is sent in OOC
- sendServerMessage("Welcome, " + username);
- }
- else {
- sendPacket("AUTH", {"0"}); // Client: "Login unsuccessful."
- sendServerMessage("Incorrect password.");
- }
- server->areas.value(current_area)->logger->logLogin(this, authenticated, username);
- }
- else {
- qWarning() << "config.ini has an unrecognized auth_type!";
- sendServerMessage("Config.ini contains an invalid auth_type, please check your config.");
- }
-}
-
void AOClient::cmdGetAreas(int argc, QStringList argv)
{
QStringList entries;
@@ -187,39 +138,6 @@ void AOClient::cmdKick(int argc, QStringList argv)
sendServerMessage("User with ipid not found!");
}
-void AOClient::cmdChangeAuth(int argc, QStringList argv)
-{
- if (server->auth_type == "simple") {
- change_auth_started = true;
- sendServerMessage("WARNING!\nThis command will change how logging in as a moderator works.\nOnly proceed if you know what you are doing\nUse the command /rootpass to set the password for your root account.");
- }
-}
-
-void AOClient::cmdSetRootPass(int argc, QStringList argv)
-{
- if (!change_auth_started)
- return;
-
- sendServerMessage("Changing auth type and setting root password.\nLogin again with /login root [password]");
- authenticated = false;
- QSettings settings("config/config.ini", QSettings::IniFormat);
- settings.beginGroup("Options");
- settings.setValue("auth", "advanced");
- server->auth_type = "advanced";
-
-#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
- qsrand(QDateTime::currentMSecsSinceEpoch());
- quint32 upper_salt = qrand();
- quint32 lower_salt = qrand();
- quint64 salt_number = (upper_salt << 32) | lower_salt;
-#else
- quint64 salt_number = QRandomGenerator::system()->generate64();
-#endif
- QString salt = QStringLiteral("%1").arg(salt_number, 16, 16, QLatin1Char('0'));
-
- server->db_manager->createUser("root", salt, argv[0], ACLFlags.value("SUPER"));
-}
-
void AOClient::cmdSetBackground(int argc, QStringList argv)
{
AreaData* area = server->areas[current_area];
@@ -252,161 +170,7 @@ void AOClient::cmdBgUnlock(int argc, QStringList argv)
server->broadcast(AOPacket("CT", {"Server", current_char + " unlocked the background.", "1"}), current_area);
}
-void AOClient::cmdAddUser(int argc, QStringList argv)
-{
-#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
- qsrand(QDateTime::currentMSecsSinceEpoch());
- quint32 upper_salt = qrand();
- quint32 lower_salt = qrand();
- quint64 salt_number = (upper_salt << 32) | lower_salt;
-#else
- quint64 salt_number = QRandomGenerator::system()->generate64();
-#endif
- QString salt = QStringLiteral("%1").arg(salt_number, 16, 16, QLatin1Char('0'));
- if (server->db_manager->createUser(argv[0], salt, argv[1], ACLFlags.value("NONE")))
- sendServerMessage("Created user " + argv[0] + ".\nUse /addperm to modify their permissions.");
- else
- sendServerMessage("Unable to create user " + argv[0] + ".\nDoes a user with that name already exist?");
-}
-
-void AOClient::cmdRemoveUser(int argc, QStringList argv)
-{
- if (server->db_manager->deleteUser(argv[0]))
- sendServerMessage("Successfully removed user " + argv[0] + ".");
- else
- sendServerMessage("Unable to remove user " + argv[0] + ".\nDoes it exist?");
-}
-
-void AOClient::cmdListPerms(int argc, QStringList argv)
-{
- unsigned long long user_acl = server->db_manager->getACL(moderator_name);
- QStringList message;
- if (argc == 0) {
- // Just print out all permissions available to the user.
- message.append("You have been given the following permissions:");
- for (QString perm : ACLFlags.keys()) {
- if (perm == "NONE"); // don't need to list this one
- else if (perm == "SUPER") {
- if (user_acl == ACLFlags.value("SUPER")) // This has to be checked separately, because SUPER & anything will always be truthy
- message.append("SUPER (Be careful! This grants the user all permissions.)");
- }
- else if ((ACLFlags.value(perm) & user_acl) == 0); // user doesn't have this permission, don't print it
- else
- message.append(perm);
- }
- }
- else {
- if ((user_acl & ACLFlags.value("MODIFY_USERS")) == 0) {
- sendServerMessage("You do not have permission to view other users' permissions.");
- return;
- }
-
- message.append("User " + argv[0] + " has the following permissions:");
- unsigned long long acl = server->db_manager->getACL(argv[0]);
- if (acl == 0) {
- sendServerMessage("This user either doesn't exist, or has no permissions set.");
- return;
- }
-
- for (QString perm : ACLFlags.keys()) {
- if ((ACLFlags.value(perm) & acl) != 0 && perm != "SUPER") {
- message.append(perm);
- }
- }
- }
- sendServerMessage(message.join("\n"));
-}
-
-void AOClient::cmdAddPerms(int argc, QStringList argv)
-{
- unsigned long long user_acl = server->db_manager->getACL(moderator_name);
- argv[1] = argv[1].toUpper();
-
- if (!ACLFlags.keys().contains(argv[1])) {
- sendServerMessage("That permission doesn't exist!");
- return;
- }
-
- if (argv[1] == "SUPER") {
- if (user_acl != ACLFlags.value("SUPER")) {
- // This has to be checked separately, because SUPER & anything will always be truthy
- sendServerMessage("You aren't allowed to add that permission!");
- return;
- }
- }
- if (argv[1] == "NONE") {
- sendServerMessage("Added no permissions!");
- return;
- }
-
- unsigned long long newperm = ACLFlags.value(argv[1]);
- if ((newperm & user_acl) != 0) {
- if (server->db_manager->updateACL(argv[0], newperm, true))
- sendServerMessage("Successfully added permission " + argv[1] + " to user " + argv[0]);
- else
- sendServerMessage(argv[0] + " wasn't found!");
- return;
- }
-
- sendServerMessage("You aren't allowed to add that permission!");
-}
-
-void AOClient::cmdRemovePerms(int argc, QStringList argv)
-{
- unsigned long long user_acl = server->db_manager->getACL(moderator_name);
- argv[1] = argv[1].toUpper();
-
- if (!ACLFlags.keys().contains(argv[1])) {
- sendServerMessage("That permission doesn't exist!");
- return;
- }
-
- if (argv[0] == "root") {
- sendServerMessage("You cannot change the permissions of the root account!");
- return;
- }
-
- if (argv[1] == "SUPER") {
- if (user_acl != ACLFlags.value("SUPER")) {
- // This has to be checked separately, because SUPER & anything will always be truthy
- sendServerMessage("You aren't allowed to remove that permission!");
- return;
- }
- }
- if (argv[1] == "NONE") {
- sendServerMessage("Removed no permissions!");
- return;
- }
-
- unsigned long long newperm = ACLFlags.value(argv[1]);
- if ((newperm & user_acl) != 0) {
- if (server->db_manager->updateACL(argv[0], newperm, false))
- sendServerMessage("Successfully removed permission " + argv[1] + " from user " + argv[0]);
- else
- sendServerMessage(argv[0] + " wasn't found!");
- return;
- }
-
- sendServerMessage("You aren't allowed to remove that permission!");
-}
-
-void AOClient::cmdListUsers(int argc, QStringList argv)
-{
- QStringList users = server->db_manager->getUsers();
- sendServerMessage("All users:\n" + users.join("\n"));
-}
-
-void AOClient::cmdLogout(int argc, QStringList argv)
-{
- if (!authenticated) {
- sendServerMessage("You are not logged in!");
- return;
- }
- authenticated = false;
- moderator_name = "";
- sendPacket("AUTH", {"-1"}); // Client: "You were logged out."
-}
void AOClient::cmdPos(int argc, QStringList argv)
{
diff --git a/src/commands/authentication.cpp b/src/commands/authentication.cpp
new file mode 100644
index 0000000..fa0dd4d
--- /dev/null
+++ b/src/commands/authentication.cpp
@@ -0,0 +1,258 @@
+//////////////////////////////////////////////////////////////////////////////////////
+// akashi - a server for Attorney Online 2 //
+// Copyright (C) 2020 scatterflower //
+// //
+// 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 . //
+//////////////////////////////////////////////////////////////////////////////////////
+#include "include/aoclient.h"
+
+// Be sure to register the command in the header before adding it here!
+
+void AOClient::cmdLogin(int argc, QStringList argv)
+{
+ if (authenticated) {
+ sendServerMessage("You are already logged in!");
+ return;
+ }
+
+ if (server->auth_type == "simple") {
+ if (server->modpass == "") {
+ sendServerMessage("No modpass is set! Please set a modpass before authenticating.");
+ }
+ else if(argv[0] == server->modpass) {
+ sendPacket("AUTH", {"1"}); // Client: "You were granted the Disable Modcalls button."
+ sendServerMessage("Logged in as a moderator."); // pre-2.9.1 clients are hardcoded to display the mod UI when this string is sent in OOC
+ authenticated = true;
+ }
+ else {
+ sendPacket("AUTH", {"0"}); // Client: "Login unsuccessful."
+ sendServerMessage("Incorrect password.");
+ }
+ server->areas.value(current_area)->logger->logLogin(this, authenticated, "moderator");
+ }
+ else if (server->auth_type == "advanced") {
+ if (argc < 2) {
+ sendServerMessage("You must specify a username and a password");
+ return;
+ }
+ QString username = argv[0];
+ QString password = argv[1];
+ if (server->db_manager->authenticate(username, password)) {
+ moderator_name = username;
+ authenticated = true;
+ sendPacket("AUTH", {"1"}); // Client: "You were granted the Disable Modcalls button."
+ if (version.release <= 2 && version.major <= 9 && version.minor <= 0)
+ sendServerMessage("Logged in as a moderator."); // pre-2.9.1 clients are hardcoded to display the mod UI when this string is sent in OOC
+ sendServerMessage("Welcome, " + username);
+ }
+ else {
+ sendPacket("AUTH", {"0"}); // Client: "Login unsuccessful."
+ sendServerMessage("Incorrect password.");
+ }
+ server->areas.value(current_area)->logger->logLogin(this, authenticated, username);
+ }
+ else {
+ qWarning() << "config.ini has an unrecognized auth_type!";
+ sendServerMessage("Config.ini contains an invalid auth_type, please check your config.");
+ }
+}
+
+void AOClient::cmdChangeAuth(int argc, QStringList argv)
+{
+ if (server->auth_type == "simple") {
+ change_auth_started = true;
+ sendServerMessage("WARNING!\nThis command will change how logging in as a moderator works.\nOnly proceed if you know what you are doing\nUse the command /rootpass to set the password for your root account.");
+ }
+}
+
+void AOClient::cmdSetRootPass(int argc, QStringList argv)
+{
+ if (!change_auth_started)
+ return;
+
+ sendServerMessage("Changing auth type and setting root password.\nLogin again with /login root [password]");
+ authenticated = false;
+ QSettings settings("config/config.ini", QSettings::IniFormat);
+ settings.beginGroup("Options");
+ settings.setValue("auth", "advanced");
+ server->auth_type = "advanced";
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
+ qsrand(QDateTime::currentMSecsSinceEpoch());
+ quint32 upper_salt = qrand();
+ quint32 lower_salt = qrand();
+ quint64 salt_number = (upper_salt << 32) | lower_salt;
+#else
+ quint64 salt_number = QRandomGenerator::system()->generate64();
+#endif
+ QString salt = QStringLiteral("%1").arg(salt_number, 16, 16, QLatin1Char('0'));
+
+ server->db_manager->createUser("root", salt, argv[0], ACLFlags.value("SUPER"));
+}
+
+void AOClient::cmdAddUser(int argc, QStringList argv)
+{
+#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
+ qsrand(QDateTime::currentMSecsSinceEpoch());
+ quint32 upper_salt = qrand();
+ quint32 lower_salt = qrand();
+ quint64 salt_number = (upper_salt << 32) | lower_salt;
+#else
+ quint64 salt_number = QRandomGenerator::system()->generate64();
+#endif
+ QString salt = QStringLiteral("%1").arg(salt_number, 16, 16, QLatin1Char('0'));
+
+ if (server->db_manager->createUser(argv[0], salt, argv[1], ACLFlags.value("NONE")))
+ sendServerMessage("Created user " + argv[0] + ".\nUse /addperm to modify their permissions.");
+ else
+ sendServerMessage("Unable to create user " + argv[0] + ".\nDoes a user with that name already exist?");
+}
+
+void AOClient::cmdRemoveUser(int argc, QStringList argv)
+{
+ if (server->db_manager->deleteUser(argv[0]))
+ sendServerMessage("Successfully removed user " + argv[0] + ".");
+ else
+ sendServerMessage("Unable to remove user " + argv[0] + ".\nDoes it exist?");
+}
+
+void AOClient::cmdListPerms(int argc, QStringList argv)
+{
+ unsigned long long user_acl = server->db_manager->getACL(moderator_name);
+ QStringList message;
+ if (argc == 0) {
+ // Just print out all permissions available to the user.
+ message.append("You have been given the following permissions:");
+ for (QString perm : ACLFlags.keys()) {
+ if (perm == "NONE"); // don't need to list this one
+ else if (perm == "SUPER") {
+ if (user_acl == ACLFlags.value("SUPER")) // This has to be checked separately, because SUPER & anything will always be truthy
+ message.append("SUPER (Be careful! This grants the user all permissions.)");
+ }
+ else if ((ACLFlags.value(perm) & user_acl) == 0); // user doesn't have this permission, don't print it
+ else
+ message.append(perm);
+ }
+ }
+ else {
+ if ((user_acl & ACLFlags.value("MODIFY_USERS")) == 0) {
+ sendServerMessage("You do not have permission to view other users' permissions.");
+ return;
+ }
+
+ message.append("User " + argv[0] + " has the following permissions:");
+ unsigned long long acl = server->db_manager->getACL(argv[0]);
+ if (acl == 0) {
+ sendServerMessage("This user either doesn't exist, or has no permissions set.");
+ return;
+ }
+
+ for (QString perm : ACLFlags.keys()) {
+ if ((ACLFlags.value(perm) & acl) != 0 && perm != "SUPER") {
+ message.append(perm);
+ }
+ }
+ }
+ sendServerMessage(message.join("\n"));
+}
+
+void AOClient::cmdAddPerms(int argc, QStringList argv)
+{
+ unsigned long long user_acl = server->db_manager->getACL(moderator_name);
+ argv[1] = argv[1].toUpper();
+
+ if (!ACLFlags.keys().contains(argv[1])) {
+ sendServerMessage("That permission doesn't exist!");
+ return;
+ }
+
+ if (argv[1] == "SUPER") {
+ if (user_acl != ACLFlags.value("SUPER")) {
+ // This has to be checked separately, because SUPER & anything will always be truthy
+ sendServerMessage("You aren't allowed to add that permission!");
+ return;
+ }
+ }
+ if (argv[1] == "NONE") {
+ sendServerMessage("Added no permissions!");
+ return;
+ }
+
+ unsigned long long newperm = ACLFlags.value(argv[1]);
+ if ((newperm & user_acl) != 0) {
+ if (server->db_manager->updateACL(argv[0], newperm, true))
+ sendServerMessage("Successfully added permission " + argv[1] + " to user " + argv[0]);
+ else
+ sendServerMessage(argv[0] + " wasn't found!");
+ return;
+ }
+
+ sendServerMessage("You aren't allowed to add that permission!");
+}
+
+void AOClient::cmdRemovePerms(int argc, QStringList argv)
+{
+ unsigned long long user_acl = server->db_manager->getACL(moderator_name);
+ argv[1] = argv[1].toUpper();
+
+ if (!ACLFlags.keys().contains(argv[1])) {
+ sendServerMessage("That permission doesn't exist!");
+ return;
+ }
+
+ if (argv[0] == "root") {
+ sendServerMessage("You cannot change the permissions of the root account!");
+ return;
+ }
+
+ if (argv[1] == "SUPER") {
+ if (user_acl != ACLFlags.value("SUPER")) {
+ // This has to be checked separately, because SUPER & anything will always be truthy
+ sendServerMessage("You aren't allowed to remove that permission!");
+ return;
+ }
+ }
+ if (argv[1] == "NONE") {
+ sendServerMessage("Removed no permissions!");
+ return;
+ }
+
+ unsigned long long newperm = ACLFlags.value(argv[1]);
+ if ((newperm & user_acl) != 0) {
+ if (server->db_manager->updateACL(argv[0], newperm, false))
+ sendServerMessage("Successfully removed permission " + argv[1] + " from user " + argv[0]);
+ else
+ sendServerMessage(argv[0] + " wasn't found!");
+ return;
+ }
+
+ sendServerMessage("You aren't allowed to remove that permission!");
+}
+
+void AOClient::cmdListUsers(int argc, QStringList argv)
+{
+ QStringList users = server->db_manager->getUsers();
+ sendServerMessage("All users:\n" + users.join("\n"));
+}
+
+void AOClient::cmdLogout(int argc, QStringList argv)
+{
+ if (!authenticated) {
+ sendServerMessage("You are not logged in!");
+ return;
+ }
+ authenticated = false;
+ moderator_name = "";
+ sendPacket("AUTH", {"-1"}); // Client: "You were logged out."
+}
From 885de7141704b5e97fc87a55278474686e9dcd55 Mon Sep 17 00:00:00 2001
From: MangosArentLiterature
<58055358+MangosArentLiterature@users.noreply.github.com>
Date: Thu, 15 Apr 2021 17:55:15 -0500
Subject: [PATCH 2/5] Split up commands.cpp
the beast has been vanquished
---
akashi.pro | 8 +-
include/aoclient.h | 10 -
src/commands.cpp | 1446 -------------------------------
src/commands/area.cpp | 285 ++++++
src/commands/authentication.cpp | 1 +
src/commands/casing.cpp | 167 ++++
src/commands/command_helper.cpp | 207 +++++
src/commands/messaging.cpp | 276 ++++++
src/commands/moderation.cpp | 389 +++++++++
src/commands/music.cpp | 80 ++
src/commands/roleplay.cpp | 190 ++++
11 files changed, 1602 insertions(+), 1457 deletions(-)
create mode 100644 src/commands/area.cpp
create mode 100644 src/commands/casing.cpp
create mode 100644 src/commands/command_helper.cpp
create mode 100644 src/commands/messaging.cpp
create mode 100644 src/commands/moderation.cpp
create mode 100644 src/commands/music.cpp
create mode 100644 src/commands/roleplay.cpp
diff --git a/akashi.pro b/akashi.pro
index f176d52..28d80f4 100644
--- a/akashi.pro
+++ b/akashi.pro
@@ -31,8 +31,14 @@ SOURCES += src/advertiser.cpp \
src/aopacket.cpp \
src/area_data.cpp \
src/commands.cpp \
- src/commands/areas.cpp \
+ src/commands/area.cpp \
src/commands/authentication.cpp \
+ src/commands/casing.cpp \
+ src/commands/command_helper.cpp \
+ src/commands/messaging.cpp \
+ src/commands/moderation.cpp \
+ src/commands/music.cpp \
+ src/commands/roleplay.cpp \
src/config_manager.cpp \
src/db_manager.cpp \
src/logger.cpp \
diff --git a/include/aoclient.h b/include/aoclient.h
index 16b4cfd..5035b6b 100644
--- a/include/aoclient.h
+++ b/include/aoclient.h
@@ -1331,16 +1331,6 @@ class AOClient : public QObject {
*/
void cmdLM(int argc, QStringList argv);
- ///@}
-
- /**
- * @name Fun
- *
- * @brief All functions that detail the actions of commands,
- * that are related to various kinds of fun moderator commands.
- */
- ///@{
-
/**
* @brief Replaces a target client's in-character messages with strings randomly selected from gimp.txt.
*
diff --git a/src/commands.cpp b/src/commands.cpp
index 4742d2a..9824cfa 100644
--- a/src/commands.cpp
+++ b/src/commands.cpp
@@ -18,1449 +18,3 @@
#include "include/aoclient.h"
// Be sure to register the command in the header before adding it here!
-
-void AOClient::cmdDefault(int argc, QStringList argv)
-{
- sendServerMessage("Invalid command.");
- return;
-}
-
-void AOClient::cmdGetAreas(int argc, QStringList argv)
-{
- QStringList entries;
- entries.append("== Area List ==");
- for (int i = 0; i < server->area_names.length(); i++) {
- QStringList cur_area_lines = buildAreaList(i);
- entries.append(cur_area_lines);
- }
- sendServerMessage(entries.join("\n"));
-}
-
-void AOClient::cmdGetArea(int argc, QStringList argv)
-{
- QStringList entries = buildAreaList(current_area);
- sendServerMessage(entries.join("\n"));
-}
-
-void AOClient::cmdBan(int argc, QStringList argv)
-{
- QString args_str = argv[1];
- if (argc > 2) {
- for (int i = 2; i < argc; i++)
- args_str += " " + argv[i];
- }
-
- DBManager::BanInfo ban;
-
- QRegularExpression quoteMatcher("['\"](.+?)[\"']");
- QRegularExpressionMatchIterator matches = quoteMatcher.globalMatch(args_str);
- QList unquoted_args;
- while (matches.hasNext()) {
- QRegularExpressionMatch match = matches.next();
- unquoted_args.append(match.captured(1));
- }
-
- QString duration = "perma";
-
- if (unquoted_args.length() < 1) {
- sendServerMessage("Invalid syntax. Usage:\n/ban \"\" \"\"");
- return;
- }
-
- ban.reason = unquoted_args.at(0);
- if (unquoted_args.length() > 1)
- duration = unquoted_args.at(1);
-
- long long duration_seconds = 0;
- if (duration == "perma")
- duration_seconds = -2;
- else
- duration_seconds = parseTime(duration);
-
- if (duration_seconds == -1) {
- sendServerMessage("Invalid time format. Format example: 1h30m");
- return;
- }
-
- ban.duration = duration_seconds;
-
- ban.ipid = argv[0];
- ban.time = QDateTime::currentDateTime().toSecsSinceEpoch();
- bool ban_logged = false;
- int kick_counter = 0;
-
- if (argc > 2) {
- for (int i = 2; i < argv.length(); i++) {
- ban.reason += " " + argv[i];
- }
- }
-
- for (AOClient* client : server->getClientsByIpid(ban.ipid)) {
- if (!ban_logged) {
- ban.ip = client->remote_ip;
- ban.hdid = client->hwid;
- server->db_manager->addBan(ban);
- sendServerMessage("Banned user with ipid " + ban.ipid + " for reason: " + ban.reason);
- ban_logged = true;
- }
- client->sendPacket("KB", {ban.reason + "\nID: " + QString::number(server->db_manager->getBanID(ban.ip)) + "\nUntil: " + QDateTime::fromSecsSinceEpoch(ban.time).addSecs(ban.duration).toString("dd.MM.yyyy, hh:mm")});
- client->socket->close();
- kick_counter++;
- }
-
- if (kick_counter > 1)
- sendServerMessage("Kicked " + QString::number(kick_counter) + " clients with matching ipids.");
- if (!ban_logged)
- sendServerMessage("User with ipid not found!");
-}
-
-void AOClient::cmdKick(int argc, QStringList argv)
-{
- QString target_ipid = argv[0];
- QString reason = argv[1];
- int kick_counter = 0;
-
- if (argc > 2) {
- for (int i = 2; i < argv.length(); i++) {
- reason += " " + argv[i];
- }
- }
-
- for (AOClient* client : server->getClientsByIpid(target_ipid)) {
- client->sendPacket("KK", {reason});
- client->socket->close();
- kick_counter++;
- }
-
- if (kick_counter > 0)
- sendServerMessage("Kicked " + QString::number(kick_counter) + " client(s) with ipid " + target_ipid + " for reason: " + reason);
- else
- sendServerMessage("User with ipid not found!");
-}
-
-void AOClient::cmdSetBackground(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (authenticated || !area->bg_locked) {
- if (server->backgrounds.contains(argv[0])) {
- area->background = argv[0];
- server->broadcast(AOPacket("BN", {argv[0]}), current_area);
- sendServerMessageArea(current_char + " changed the background to " + argv[0]);
- }
- else {
- sendServerMessage("Invalid background name.");
- }
- }
- else {
- sendServerMessage("This area's background is locked.");
- }
-}
-
-void AOClient::cmdBgLock(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- area->bg_locked = true;
- server->broadcast(AOPacket("CT", {"Server", current_char + " locked the background.", "1"}), current_area);
-}
-
-void AOClient::cmdBgUnlock(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- area->bg_locked = false;
- server->broadcast(AOPacket("CT", {"Server", current_char + " unlocked the background.", "1"}), current_area);
-}
-
-
-
-void AOClient::cmdPos(int argc, QStringList argv)
-{
- changePosition(argv[0]);
- updateEvidenceList(server->areas[current_area]);
-}
-
-void AOClient::cmdForcePos(int argc, QStringList argv)
-{
- bool ok;
- QList targets;
- AreaData* area = server->areas[current_area];
- int target_id = argv[1].toInt(&ok);
- int forced_clients = 0;
- if (!ok && argv[1] != "*") {
- sendServerMessage("That does not look like a valid ID.");
- return;
- }
- else if (ok) {
- AOClient* target_client = server->getClientByID(target_id);
- if (target_client != nullptr)
- targets.append(target_client);
- else {
- sendServerMessage("Target ID not found!");
- return;
- }
- }
-
- else if (argv[1] == "*") { // force all clients in the area
- for (AOClient* client : server->clients) {
- if (client->current_area == current_area)
- targets.append(client);
- }
- }
- for (AOClient* target : targets) {
- target->sendServerMessage("Position forcibly changed by CM.");
- target->changePosition(argv[0]);
- forced_clients++;
- }
- sendServerMessage("Forced " + QString::number(forced_clients) + " into pos " + argv[0] + ".");
-}
-
-void AOClient::cmdG(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- QString sender_area = server->area_names.value(current_area);
- QString sender_message = argv.join(" ");
- for (AOClient* client : server->clients) {
- if (client->global_enabled)
- client->sendPacket("CT", {"[G][" + sender_area + "]" + sender_name, sender_message});
- }
- return;
-}
-
-void AOClient::cmdNeed(int argc, QStringList argv)
-{
- QString sender_area = server->area_names.value(current_area);
- QString sender_message = argv.join(" ");
- sendServerBroadcast({"=== Advert ===\n[" + sender_area + "] needs " + sender_message+ "."});
-}
-
-void AOClient::cmdFlip(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- QStringList faces = {"heads","tails"};
- QString face = faces[AOClient::genRand(0,1)];
- sendServerMessage(sender_name + " flipped a coin and got " + face + ".");
-}
-
-void AOClient::cmdRoll(int argc, QStringList argv)
-{
- diceThrower(argc, argv, RollType::ROLL);
-}
-
-void AOClient::cmdRollP(int argc, QStringList argv)
-{
- diceThrower(argc, argv, RollType::ROLLP);
-}
-
-void AOClient::cmdDoc(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- AreaData* area = server->areas[current_area];
- if (argc == 0) {
- sendServerMessage("Document: " + area->document);
- }
- else {
- area->document = argv.join(" ");
- sendServerMessageArea(sender_name + " changed the document.");
- }
-}
-
-void AOClient::cmdClearDoc(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- AreaData* area = server->areas[current_area];
- area->document = "No document.";
- sendServerMessageArea(sender_name + " cleared the document.");
-}
-
-void AOClient::cmdCM(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- AreaData* area = server->areas[current_area];
- if (area->is_protected) {
- sendServerMessage("This area is protected, you may not become CM.");
- return;
- }
- else if (area->owners.isEmpty()) { // no one owns this area, and it's not protected
- area->owners.append(id);
- area->invited.append(id);
- sendServerMessageArea(sender_name + " is now CM in this area.");
- arup(ARUPType::CM, true);
- }
- else if (!area->owners.contains(id)) { // there is already a CM, and it isn't us
- sendServerMessage("You cannot become a CM in this area.");
- }
- else if (argc == 1) { // we are CM, and we want to make ID argv[0] also CM
- bool ok;
- AOClient* owner_candidate = server->getClientByID(argv[0].toInt(&ok));
- if (!ok) {
- sendServerMessage("That doesn't look like a valid ID.");
- return;
- }
- if (owner_candidate == nullptr) {
- sendServerMessage("Unable to find client with ID " + argv[0] + ".");
- return;
- }
- area->owners.append(owner_candidate->id);
- sendServerMessageArea(owner_candidate->ooc_name + " is now CM in this area.");
- arup(ARUPType::CM, true);
- }
- else {
- sendServerMessage("You are already a CM in this area.");
- }
-}
-
-void AOClient::cmdUnCM(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- int removed = area->owners.removeAll(id);
- area->invited.removeAll(id);
- sendServerMessage("You are no longer CM in this area.");
- arup(ARUPType::CM, true);
- if (area->owners.isEmpty()) {
- area->invited.clear();
- if (area->locked != AreaData::FREE) {
- area->locked = AreaData::FREE;
- arup(ARUPType::LOCKED, true);
- }
- }
-}
-
-void AOClient::cmdInvite(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- bool ok;
- int invited_id = argv[0].toInt(&ok);
- if (!ok) {
- sendServerMessage("That does not look like a valid ID.");
- return;
- }
- else if (server->getClientByID(invited_id) == nullptr) {
- sendServerMessage("No client with that ID found.");
- return;
- }
- else if (area->invited.contains(invited_id)) {
- sendServerMessage("That ID is already on the invite list.");
- return;
- }
- area->invited.append(invited_id);
- sendServerMessage("You invited ID " + argv[0]);
-}
-
-void AOClient::cmdUnInvite(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- bool ok;
- int uninvited_id = argv[0].toInt(&ok);
- if (!ok) {
- sendServerMessage("That does not look like a valid ID.");
- return;
- }
- else if (server->getClientByID(uninvited_id) == nullptr) {
- sendServerMessage("No client with that ID found.");
- return;
- }
- else if (area->owners.contains(uninvited_id)) {
- sendServerMessage("You cannot uninvite a CM!");
- return;
- }
- else if (!area->invited.contains(uninvited_id)) {
- sendServerMessage("That ID is not on the invite list.");
- return;
- }
- area->invited.removeAll(uninvited_id);
- sendServerMessage("You uninvited ID " + argv[0]);
-}
-
-void AOClient::cmdLock(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->locked == AreaData::LockStatus::LOCKED) {
- sendServerMessage("This area is already locked.");
- return;
- }
- sendServerMessageArea("This area is now locked.");
- area->locked = AreaData::LockStatus::LOCKED;
- for (AOClient* client : server->clients) {
- if (client->current_area == current_area && client->joined) {
- area->invited.append(client->id);
- }
- }
- arup(ARUPType::LOCKED, true);
-}
-
-void AOClient::cmdSpectatable(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->locked == AreaData::LockStatus::SPECTATABLE) {
- sendServerMessage("This area is already in spectate mode.");
- return;
- }
- sendServerMessageArea("This area is now spectatable.");
- area->locked = AreaData::LockStatus::SPECTATABLE;
- for (AOClient* client : server->clients) {
- if (client->current_area == current_area && client->joined) {
- area->invited.append(client->id);
- }
- }
- arup(ARUPType::LOCKED, true);
-}
-
-void AOClient::cmdUnLock(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->locked == AreaData::LockStatus::FREE) {
- sendServerMessage("This area is not locked.");
- return;
- }
- sendServerMessageArea("This area is now unlocked.");
- area->locked = AreaData::LockStatus::FREE;
- arup(ARUPType::LOCKED, true);
-}
-
-void AOClient::cmdTimer(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
-
- // Called without arguments
- // Shows a brief of all timers
- if (argc == 0) {
- QStringList timers;
- timers.append("Currently active timers:");
- for (int i = 0; i <= 4; i++) {
- timers.append(getAreaTimer(area->index, i));
- }
- sendServerMessage(timers.join("\n"));
- return;
- }
-
- // Called with more than one argument
- bool ok;
- int timer_id = argv[0].toInt(&ok);
- if (!ok || timer_id < 0 || timer_id > 4) {
- sendServerMessage("Invalid timer ID. Timer ID must be a whole number between 0 and 4.");
- return;
- }
-
- // Called with one argument
- // Shows the status of one timer
- if (argc == 1) {
- sendServerMessage(getAreaTimer(area->index, timer_id));
- return;
- }
-
- // Called with more than one argument
- // Updates the state of a timer
-
- // Select the proper timer
- // Check against permissions if global timer is selected
- QTimer* requested_timer;
- if (timer_id == 0) {
- if (!checkAuth(ACLFlags.value("GLOBAL_TIMER"))) {
- sendServerMessage("You are not authorized to alter the global timer.");
- return;
- }
- requested_timer = server->timer;
- }
- else
- requested_timer = area->timers[timer_id - 1];
-
- AOPacket show_timer("TI", {QString::number(timer_id), "2"});
- AOPacket hide_timer("TI", {QString::number(timer_id), "3"});
- bool is_global = timer_id == 0;
-
- // Set the timer's time remaining if the second
- // argument is a valid time
- QTime requested_time = QTime::fromString(argv[1], "hh:mm:ss");
- if (requested_time.isValid()) {
- requested_timer->setInterval(QTime(0,0).msecsTo(requested_time));
- requested_timer->start();
- sendServerMessage("Set timer " + QString::number(timer_id) + " to " + argv[1] + ".");
- AOPacket update_timer("TI", {QString::number(timer_id), "0", QString::number(QTime(0,0).msecsTo(requested_time))});
- is_global ? server->broadcast(show_timer) : server->broadcast(show_timer, current_area); // Show the timer
- is_global ? server->broadcast(update_timer) : server->broadcast(update_timer, current_area);
- return;
- }
- // Otherwise, update the state of the timer
- else {
- if (argv[1] == "start") {
- requested_timer->start();
- sendServerMessage("Started timer " + QString::number(timer_id) + ".");
- AOPacket update_timer("TI", {QString::number(timer_id), "0", QString::number(QTime(0,0).msecsTo(QTime(0,0).addMSecs(requested_timer->remainingTime())))});
- is_global ? server->broadcast(show_timer) : server->broadcast(show_timer, current_area);
- is_global ? server->broadcast(update_timer) : server->broadcast(update_timer, current_area);
- }
- else if (argv[1] == "pause" || argv[1] == "stop") {
- requested_timer->setInterval(requested_timer->remainingTime());
- requested_timer->stop();
- sendServerMessage("Stopped timer " + QString::number(timer_id) + ".");
- AOPacket update_timer("TI", {QString::number(timer_id), "1", QString::number(QTime(0,0).msecsTo(QTime(0,0).addMSecs(requested_timer->interval())))});
- is_global ? server->broadcast(update_timer) : server->broadcast(update_timer, current_area);
- }
- else if (argv[1] == "hide" || argv[1] == "unset") {
- requested_timer->setInterval(0);
- requested_timer->stop();
- sendServerMessage("Hid timer " + QString::number(timer_id) + ".");
- // Hide the timer
- is_global ? server->broadcast(hide_timer) : server->broadcast(hide_timer, current_area);
- }
- }
-}
-
-void AOClient::cmdEvidenceMod(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- argv[0] = argv[0].toLower();
- if (argv[0] == "cm")
- area->evi_mod = AreaData::EvidenceMod::CM;
- else if (argv[0] == "mod")
- area->evi_mod = AreaData::EvidenceMod::MOD;
- else if (argv[0] == "hiddencm")
- area->evi_mod = AreaData::EvidenceMod::HIDDEN_CM;
- else if (argv[0] == "ffa")
- area->evi_mod = AreaData::EvidenceMod::FFA;
- else {
- sendServerMessage("Invalid evidence mod.");
- return;
- }
- sendServerMessage("Changed evidence mod.");
-
- // Resend evidence lists to everyone in the area
- sendEvidenceList(area);
-}
-
-void AOClient::cmdArea(int argc, QStringList argv)
-{
- bool ok;
- int new_area = argv[0].toInt(&ok);
- if (!ok || new_area >= server->areas.size() || new_area < 0) {
- sendServerMessage("That does not look like a valid area ID.");
- return;
- }
- changeArea(new_area);
-}
-
-void AOClient::cmdPlay(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- QString song = argv.join(" ");
- area->current_music = song;
- area->music_played_by = showname;
- AOPacket music_change("MC", {song, QString::number(server->getCharID(current_char)), showname, "1", "0"});
- server->broadcast(music_change, current_area);
-}
-
-void AOClient::cmdAreaKick(int argc, QStringList argv)
-{
- bool ok;
- int idx = argv[0].toInt(&ok);
- if (!ok) {
- sendServerMessage("That does not look like a valid ID.");
- return;
- }
- AOClient* client_to_kick = server->getClientByID(idx);
- if (client_to_kick == nullptr) {
- sendServerMessage("No client with that ID found.");
- return;
- }
- client_to_kick->changeArea(0);
- sendServerMessage("Client " + argv[0] + " kicked back to area 0.");
-}
-
-void AOClient::cmdSwitch(int argc, QStringList argv)
-{
- int char_id = server->getCharID(argv.join(" "));
- if (char_id == -1) {
- sendServerMessage("That does not look like a valid character.");
- return;
- }
- changeCharacter(char_id);
-}
-
-void AOClient::cmdRandomChar(int argc, QStringList argv)
-{
- int char_id = genRand(0, server->characters.size() - 1);
- changeCharacter(char_id);
-}
-
-void AOClient::cmdToggleGlobal(int argc, QStringList argv)
-{
- global_enabled = !global_enabled;
- QString str_en = global_enabled ? "shown" : "hidden";
- sendServerMessage("Global chat set to " + str_en);
-}
-
-void AOClient::cmdMods(int argc, QStringList argv)
-{
- QStringList entries;
- int online_count = 0;
- for (AOClient* client : server->clients) {
- if (client->authenticated) {
- entries << "---";
- if (server->auth_type != "simple")
- entries << "Moderator: " + client->moderator_name;
- entries << "OOC name: " + client->ooc_name;
- entries << "ID: " + QString::number(client->id);
- entries << "Area: " + QString::number(client->current_area);
- entries << "Character: " + client->current_char;
- online_count++;
- }
- }
- entries << "---";
- entries << "Total online: " << QString::number(online_count);
- sendServerMessage(entries.join("\n"));
-}
-
-void AOClient::cmdHelp(int argc, QStringList argv)
-{
- QStringList entries;
- entries << "Allowed commands:";
- QMap::const_iterator i;
- for (i = commands.constBegin(); i!= commands.constEnd(); ++i) {
- CommandInfo info = i.value();
- if (checkAuth(info.acl_mask)) { // if we are allowed to use this command
- entries << "/" + i.key();
- }
- }
- sendServerMessage(entries.join("\n"));
-}
-
-void AOClient::cmdStatus(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- QString arg = argv[0].toLower();
- if (arg == "idle")
- area->status = AreaData::IDLE;
- else if (arg == "rp")
- area->status = AreaData::RP;
- else if (arg == "casing")
- area->status = AreaData::CASING;
- else if (arg == "looking-for-players" || arg == "lfp")
- area->status = AreaData::LOOKING_FOR_PLAYERS;
- else if (arg == "recess")
- area->status = AreaData::RECESS;
- else if (arg == "gaming")
- area->status = AreaData::GAMING;
- else {
- sendServerMessage("That does not look like a valid status. Valid statuses are idle, rp, casing, lfp, recess, gaming");
- return;
- }
- arup(ARUPType::STATUS, true);
-}
-
-void AOClient::cmdCurrentMusic(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->current_music != "" && area->current_music != "~stop.mp3") // dummy track for stopping music
- sendServerMessage("The current song is " + area->current_music + " played by " + area->music_played_by);
- else
- sendServerMessage("There is no music playing.");
-}
-
-void AOClient::cmdPM(int arc, QStringList argv)
-{
- bool ok;
- int target_id = argv.takeFirst().toInt(&ok); // using takeFirst removes the ID from our list of arguments...
- if (!ok) {
- sendServerMessage("That does not look like a valid ID.");
- return;
- }
- AOClient* target_client = server->getClientByID(target_id);
- if (target_client == nullptr) {
- sendServerMessage("No client with that ID found.");
- return;
- }
- QString message = argv.join(" "); //...which means it will not end up as part of the message
- target_client->sendServerMessage("Message from " + ooc_name + " (" + QString::number(id) + "): " + message);
-}
-
-void AOClient::cmdMOTD(int argc, QStringList argv)
-{
- if (argc == 0) {
- sendServerMessage("=== MOTD ===\r\n" + server->MOTD + "\r\n=============");
- }
- else if (argc > 0) {
- if (checkAuth(ACLFlags.value("MOTD"))) {
- QString MOTD = argv.join(" ");
- server->MOTD = MOTD;
- sendServerMessage("MOTD has been changed.");
- }
- else {
- sendServerMessage("You do not have permission to change the MOTD");
- }
- }
-}
-
-void AOClient::cmdAnnounce(int argc, QStringList argv)
-{
- sendServerBroadcast("=== Announcement ===\r\n" + argv.join(" ") + "\r\n=============");
-}
-
-void AOClient::cmdM(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- QString sender_message = argv.join(" ");
- for (AOClient* client : server->clients) {
- if (client->checkAuth(ACLFlags.value("MODCHAT")))
- client->sendPacket("CT", {"[M]" + sender_name, sender_message});
- }
- return;
-}
-
-void AOClient::cmdGM(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- QString sender_area = server->area_names.value(current_area);
- QString sender_message = argv.join(" ");
- for (AOClient* client : server->clients) {
- if (client->global_enabled) {
- client->sendPacket("CT", {"[G][" + sender_area + "]" + "["+sender_name+"][M]", sender_message});
- }
- }
-}
-
-void AOClient::cmdLM(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- QString sender_message = argv.join(" ");
- server->broadcast(AOPacket("CT", {"["+sender_name+"][M]", sender_message}), current_area);
-}
-
-void AOClient::cmdBans(int argc, QStringList argv)
-{
- QStringList recent_bans;
- recent_bans << "Last 5 bans:";
- recent_bans << "-----";
- for (DBManager::BanInfo ban : server->db_manager->getRecentBans()) {
- QString banned_until;
- if (ban.duration == -2)
- banned_until = "The heat death of the universe";
- else
- banned_until = QDateTime::fromSecsSinceEpoch(ban.time).addSecs(ban.duration).toString("dd.MM.yyyy, hh:mm");
- recent_bans << "Affected IPID: " + ban.ipid;
- recent_bans << "Affected HDID: " + ban.hdid;
- recent_bans << "Reason for ban: " + ban.reason;
- recent_bans << "Date of ban: " + QDateTime::fromSecsSinceEpoch(ban.time).toString("dd.MM.yyyy, hh:mm");
- recent_bans << "Ban lasts until: " + banned_until;
- recent_bans << "-----";
- }
- sendServerMessage(recent_bans.join("\n"));
-}
-
-void AOClient::cmdUnBan(int argc, QStringList argv)
-{
- bool ok;
- int target_ban = argv[0].toInt(&ok);
- if (!ok) {
- sendServerMessage("Invalid ban ID.");
- return;
- }
- else if (server->db_manager->invalidateBan(target_ban))
- sendServerMessage("Successfully invalidated ban " + argv[0] + ".");
- else
- sendServerMessage("Couldn't invalidate ban " + argv[0] + ", are you sure it exists?");
-}
-
-void AOClient::cmdSubTheme(int argc, QStringList argv)
-{
- QString subtheme = argv.join(" ");
- for (AOClient* client : server->clients) {
- if (client->current_area == current_area)
- client->sendPacket("ST", {subtheme, "1"});
- }
- sendServerMessageArea("Subtheme was set to " + subtheme);
-}
-
-void AOClient::cmdAbout(int argc, QStringList argv)
-{
- sendPacket("CT", {"The akashi dev team", "Thank you for using akashi! Made with love by scatterflower, with help from in1tiate and Salanto. akashi " + QCoreApplication::applicationVersion()});
-}
-
-void AOClient::cmdEvidence_Swap(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- int ev_size = area->evidence.size() -1;
-
- if (ev_size < 0) {
- sendServerMessage("No evidence in area.");
- return;
- }
-
- bool ok, ok2;
- int ev_id1 = argv[0].toInt(&ok), ev_id2 = argv[1].toInt(&ok2);
-
- if ((!ok || !ok2)) {
- sendServerMessage("Invalid evidence ID.");
- return;
- }
- if ((ev_id1 < 0) || (ev_id2 < 0)) {
- sendServerMessage("Evidence ID can't be negative.");
- return;
- }
- if ((ev_id2 <= ev_size) && (ev_id1 <= ev_size)) {
-#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
- //swapItemsAt does not exist in Qt older than 5.13
- area->evidence.swap(ev_id1, ev_id2);
-#else
- area->evidence.swapItemsAt(ev_id1, ev_id2);
-#endif
- sendEvidenceList(area);
- sendServerMessage("The evidence " + QString::number(ev_id1) + " and " + QString::number(ev_id2) + " have been swapped.");
- }
- else {
- sendServerMessage("Unable to swap evidence. Evidence ID out of range.");
- }
-}
-
-void AOClient::cmdMute(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (target->is_muted)
- sendServerMessage("That player is already muted!");
- else {
- sendServerMessage("Muted player.");
- target->sendServerMessage("You were muted by a moderator. " + getReprimand());
- }
- target->is_muted = true;
-}
-
-void AOClient::cmdUnMute(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (!target->is_muted)
- sendServerMessage("That player is not muted!");
- else {
- sendServerMessage("Unmuted player.");
- target->sendServerMessage("You were unmuted by a moderator. " + getReprimand(true));
- }
- target->is_muted = false;
-}
-
-void AOClient::cmdOocMute(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (target->is_ooc_muted)
- sendServerMessage("That player is already OOC muted!");
- else {
- sendServerMessage("OOC muted player.");
- target->sendServerMessage("You were OOC muted by a moderator. " + getReprimand());
- }
- target->is_ooc_muted = true;
-}
-
-void AOClient::cmdOocUnMute(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (!target->is_ooc_muted)
- sendServerMessage("That player is not OOC muted!");
- else {
- sendServerMessage("OOC unmuted player.");
- target->sendServerMessage("You were OOC unmuted by a moderator. " + getReprimand(true));
- }
- target->is_ooc_muted = false;
-}
-
-void AOClient::cmdBlockDj(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (target->is_dj_blocked)
- sendServerMessage("That player is already DJ blocked!");
- else {
- sendServerMessage("DJ blocked player.");
- target->sendServerMessage("You were blocked from changing the music by a moderator. " + getReprimand());
- }
- target->is_dj_blocked = true;
-}
-
-void AOClient::cmdUnBlockDj(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (!target->is_dj_blocked)
- sendServerMessage("That player is not DJ blocked!");
- else {
- sendServerMessage("DJ permissions restored to player.");
- target->sendServerMessage("A moderator restored your music permissions. " + getReprimand(true));
- }
- target->is_dj_blocked = false;
-}
-
-void AOClient::cmdBlockWtce(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (target->is_wtce_blocked)
- sendServerMessage("That player is already judge blocked!");
- else {
- sendServerMessage("Revoked player's access to judge controls.");
- target->sendServerMessage("A moderator revoked your judge controls access. " + getReprimand());
- }
- target->is_wtce_blocked = true;
-}
-
-void AOClient::cmdUnBlockWtce(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (!target->is_wtce_blocked)
- sendServerMessage("That player is not judge blocked!");
- else {
- sendServerMessage("Restored player's access to judge controls.");
- target->sendServerMessage("A moderator restored your judge controls access. " + getReprimand(true));
- }
- target->is_wtce_blocked = false;
-}
-
-void AOClient::cmdNoteCard(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->notecards.keys().contains(current_char))
- area->notecards.remove(current_char);
- QString notecard = argv.join(" ");
- area->notecards[current_char] = notecard;
- sendServerMessageArea(current_char + " wrote a note card.");
-}
-
-void AOClient::cmdNoteCardClear(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->notecards.keys().contains(current_char)) {
- area->notecards.remove(current_char);
- sendServerMessageArea(current_char + " erased their note card.");
- }
- else
- sendServerMessage("You do not have a note card.");
-}
-
-void AOClient::cmdNoteCardReveal(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->notecards.isEmpty()) {
- sendServerMessage("There are no cards to reveal in this area.");
- return;
- }
- QStringList message;
- message << "Note cards have been revealed.";
- QMap::iterator i;
- for (i = area->notecards.begin(); i != area->notecards.end(); ++i)
- message << i.key() + ": " + i.value();
- sendServerMessageArea(message.join("\n"));
- area->notecards.clear();
-}
-
-void AOClient::cmd8Ball(int argc, QStringList argv)
-{
- if (server->magic_8ball_answers.isEmpty()) {
- qWarning() << "8ball.txt is empty!";
- sendServerMessage("8ball.txt is empty.");
- }
- else {
- QString response = server->magic_8ball_answers[(genRand(1, server->magic_8ball_answers.size() - 1))];
- QString sender_name = ooc_name;
- QString sender_message = argv.join(" ");
-
- sendServerMessageArea(sender_name + " asked the magic 8-ball, \"" + sender_message + "\" and the answer is: " + response);
- }
-}
-
-void AOClient::cmdJudgeLog(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->judgelog.isEmpty()) {
- sendServerMessage("There have been no judge actions in this area.");
- return;
- }
- QString message = area->judgelog.join("\n");
- //Judgelog contains an IPID, so we shouldn't send that unless the caller has appropriate permissions
- if (checkAuth(ACLFlags.value("KICK")) == 1 || checkAuth(ACLFlags.value("BAN")) == 1) {
- sendServerMessage(message);
- }
- else {
- QString filteredmessage = message.remove(QRegularExpression("[(].*[)]")); //Filter out anything between two parentheses. This should only ever be the IPID
- sendServerMessage(filteredmessage);
- }
-}
-
-void AOClient::cmdAllow_Blankposting(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- AreaData* area = server->areas[current_area];
- area->blankposting_allowed = !area->blankposting_allowed;
- if (area->blankposting_allowed == false) {
- sendServerMessageArea(sender_name + " has set blankposting in the area to forbidden.");
- }
- else {
- sendServerMessageArea(sender_name + " has set blankposting in the area to allowed.");
- }
-}
-
-void AOClient::cmdGimp(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (target->is_gimped)
- sendServerMessage("That player is already gimped!");
- else {
- sendServerMessage("Gimped player.");
- target->sendServerMessage("You have been gimped! " + getReprimand());
- }
- target->is_gimped = true;
-}
-
-void AOClient::cmdUnGimp(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (!(target->is_gimped))
- sendServerMessage("That player is not gimped!");
- else {
- sendServerMessage("Ungimped player.");
- target->sendServerMessage("A moderator has ungimped you! " + getReprimand(true));
- }
- target->is_gimped = false;
-}
-void AOClient::cmdBanInfo(int argc, QStringList argv)
-{
- QStringList ban_info;
- ban_info << ("Ban Info for " + argv[0]);
- ban_info << "-----";
- QString lookup_type;
-
- if (argc == 1) {
- lookup_type = "banid";
- }
- else if (argc == 2) {
- lookup_type = argv[1];
- if (!((lookup_type == "banid") || (lookup_type == "ipid") || (lookup_type == "hdid"))) {
- sendServerMessage("Invalid ID type.");
- return;
- }
- }
- else {
- sendServerMessage("Invalid command.");
- return;
- }
- QString id = argv[0];
- for (DBManager::BanInfo ban : server->db_manager->getBanInfo(lookup_type, id)) {
- QString banned_until;
- if (ban.duration == -2)
- banned_until = "The heat death of the universe";
- else
- banned_until = QDateTime::fromSecsSinceEpoch(ban.time).addSecs(ban.duration).toString("dd.MM.yyyy, hh:mm");
- ban_info << "Affected IPID: " + ban.ipid;
- ban_info << "Affected HDID: " + ban.hdid;
- ban_info << "Reason for ban: " + ban.reason;
- ban_info << "Date of ban: " + QDateTime::fromSecsSinceEpoch(ban.time).toString("dd.MM.yyyy, hh:mm");
- ban_info << "Ban lasts until: " + banned_until;
- ban_info << "-----";
- }
- sendServerMessage(ban_info.join("\n"));
-}
-
-void AOClient::cmdTestify(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->test_rec == AreaData::TestimonyRecording::RECORDING) {
- sendServerMessage("Testimony recording is already in progress. Please stop it before starting a new one.");
- }
- else {
- clearTestimony();
- area->statement = 0;
- area->test_rec = AreaData::TestimonyRecording::RECORDING;
- sendServerMessage("Started testimony recording.");
- }
-}
-
-void AOClient::cmdExamine(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->testimony.size() -1 > 0)
- {
- area->test_rec = AreaData::TestimonyRecording::PLAYBACK;
- server->broadcast(AOPacket("RT",{"testimony2"}), current_area);
- server->broadcast(AOPacket("MS", {area->testimony[0]}), current_area);
- area->statement = 0;
- return;
- }
- if (area->test_rec == AreaData::TestimonyRecording::PLAYBACK)
- sendServerMessage("Unable to examine while another examination is running");
- else
- sendServerMessage("Unable to start replay without prior examination.");
-}
-
-void AOClient::cmdDeleteStatement(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- int c_statement = area->statement;
- if (area->testimony.size() - 1 == 0) {
- sendServerMessage("Unable to delete statement. No statements saved in this area.");
- }
- if (c_statement > 0 && area->testimony.size() > 2) {
- area->testimony.remove(c_statement);
- sendServerMessage("The statement with id " + QString::number(c_statement) + " has been deleted from the testimony.");
- }
-}
-
-void AOClient::cmdUpdateStatement(int argc, QStringList argv)
-{
- server->areas[current_area]->test_rec = AreaData::TestimonyRecording::UPDATE;
- sendServerMessage("The next IC-Message will replace the last displayed replay message.");
-}
-
-void AOClient::cmdPauseTestimony(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- area->test_rec = AreaData::TestimonyRecording::STOPPED;
- sendServerMessage("Testimony has been stopped.");
-}
-
-void AOClient::cmdAddStatement(int argc, QStringList argv)
-{
- if (server->areas[current_area]->statement < server->maximum_statements) {
- server->areas[current_area]->test_rec = AreaData::TestimonyRecording::ADD;
- sendServerMessage("The next IC-Message will be inserted into the testimony.");
- }
- else
- sendServerMessage("Unable to add anymore statements. Please remove any unused ones.");
-}
-
-void AOClient::cmdReload(int argc, QStringList argv)
-{
- server->loadServerConfig();
- server->loadCommandConfig();
- emit server->reloadRequest(server->server_name, server->server_desc);
- sendServerMessage("Reloaded configurations");
-}
-
-void AOClient::cmdDisemvowel(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (target->is_disemvoweled)
- sendServerMessage("That player is already disemvoweled!");
- else {
- sendServerMessage("Disemvoweled player.");
- target->sendServerMessage("You have been disemvoweled! " + getReprimand());
- }
- target->is_disemvoweled = true;
-}
-
-void AOClient::cmdUnDisemvowel(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (!(target->is_disemvoweled))
- sendServerMessage("That player is not disemvoweled!");
- else {
- sendServerMessage("Undisemvoweled player.");
- target->sendServerMessage("A moderator has undisemvoweled you! " + getReprimand(true));
- }
- target->is_disemvoweled = false;
-}
-
-void AOClient::cmdShake(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (target->is_shaken)
- sendServerMessage("That player is already shaken!");
- else {
- sendServerMessage("Shook player.");
- target->sendServerMessage("A moderator has shaken your words! " + getReprimand());
- }
- target->is_shaken = true;
-}
-
-void AOClient::cmdUnShake(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (!(target->is_shaken))
- sendServerMessage("That player is not shaken!");
- else {
- sendServerMessage("Unshook player.");
- target->sendServerMessage("A moderator has unshook you! " + getReprimand(true));
- }
- target->is_shaken = false;
-}
-
-QStringList AOClient::buildAreaList(int area_idx)
-{
- QStringList entries;
- QString area_name = server->area_names[area_idx];
- AreaData* area = server->areas[area_idx];
- entries.append("=== " + area_name + " ===");
- switch (area->locked) {
- case AreaData::LockStatus::LOCKED:
- entries.append("[LOCKED]");
- break;
- case AreaData::LockStatus::SPECTATABLE:
- entries.append("[SPECTATABLE]");
- break;
- case AreaData::LockStatus::FREE:
- default:
- break;
- }
- entries.append("[" + QString::number(area->player_count) + " users][" + QVariant::fromValue(area->status).toString().replace("_", "-") + "]");
- for (AOClient* client : server->clients) {
- if (client->current_area == area_idx && client->joined) {
- QString char_entry = "[" + QString::number(client->id) + "] " + client->current_char;
- if (client->current_char == "")
- char_entry += "Spectator";
- if (area->owners.contains(client->id))
- char_entry.insert(0, "[CM] ");
- if (authenticated)
- char_entry += " (" + client->getIpid() + "): " + client->ooc_name;
- entries.append(char_entry);
- }
- }
- return entries;
-}
-
-int AOClient::genRand(int min, int max)
-{
-#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
- qsrand(QDateTime::currentMSecsSinceEpoch());
- quint32 random_number = (qrand() % (max - min + 1)) + min;
- return random_number;
-
-#else
- quint32 random_number = QRandomGenerator::system()->bounded(min, max + 1);
- return random_number;
-#endif
-}
-
-void AOClient::diceThrower(int argc, QStringList argv, RollType type)
-{
- QString sender_name = ooc_name;
- int max_value = server->dice_value;
- int max_dice = server->max_dice;
- int bounded_value;
- int bounded_amount;
- QString dice_results;
-
- if (argc == 0) {
- dice_results = QString::number(genRand(1, 6)); // Self-explanatory
- }
- else if (argc == 1) {
- bounded_value = qBound(1, argv[0].toInt(), max_value); // faces, max faces
- dice_results = QString::number(genRand(1, bounded_value));
- }
- else if (argc == 2) {
- bounded_value = qBound(1, argv[0].toInt(), max_value); // 1, faces, max faces
- bounded_amount = qBound(1, argv[1].toInt(), max_dice); // 1, amount, max amount
-
- for (int i = 1; i <= bounded_amount ; i++) // Loop as multiple dices are thrown
- {
- QString dice_result = QString::number(genRand(1, bounded_value));
- if (i == bounded_amount) {
- dice_results = dice_results.append(dice_result);
- }
- else {
- dice_results = dice_results.append(dice_result + ",");
- }
- }
- }
- // Switch to change message behaviour, isEmpty check or the entire server crashes due to an out of range issue in the QStringList
- switch(type)
- {
- case ROLL:
- if (argv.isEmpty()) {
- sendServerMessageArea(sender_name + " rolled " + dice_results + " out of 6");
- }
- else {
- sendServerMessageArea(sender_name + " rolled " + dice_results + " out of " + QString::number(bounded_value));
- }
- break;
- case ROLLP:
- if (argv.isEmpty()) {
- sendServerMessage(sender_name + " rolled " + dice_results + " out of 6");
- sendServerMessageArea((sender_name + " rolled in secret."));
- }
- else {
- sendServerMessageArea(sender_name + " rolled " + dice_results + " out of " + QString::number(bounded_value));
- sendServerMessageArea((sender_name + " rolled in secret."));
- }
- break;
- case ROLLA:
- //Not implemented yet
- default : break;
- }
-}
-
-QString AOClient::getAreaTimer(int area_idx, int timer_idx)
-{
- AreaData* area = server->areas[area_idx];
- QTimer* timer;
- QString timer_name = (timer_idx == 0) ? "Global timer" : "Timer " + QString::number(timer_idx);
-
- if (timer_idx == 0)
- timer = server->timer;
- else if (timer_idx > 0 && timer_idx <= 4)
- timer = area->timers[timer_idx - 1];
- else
- return "Invalid timer ID.";
-
- if (timer->isActive()) {
- QTime current_time = QTime(0,0).addMSecs(timer->remainingTime());
-
- return timer_name + " is at " + current_time.toString("hh:mm:ss.zzz");
- }
- else {
- return timer_name + " is inactive.";
- }
-}
-
-long long AOClient::parseTime(QString input)
-{
- QRegularExpression regex("(?:(?:(?.*?)y)*(?:(?.*?)w)*(?:(?.*?)d)*(?:(?
.*?)h)*(?:(?.*?)m)*(?:(?.*?)s)*)");
- QRegularExpressionMatch match = regex.match(input);
- QString str_year, str_week, str_hour, str_day, str_minute, str_second;
- int year, week, day, hour, minute, second;
-
- str_year = match.captured("year");
- str_week = match.captured("week");
- str_day = match.captured("day");
- str_hour = match.captured("hr");
- str_minute = match.captured("min");
- str_second = match.captured("sec");
-
- bool is_well_formed = false;
- QString concat_str(str_year + str_week + str_day + str_hour + str_minute + str_second);
- concat_str.toInt(&is_well_formed);
-
- if (!is_well_formed) {
- return -1;
- }
-
- year = str_year.toInt();
- week = str_week.toInt();
- day = str_day.toInt();
- hour = str_hour.toInt();
- minute = str_minute.toInt();
- second = str_second.toInt();
-
- long long total = 0;
- total += 31622400 * year;
- total += 604800 * week;
- total += 86400 * day;
- total += 3600 * hour;
- total += 60 * minute;
- total += second;
-
- if (total < 0)
- return -1;
-
- return total;
-}
-
-QString AOClient::getReprimand(bool positive)
-{
- if (positive) {
- return server->praise_list[genRand(0, server->praise_list.size() - 1)];
- }
- else {
- return server->reprimands_list[genRand(0, server->reprimands_list.size() - 1)];
- }
-}
diff --git a/src/commands/area.cpp b/src/commands/area.cpp
new file mode 100644
index 0000000..d471ef6
--- /dev/null
+++ b/src/commands/area.cpp
@@ -0,0 +1,285 @@
+//////////////////////////////////////////////////////////////////////////////////////
+// akashi - a server for Attorney Online 2 //
+// Copyright (C) 2020 scatterflower //
+// //
+// 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 . //
+//////////////////////////////////////////////////////////////////////////////////////
+#include "include/aoclient.h"
+
+// This file is for commands under the area category in aoclient.h
+// Be sure to register the command in the header before adding it here!
+
+
+void AOClient::cmdCM(int argc, QStringList argv)
+{
+ QString sender_name = ooc_name;
+ AreaData* area = server->areas[current_area];
+ if (area->is_protected) {
+ sendServerMessage("This area is protected, you may not become CM.");
+ return;
+ }
+ else if (area->owners.isEmpty()) { // no one owns this area, and it's not protected
+ area->owners.append(id);
+ area->invited.append(id);
+ sendServerMessageArea(sender_name + " is now CM in this area.");
+ arup(ARUPType::CM, true);
+ }
+ else if (!area->owners.contains(id)) { // there is already a CM, and it isn't us
+ sendServerMessage("You cannot become a CM in this area.");
+ }
+ else if (argc == 1) { // we are CM, and we want to make ID argv[0] also CM
+ bool ok;
+ AOClient* owner_candidate = server->getClientByID(argv[0].toInt(&ok));
+ if (!ok) {
+ sendServerMessage("That doesn't look like a valid ID.");
+ return;
+ }
+ if (owner_candidate == nullptr) {
+ sendServerMessage("Unable to find client with ID " + argv[0] + ".");
+ return;
+ }
+ area->owners.append(owner_candidate->id);
+ sendServerMessageArea(owner_candidate->ooc_name + " is now CM in this area.");
+ arup(ARUPType::CM, true);
+ }
+ else {
+ sendServerMessage("You are already a CM in this area.");
+ }
+}
+
+void AOClient::cmdUnCM(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ int removed = area->owners.removeAll(id);
+ area->invited.removeAll(id);
+ sendServerMessage("You are no longer CM in this area.");
+ arup(ARUPType::CM, true);
+ if (area->owners.isEmpty()) {
+ area->invited.clear();
+ if (area->locked != AreaData::FREE) {
+ area->locked = AreaData::FREE;
+ arup(ARUPType::LOCKED, true);
+ }
+ }
+}
+
+void AOClient::cmdInvite(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ bool ok;
+ int invited_id = argv[0].toInt(&ok);
+ if (!ok) {
+ sendServerMessage("That does not look like a valid ID.");
+ return;
+ }
+ else if (server->getClientByID(invited_id) == nullptr) {
+ sendServerMessage("No client with that ID found.");
+ return;
+ }
+ else if (area->invited.contains(invited_id)) {
+ sendServerMessage("That ID is already on the invite list.");
+ return;
+ }
+ area->invited.append(invited_id);
+ sendServerMessage("You invited ID " + argv[0]);
+}
+
+void AOClient::cmdUnInvite(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ bool ok;
+ int uninvited_id = argv[0].toInt(&ok);
+ if (!ok) {
+ sendServerMessage("That does not look like a valid ID.");
+ return;
+ }
+ else if (server->getClientByID(uninvited_id) == nullptr) {
+ sendServerMessage("No client with that ID found.");
+ return;
+ }
+ else if (area->owners.contains(uninvited_id)) {
+ sendServerMessage("You cannot uninvite a CM!");
+ return;
+ }
+ else if (!area->invited.contains(uninvited_id)) {
+ sendServerMessage("That ID is not on the invite list.");
+ return;
+ }
+ area->invited.removeAll(uninvited_id);
+ sendServerMessage("You uninvited ID " + argv[0]);
+}
+
+void AOClient::cmdLock(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ if (area->locked == AreaData::LockStatus::LOCKED) {
+ sendServerMessage("This area is already locked.");
+ return;
+ }
+ sendServerMessageArea("This area is now locked.");
+ area->locked = AreaData::LockStatus::LOCKED;
+ for (AOClient* client : server->clients) {
+ if (client->current_area == current_area && client->joined) {
+ area->invited.append(client->id);
+ }
+ }
+ arup(ARUPType::LOCKED, true);
+}
+
+void AOClient::cmdSpectatable(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ if (area->locked == AreaData::LockStatus::SPECTATABLE) {
+ sendServerMessage("This area is already in spectate mode.");
+ return;
+ }
+ sendServerMessageArea("This area is now spectatable.");
+ area->locked = AreaData::LockStatus::SPECTATABLE;
+ for (AOClient* client : server->clients) {
+ if (client->current_area == current_area && client->joined) {
+ area->invited.append(client->id);
+ }
+ }
+ arup(ARUPType::LOCKED, true);
+}
+
+void AOClient::cmdUnLock(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ if (area->locked == AreaData::LockStatus::FREE) {
+ sendServerMessage("This area is not locked.");
+ return;
+ }
+ sendServerMessageArea("This area is now unlocked.");
+ area->locked = AreaData::LockStatus::FREE;
+ arup(ARUPType::LOCKED, true);
+}
+
+void AOClient::cmdGetAreas(int argc, QStringList argv)
+{
+ QStringList entries;
+ entries.append("== Area List ==");
+ for (int i = 0; i < server->area_names.length(); i++) {
+ QStringList cur_area_lines = buildAreaList(i);
+ entries.append(cur_area_lines);
+ }
+ sendServerMessage(entries.join("\n"));
+}
+
+void AOClient::cmdGetArea(int argc, QStringList argv)
+{
+ QStringList entries = buildAreaList(current_area);
+ sendServerMessage(entries.join("\n"));
+}
+
+void AOClient::cmdArea(int argc, QStringList argv)
+{
+ bool ok;
+ int new_area = argv[0].toInt(&ok);
+ if (!ok || new_area >= server->areas.size() || new_area < 0) {
+ sendServerMessage("That does not look like a valid area ID.");
+ return;
+ }
+ changeArea(new_area);
+}
+
+void AOClient::cmdAreaKick(int argc, QStringList argv)
+{
+ bool ok;
+ int idx = argv[0].toInt(&ok);
+ if (!ok) {
+ sendServerMessage("That does not look like a valid ID.");
+ return;
+ }
+ AOClient* client_to_kick = server->getClientByID(idx);
+ if (client_to_kick == nullptr) {
+ sendServerMessage("No client with that ID found.");
+ return;
+ }
+ client_to_kick->changeArea(0);
+ sendServerMessage("Client " + argv[0] + " kicked back to area 0.");
+}
+
+void AOClient::cmdSetBackground(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ if (authenticated || !area->bg_locked) {
+ if (server->backgrounds.contains(argv[0])) {
+ area->background = argv[0];
+ server->broadcast(AOPacket("BN", {argv[0]}), current_area);
+ sendServerMessageArea(current_char + " changed the background to " + argv[0]);
+ }
+ else {
+ sendServerMessage("Invalid background name.");
+ }
+ }
+ else {
+ sendServerMessage("This area's background is locked.");
+ }
+}
+
+void AOClient::cmdBgLock(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ area->bg_locked = true;
+ server->broadcast(AOPacket("CT", {"Server", current_char + " locked the background.", "1"}), current_area);
+}
+
+void AOClient::cmdBgUnlock(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ area->bg_locked = false;
+ server->broadcast(AOPacket("CT", {"Server", current_char + " unlocked the background.", "1"}), current_area);
+}
+
+void AOClient::cmdStatus(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ QString arg = argv[0].toLower();
+ if (arg == "idle")
+ area->status = AreaData::IDLE;
+ else if (arg == "rp")
+ area->status = AreaData::RP;
+ else if (arg == "casing")
+ area->status = AreaData::CASING;
+ else if (arg == "looking-for-players" || arg == "lfp")
+ area->status = AreaData::LOOKING_FOR_PLAYERS;
+ else if (arg == "recess")
+ area->status = AreaData::RECESS;
+ else if (arg == "gaming")
+ area->status = AreaData::GAMING;
+ else {
+ sendServerMessage("That does not look like a valid status. Valid statuses are idle, rp, casing, lfp, recess, gaming");
+ return;
+ }
+ arup(ARUPType::STATUS, true);
+}
+
+void AOClient::cmdJudgeLog(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ if (area->judgelog.isEmpty()) {
+ sendServerMessage("There have been no judge actions in this area.");
+ return;
+ }
+ QString message = area->judgelog.join("\n");
+ //Judgelog contains an IPID, so we shouldn't send that unless the caller has appropriate permissions
+ if (checkAuth(ACLFlags.value("KICK")) == 1 || checkAuth(ACLFlags.value("BAN")) == 1) {
+ sendServerMessage(message);
+ }
+ else {
+ QString filteredmessage = message.remove(QRegularExpression("[(].*[)]")); //Filter out anything between two parentheses. This should only ever be the IPID
+ sendServerMessage(filteredmessage);
+ }
+}
diff --git a/src/commands/authentication.cpp b/src/commands/authentication.cpp
index fa0dd4d..1aeb24d 100644
--- a/src/commands/authentication.cpp
+++ b/src/commands/authentication.cpp
@@ -17,6 +17,7 @@
//////////////////////////////////////////////////////////////////////////////////////
#include "include/aoclient.h"
+// This file is for commands under the authentication category in aoclient.h
// Be sure to register the command in the header before adding it here!
void AOClient::cmdLogin(int argc, QStringList argv)
diff --git a/src/commands/casing.cpp b/src/commands/casing.cpp
new file mode 100644
index 0000000..db4ce40
--- /dev/null
+++ b/src/commands/casing.cpp
@@ -0,0 +1,167 @@
+//////////////////////////////////////////////////////////////////////////////////////
+// akashi - a server for Attorney Online 2 //
+// Copyright (C) 2020 scatterflower //
+// //
+// 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 . //
+//////////////////////////////////////////////////////////////////////////////////////
+#include "include/aoclient.h"
+
+// This file is for commands under the casing category in aoclient.h
+// Be sure to register the command in the header before adding it here!
+
+void AOClient::cmdDoc(int argc, QStringList argv)
+{
+ QString sender_name = ooc_name;
+ AreaData* area = server->areas[current_area];
+ if (argc == 0) {
+ sendServerMessage("Document: " + area->document);
+ }
+ else {
+ area->document = argv.join(" ");
+ sendServerMessageArea(sender_name + " changed the document.");
+ }
+}
+
+void AOClient::cmdClearDoc(int argc, QStringList argv)
+{
+ QString sender_name = ooc_name;
+ AreaData* area = server->areas[current_area];
+ area->document = "No document.";
+ sendServerMessageArea(sender_name + " cleared the document.");
+}
+
+void AOClient::cmdEvidenceMod(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ argv[0] = argv[0].toLower();
+ if (argv[0] == "cm")
+ area->evi_mod = AreaData::EvidenceMod::CM;
+ else if (argv[0] == "mod")
+ area->evi_mod = AreaData::EvidenceMod::MOD;
+ else if (argv[0] == "hiddencm")
+ area->evi_mod = AreaData::EvidenceMod::HIDDEN_CM;
+ else if (argv[0] == "ffa")
+ area->evi_mod = AreaData::EvidenceMod::FFA;
+ else {
+ sendServerMessage("Invalid evidence mod.");
+ return;
+ }
+ sendServerMessage("Changed evidence mod.");
+
+ // Resend evidence lists to everyone in the area
+ sendEvidenceList(area);
+}
+
+void AOClient::cmdEvidence_Swap(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ int ev_size = area->evidence.size() -1;
+
+ if (ev_size < 0) {
+ sendServerMessage("No evidence in area.");
+ return;
+ }
+
+ bool ok, ok2;
+ int ev_id1 = argv[0].toInt(&ok), ev_id2 = argv[1].toInt(&ok2);
+
+ if ((!ok || !ok2)) {
+ sendServerMessage("Invalid evidence ID.");
+ return;
+ }
+ if ((ev_id1 < 0) || (ev_id2 < 0)) {
+ sendServerMessage("Evidence ID can't be negative.");
+ return;
+ }
+ if ((ev_id2 <= ev_size) && (ev_id1 <= ev_size)) {
+#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
+ //swapItemsAt does not exist in Qt older than 5.13
+ area->evidence.swap(ev_id1, ev_id2);
+#else
+ area->evidence.swapItemsAt(ev_id1, ev_id2);
+#endif
+ sendEvidenceList(area);
+ sendServerMessage("The evidence " + QString::number(ev_id1) + " and " + QString::number(ev_id2) + " have been swapped.");
+ }
+ else {
+ sendServerMessage("Unable to swap evidence. Evidence ID out of range.");
+ }
+}
+
+void AOClient::cmdTestify(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ if (area->test_rec == AreaData::TestimonyRecording::RECORDING) {
+ sendServerMessage("Testimony recording is already in progress. Please stop it before starting a new one.");
+ }
+ else {
+ clearTestimony();
+ area->statement = 0;
+ area->test_rec = AreaData::TestimonyRecording::RECORDING;
+ sendServerMessage("Started testimony recording.");
+ }
+}
+
+void AOClient::cmdExamine(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ if (area->testimony.size() -1 > 0)
+ {
+ area->test_rec = AreaData::TestimonyRecording::PLAYBACK;
+ server->broadcast(AOPacket("RT",{"testimony2"}), current_area);
+ server->broadcast(AOPacket("MS", {area->testimony[0]}), current_area);
+ area->statement = 0;
+ return;
+ }
+ if (area->test_rec == AreaData::TestimonyRecording::PLAYBACK)
+ sendServerMessage("Unable to examine while another examination is running");
+ else
+ sendServerMessage("Unable to start replay without prior examination.");
+}
+
+void AOClient::cmdDeleteStatement(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ int c_statement = area->statement;
+ if (area->testimony.size() - 1 == 0) {
+ sendServerMessage("Unable to delete statement. No statements saved in this area.");
+ }
+ if (c_statement > 0 && area->testimony.size() > 2) {
+ area->testimony.remove(c_statement);
+ sendServerMessage("The statement with id " + QString::number(c_statement) + " has been deleted from the testimony.");
+ }
+}
+
+void AOClient::cmdUpdateStatement(int argc, QStringList argv)
+{
+ server->areas[current_area]->test_rec = AreaData::TestimonyRecording::UPDATE;
+ sendServerMessage("The next IC-Message will replace the last displayed replay message.");
+}
+
+void AOClient::cmdPauseTestimony(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ area->test_rec = AreaData::TestimonyRecording::STOPPED;
+ sendServerMessage("Testimony has been stopped.");
+}
+
+void AOClient::cmdAddStatement(int argc, QStringList argv)
+{
+ if (server->areas[current_area]->statement < server->maximum_statements) {
+ server->areas[current_area]->test_rec = AreaData::TestimonyRecording::ADD;
+ sendServerMessage("The next IC-Message will be inserted into the testimony.");
+ }
+ else
+ sendServerMessage("Unable to add anymore statements. Please remove any unused ones.");
+}
diff --git a/src/commands/command_helper.cpp b/src/commands/command_helper.cpp
new file mode 100644
index 0000000..908f82b
--- /dev/null
+++ b/src/commands/command_helper.cpp
@@ -0,0 +1,207 @@
+//////////////////////////////////////////////////////////////////////////////////////
+// akashi - a server for Attorney Online 2 //
+// Copyright (C) 2020 scatterflower //
+// //
+// 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 . //
+//////////////////////////////////////////////////////////////////////////////////////
+#include "include/aoclient.h"
+
+// This file is for functions used by various commands, defined in the command helper function category in aoclient.h
+// Be sure to register the command in the header before adding it here!
+
+void AOClient::cmdDefault(int argc, QStringList argv)
+{
+ sendServerMessage("Invalid command.");
+ return;
+}
+
+QStringList AOClient::buildAreaList(int area_idx)
+{
+ QStringList entries;
+ QString area_name = server->area_names[area_idx];
+ AreaData* area = server->areas[area_idx];
+ entries.append("=== " + area_name + " ===");
+ switch (area->locked) {
+ case AreaData::LockStatus::LOCKED:
+ entries.append("[LOCKED]");
+ break;
+ case AreaData::LockStatus::SPECTATABLE:
+ entries.append("[SPECTATABLE]");
+ break;
+ case AreaData::LockStatus::FREE:
+ default:
+ break;
+ }
+ entries.append("[" + QString::number(area->player_count) + " users][" + QVariant::fromValue(area->status).toString().replace("_", "-") + "]");
+ for (AOClient* client : server->clients) {
+ if (client->current_area == area_idx && client->joined) {
+ QString char_entry = "[" + QString::number(client->id) + "] " + client->current_char;
+ if (client->current_char == "")
+ char_entry += "Spectator";
+ if (area->owners.contains(client->id))
+ char_entry.insert(0, "[CM] ");
+ if (authenticated)
+ char_entry += " (" + client->getIpid() + "): " + client->ooc_name;
+ entries.append(char_entry);
+ }
+ }
+ return entries;
+}
+
+int AOClient::genRand(int min, int max)
+{
+#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
+ qsrand(QDateTime::currentMSecsSinceEpoch());
+ quint32 random_number = (qrand() % (max - min + 1)) + min;
+ return random_number;
+
+#else
+ quint32 random_number = QRandomGenerator::system()->bounded(min, max + 1);
+ return random_number;
+#endif
+}
+
+void AOClient::diceThrower(int argc, QStringList argv, RollType type)
+{
+ QString sender_name = ooc_name;
+ int max_value = server->dice_value;
+ int max_dice = server->max_dice;
+ int bounded_value;
+ int bounded_amount;
+ QString dice_results;
+
+ if (argc == 0) {
+ dice_results = QString::number(genRand(1, 6)); // Self-explanatory
+ }
+ else if (argc == 1) {
+ bounded_value = qBound(1, argv[0].toInt(), max_value); // faces, max faces
+ dice_results = QString::number(genRand(1, bounded_value));
+ }
+ else if (argc == 2) {
+ bounded_value = qBound(1, argv[0].toInt(), max_value); // 1, faces, max faces
+ bounded_amount = qBound(1, argv[1].toInt(), max_dice); // 1, amount, max amount
+
+ for (int i = 1; i <= bounded_amount ; i++) // Loop as multiple dices are thrown
+ {
+ QString dice_result = QString::number(genRand(1, bounded_value));
+ if (i == bounded_amount) {
+ dice_results = dice_results.append(dice_result);
+ }
+ else {
+ dice_results = dice_results.append(dice_result + ",");
+ }
+ }
+ }
+ // Switch to change message behaviour, isEmpty check or the entire server crashes due to an out of range issue in the QStringList
+ switch(type)
+ {
+ case ROLL:
+ if (argv.isEmpty()) {
+ sendServerMessageArea(sender_name + " rolled " + dice_results + " out of 6");
+ }
+ else {
+ sendServerMessageArea(sender_name + " rolled " + dice_results + " out of " + QString::number(bounded_value));
+ }
+ break;
+ case ROLLP:
+ if (argv.isEmpty()) {
+ sendServerMessage(sender_name + " rolled " + dice_results + " out of 6");
+ sendServerMessageArea((sender_name + " rolled in secret."));
+ }
+ else {
+ sendServerMessageArea(sender_name + " rolled " + dice_results + " out of " + QString::number(bounded_value));
+ sendServerMessageArea((sender_name + " rolled in secret."));
+ }
+ break;
+ case ROLLA:
+ //Not implemented yet
+ default : break;
+ }
+}
+
+QString AOClient::getAreaTimer(int area_idx, int timer_idx)
+{
+ AreaData* area = server->areas[area_idx];
+ QTimer* timer;
+ QString timer_name = (timer_idx == 0) ? "Global timer" : "Timer " + QString::number(timer_idx);
+
+ if (timer_idx == 0)
+ timer = server->timer;
+ else if (timer_idx > 0 && timer_idx <= 4)
+ timer = area->timers[timer_idx - 1];
+ else
+ return "Invalid timer ID.";
+
+ if (timer->isActive()) {
+ QTime current_time = QTime(0,0).addMSecs(timer->remainingTime());
+
+ return timer_name + " is at " + current_time.toString("hh:mm:ss.zzz");
+ }
+ else {
+ return timer_name + " is inactive.";
+ }
+}
+
+long long AOClient::parseTime(QString input)
+{
+ QRegularExpression regex("(?:(?:(?.*?)y)*(?:(?.*?)w)*(?:(?.*?)d)*(?:(?
.*?)h)*(?:(?.*?)m)*(?:(?.*?)s)*)");
+ QRegularExpressionMatch match = regex.match(input);
+ QString str_year, str_week, str_hour, str_day, str_minute, str_second;
+ int year, week, day, hour, minute, second;
+
+ str_year = match.captured("year");
+ str_week = match.captured("week");
+ str_day = match.captured("day");
+ str_hour = match.captured("hr");
+ str_minute = match.captured("min");
+ str_second = match.captured("sec");
+
+ bool is_well_formed = false;
+ QString concat_str(str_year + str_week + str_day + str_hour + str_minute + str_second);
+ concat_str.toInt(&is_well_formed);
+
+ if (!is_well_formed) {
+ return -1;
+ }
+
+ year = str_year.toInt();
+ week = str_week.toInt();
+ day = str_day.toInt();
+ hour = str_hour.toInt();
+ minute = str_minute.toInt();
+ second = str_second.toInt();
+
+ long long total = 0;
+ total += 31622400 * year;
+ total += 604800 * week;
+ total += 86400 * day;
+ total += 3600 * hour;
+ total += 60 * minute;
+ total += second;
+
+ if (total < 0)
+ return -1;
+
+ return total;
+}
+
+QString AOClient::getReprimand(bool positive)
+{
+ if (positive) {
+ return server->praise_list[genRand(0, server->praise_list.size() - 1)];
+ }
+ else {
+ return server->reprimands_list[genRand(0, server->reprimands_list.size() - 1)];
+ }
+}
diff --git a/src/commands/messaging.cpp b/src/commands/messaging.cpp
new file mode 100644
index 0000000..9a852a6
--- /dev/null
+++ b/src/commands/messaging.cpp
@@ -0,0 +1,276 @@
+//////////////////////////////////////////////////////////////////////////////////////
+// akashi - a server for Attorney Online 2 //
+// Copyright (C) 2020 scatterflower //
+// //
+// 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 . //
+//////////////////////////////////////////////////////////////////////////////////////
+#include "include/aoclient.h"
+
+// This file is for commands under the messaging category in aoclient.h
+// Be sure to register the command in the header before adding it here!
+
+void AOClient::cmdPos(int argc, QStringList argv)
+{
+ changePosition(argv[0]);
+ updateEvidenceList(server->areas[current_area]);
+}
+
+void AOClient::cmdForcePos(int argc, QStringList argv)
+{
+ bool ok;
+ QList targets;
+ AreaData* area = server->areas[current_area];
+ int target_id = argv[1].toInt(&ok);
+ int forced_clients = 0;
+ if (!ok && argv[1] != "*") {
+ sendServerMessage("That does not look like a valid ID.");
+ return;
+ }
+ else if (ok) {
+ AOClient* target_client = server->getClientByID(target_id);
+ if (target_client != nullptr)
+ targets.append(target_client);
+ else {
+ sendServerMessage("Target ID not found!");
+ return;
+ }
+ }
+
+ else if (argv[1] == "*") { // force all clients in the area
+ for (AOClient* client : server->clients) {
+ if (client->current_area == current_area)
+ targets.append(client);
+ }
+ }
+ for (AOClient* target : targets) {
+ target->sendServerMessage("Position forcibly changed by CM.");
+ target->changePosition(argv[0]);
+ forced_clients++;
+ }
+ sendServerMessage("Forced " + QString::number(forced_clients) + " into pos " + argv[0] + ".");
+}
+
+void AOClient::cmdG(int argc, QStringList argv)
+{
+ QString sender_name = ooc_name;
+ QString sender_area = server->area_names.value(current_area);
+ QString sender_message = argv.join(" ");
+ for (AOClient* client : server->clients) {
+ if (client->global_enabled)
+ client->sendPacket("CT", {"[G][" + sender_area + "]" + sender_name, sender_message});
+ }
+ return;
+}
+
+void AOClient::cmdNeed(int argc, QStringList argv)
+{
+ QString sender_area = server->area_names.value(current_area);
+ QString sender_message = argv.join(" ");
+ sendServerBroadcast({"=== Advert ===\n[" + sender_area + "] needs " + sender_message+ "."});
+}
+
+void AOClient::cmdSwitch(int argc, QStringList argv)
+{
+ int char_id = server->getCharID(argv.join(" "));
+ if (char_id == -1) {
+ sendServerMessage("That does not look like a valid character.");
+ return;
+ }
+ changeCharacter(char_id);
+}
+
+void AOClient::cmdRandomChar(int argc, QStringList argv)
+{
+ int char_id = genRand(0, server->characters.size() - 1);
+ changeCharacter(char_id);
+}
+
+void AOClient::cmdToggleGlobal(int argc, QStringList argv)
+{
+ global_enabled = !global_enabled;
+ QString str_en = global_enabled ? "shown" : "hidden";
+ sendServerMessage("Global chat set to " + str_en);
+}
+
+void AOClient::cmdPM(int arc, QStringList argv)
+{
+ bool ok;
+ int target_id = argv.takeFirst().toInt(&ok); // using takeFirst removes the ID from our list of arguments...
+ if (!ok) {
+ sendServerMessage("That does not look like a valid ID.");
+ return;
+ }
+ AOClient* target_client = server->getClientByID(target_id);
+ if (target_client == nullptr) {
+ sendServerMessage("No client with that ID found.");
+ return;
+ }
+ QString message = argv.join(" "); //...which means it will not end up as part of the message
+ target_client->sendServerMessage("Message from " + ooc_name + " (" + QString::number(id) + "): " + message);
+}
+
+void AOClient::cmdAnnounce(int argc, QStringList argv)
+{
+ sendServerBroadcast("=== Announcement ===\r\n" + argv.join(" ") + "\r\n=============");
+}
+
+void AOClient::cmdM(int argc, QStringList argv)
+{
+ QString sender_name = ooc_name;
+ QString sender_message = argv.join(" ");
+ for (AOClient* client : server->clients) {
+ if (client->checkAuth(ACLFlags.value("MODCHAT")))
+ client->sendPacket("CT", {"[M]" + sender_name, sender_message});
+ }
+ return;
+}
+
+void AOClient::cmdGM(int argc, QStringList argv)
+{
+ QString sender_name = ooc_name;
+ QString sender_area = server->area_names.value(current_area);
+ QString sender_message = argv.join(" ");
+ for (AOClient* client : server->clients) {
+ if (client->global_enabled) {
+ client->sendPacket("CT", {"[G][" + sender_area + "]" + "["+sender_name+"][M]", sender_message});
+ }
+ }
+}
+
+void AOClient::cmdLM(int argc, QStringList argv)
+{
+ QString sender_name = ooc_name;
+ QString sender_message = argv.join(" ");
+ server->broadcast(AOPacket("CT", {"["+sender_name+"][M]", sender_message}), current_area);
+}
+
+void AOClient::cmdGimp(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (target->is_gimped)
+ sendServerMessage("That player is already gimped!");
+ else {
+ sendServerMessage("Gimped player.");
+ target->sendServerMessage("You have been gimped! " + getReprimand());
+ }
+ target->is_gimped = true;
+}
+
+void AOClient::cmdUnGimp(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (!(target->is_gimped))
+ sendServerMessage("That player is not gimped!");
+ else {
+ sendServerMessage("Ungimped player.");
+ target->sendServerMessage("A moderator has ungimped you! " + getReprimand(true));
+ }
+ target->is_gimped = false;
+}
+
+void AOClient::cmdDisemvowel(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (target->is_disemvoweled)
+ sendServerMessage("That player is already disemvoweled!");
+ else {
+ sendServerMessage("Disemvoweled player.");
+ target->sendServerMessage("You have been disemvoweled! " + getReprimand());
+ }
+ target->is_disemvoweled = true;
+}
+
+void AOClient::cmdUnDisemvowel(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (!(target->is_disemvoweled))
+ sendServerMessage("That player is not disemvoweled!");
+ else {
+ sendServerMessage("Undisemvoweled player.");
+ target->sendServerMessage("A moderator has undisemvoweled you! " + getReprimand(true));
+ }
+ target->is_disemvoweled = false;
+}
+
+void AOClient::cmdShake(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (target->is_shaken)
+ sendServerMessage("That player is already shaken!");
+ else {
+ sendServerMessage("Shook player.");
+ target->sendServerMessage("A moderator has shaken your words! " + getReprimand());
+ }
+ target->is_shaken = true;
+}
+
+void AOClient::cmdUnShake(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (!(target->is_shaken))
+ sendServerMessage("That player is not shaken!");
+ else {
+ sendServerMessage("Unshook player.");
+ target->sendServerMessage("A moderator has unshook you! " + getReprimand(true));
+ }
+ target->is_shaken = false;
+}
diff --git a/src/commands/moderation.cpp b/src/commands/moderation.cpp
new file mode 100644
index 0000000..09e8b66
--- /dev/null
+++ b/src/commands/moderation.cpp
@@ -0,0 +1,389 @@
+//////////////////////////////////////////////////////////////////////////////////////
+// akashi - a server for Attorney Online 2 //
+// Copyright (C) 2020 scatterflower //
+// //
+// 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 . //
+//////////////////////////////////////////////////////////////////////////////////////
+#include "include/aoclient.h"
+
+// This file is for commands under the moderation category in aoclient.h
+// Be sure to register the command in the header before adding it here!
+
+void AOClient::cmdBan(int argc, QStringList argv)
+{
+ QString args_str = argv[1];
+ if (argc > 2) {
+ for (int i = 2; i < argc; i++)
+ args_str += " " + argv[i];
+ }
+
+ DBManager::BanInfo ban;
+
+ QRegularExpression quoteMatcher("['\"](.+?)[\"']");
+ QRegularExpressionMatchIterator matches = quoteMatcher.globalMatch(args_str);
+ QList unquoted_args;
+ while (matches.hasNext()) {
+ QRegularExpressionMatch match = matches.next();
+ unquoted_args.append(match.captured(1));
+ }
+
+ QString duration = "perma";
+
+ if (unquoted_args.length() < 1) {
+ sendServerMessage("Invalid syntax. Usage:\n/ban \"\" \"\"");
+ return;
+ }
+
+ ban.reason = unquoted_args.at(0);
+ if (unquoted_args.length() > 1)
+ duration = unquoted_args.at(1);
+
+ long long duration_seconds = 0;
+ if (duration == "perma")
+ duration_seconds = -2;
+ else
+ duration_seconds = parseTime(duration);
+
+ if (duration_seconds == -1) {
+ sendServerMessage("Invalid time format. Format example: 1h30m");
+ return;
+ }
+
+ ban.duration = duration_seconds;
+
+ ban.ipid = argv[0];
+ ban.time = QDateTime::currentDateTime().toSecsSinceEpoch();
+ bool ban_logged = false;
+ int kick_counter = 0;
+
+ if (argc > 2) {
+ for (int i = 2; i < argv.length(); i++) {
+ ban.reason += " " + argv[i];
+ }
+ }
+
+ for (AOClient* client : server->getClientsByIpid(ban.ipid)) {
+ if (!ban_logged) {
+ ban.ip = client->remote_ip;
+ ban.hdid = client->hwid;
+ server->db_manager->addBan(ban);
+ sendServerMessage("Banned user with ipid " + ban.ipid + " for reason: " + ban.reason);
+ ban_logged = true;
+ }
+ client->sendPacket("KB", {ban.reason + "\nID: " + QString::number(server->db_manager->getBanID(ban.ip)) + "\nUntil: " + QDateTime::fromSecsSinceEpoch(ban.time).addSecs(ban.duration).toString("dd.MM.yyyy, hh:mm")});
+ client->socket->close();
+ kick_counter++;
+ }
+
+ if (kick_counter > 1)
+ sendServerMessage("Kicked " + QString::number(kick_counter) + " clients with matching ipids.");
+ if (!ban_logged)
+ sendServerMessage("User with ipid not found!");
+}
+
+void AOClient::cmdKick(int argc, QStringList argv)
+{
+ QString target_ipid = argv[0];
+ QString reason = argv[1];
+ int kick_counter = 0;
+
+ if (argc > 2) {
+ for (int i = 2; i < argv.length(); i++) {
+ reason += " " + argv[i];
+ }
+ }
+
+ for (AOClient* client : server->getClientsByIpid(target_ipid)) {
+ client->sendPacket("KK", {reason});
+ client->socket->close();
+ kick_counter++;
+ }
+
+ if (kick_counter > 0)
+ sendServerMessage("Kicked " + QString::number(kick_counter) + " client(s) with ipid " + target_ipid + " for reason: " + reason);
+ else
+ sendServerMessage("User with ipid not found!");
+}
+
+void AOClient::cmdMods(int argc, QStringList argv)
+{
+ QStringList entries;
+ int online_count = 0;
+ for (AOClient* client : server->clients) {
+ if (client->authenticated) {
+ entries << "---";
+ if (server->auth_type != "simple")
+ entries << "Moderator: " + client->moderator_name;
+ entries << "OOC name: " + client->ooc_name;
+ entries << "ID: " + QString::number(client->id);
+ entries << "Area: " + QString::number(client->current_area);
+ entries << "Character: " + client->current_char;
+ online_count++;
+ }
+ }
+ entries << "---";
+ entries << "Total online: " << QString::number(online_count);
+ sendServerMessage(entries.join("\n"));
+}
+
+void AOClient::cmdHelp(int argc, QStringList argv)
+{
+ QStringList entries;
+ entries << "Allowed commands:";
+ QMap::const_iterator i;
+ for (i = commands.constBegin(); i!= commands.constEnd(); ++i) {
+ CommandInfo info = i.value();
+ if (checkAuth(info.acl_mask)) { // if we are allowed to use this command
+ entries << "/" + i.key();
+ }
+ }
+ sendServerMessage(entries.join("\n"));
+}
+
+void AOClient::cmdMOTD(int argc, QStringList argv)
+{
+ if (argc == 0) {
+ sendServerMessage("=== MOTD ===\r\n" + server->MOTD + "\r\n=============");
+ }
+ else if (argc > 0) {
+ if (checkAuth(ACLFlags.value("MOTD"))) {
+ QString MOTD = argv.join(" ");
+ server->MOTD = MOTD;
+ sendServerMessage("MOTD has been changed.");
+ }
+ else {
+ sendServerMessage("You do not have permission to change the MOTD");
+ }
+ }
+}
+
+void AOClient::cmdBans(int argc, QStringList argv)
+{
+ QStringList recent_bans;
+ recent_bans << "Last 5 bans:";
+ recent_bans << "-----";
+ for (DBManager::BanInfo ban : server->db_manager->getRecentBans()) {
+ QString banned_until;
+ if (ban.duration == -2)
+ banned_until = "The heat death of the universe";
+ else
+ banned_until = QDateTime::fromSecsSinceEpoch(ban.time).addSecs(ban.duration).toString("dd.MM.yyyy, hh:mm");
+ recent_bans << "Affected IPID: " + ban.ipid;
+ recent_bans << "Affected HDID: " + ban.hdid;
+ recent_bans << "Reason for ban: " + ban.reason;
+ recent_bans << "Date of ban: " + QDateTime::fromSecsSinceEpoch(ban.time).toString("dd.MM.yyyy, hh:mm");
+ recent_bans << "Ban lasts until: " + banned_until;
+ recent_bans << "-----";
+ }
+ sendServerMessage(recent_bans.join("\n"));
+}
+
+void AOClient::cmdUnBan(int argc, QStringList argv)
+{
+ bool ok;
+ int target_ban = argv[0].toInt(&ok);
+ if (!ok) {
+ sendServerMessage("Invalid ban ID.");
+ return;
+ }
+ else if (server->db_manager->invalidateBan(target_ban))
+ sendServerMessage("Successfully invalidated ban " + argv[0] + ".");
+ else
+ sendServerMessage("Couldn't invalidate ban " + argv[0] + ", are you sure it exists?");
+}
+
+void AOClient::cmdAbout(int argc, QStringList argv)
+{
+ sendPacket("CT", {"The akashi dev team", "Thank you for using akashi! Made with love by scatterflower, with help from in1tiate and Salanto. akashi " + QCoreApplication::applicationVersion()});
+}
+
+void AOClient::cmdMute(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (target->is_muted)
+ sendServerMessage("That player is already muted!");
+ else {
+ sendServerMessage("Muted player.");
+ target->sendServerMessage("You were muted by a moderator. " + getReprimand());
+ }
+ target->is_muted = true;
+}
+
+void AOClient::cmdUnMute(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (!target->is_muted)
+ sendServerMessage("That player is not muted!");
+ else {
+ sendServerMessage("Unmuted player.");
+ target->sendServerMessage("You were unmuted by a moderator. " + getReprimand(true));
+ }
+ target->is_muted = false;
+}
+
+void AOClient::cmdOocMute(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (target->is_ooc_muted)
+ sendServerMessage("That player is already OOC muted!");
+ else {
+ sendServerMessage("OOC muted player.");
+ target->sendServerMessage("You were OOC muted by a moderator. " + getReprimand());
+ }
+ target->is_ooc_muted = true;
+}
+
+void AOClient::cmdOocUnMute(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (!target->is_ooc_muted)
+ sendServerMessage("That player is not OOC muted!");
+ else {
+ sendServerMessage("OOC unmuted player.");
+ target->sendServerMessage("You were OOC unmuted by a moderator. " + getReprimand(true));
+ }
+ target->is_ooc_muted = false;
+}
+
+void AOClient::cmdBlockWtce(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (target->is_wtce_blocked)
+ sendServerMessage("That player is already judge blocked!");
+ else {
+ sendServerMessage("Revoked player's access to judge controls.");
+ target->sendServerMessage("A moderator revoked your judge controls access. " + getReprimand());
+ }
+ target->is_wtce_blocked = true;
+}
+
+void AOClient::cmdUnBlockWtce(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (!target->is_wtce_blocked)
+ sendServerMessage("That player is not judge blocked!");
+ else {
+ sendServerMessage("Restored player's access to judge controls.");
+ target->sendServerMessage("A moderator restored your judge controls access. " + getReprimand(true));
+ }
+ target->is_wtce_blocked = false;
+}
+
+void AOClient::cmdAllow_Blankposting(int argc, QStringList argv)
+{
+ QString sender_name = ooc_name;
+ AreaData* area = server->areas[current_area];
+ area->blankposting_allowed = !area->blankposting_allowed;
+ if (area->blankposting_allowed == false) {
+ sendServerMessageArea(sender_name + " has set blankposting in the area to forbidden.");
+ }
+ else {
+ sendServerMessageArea(sender_name + " has set blankposting in the area to allowed.");
+ }
+}
+
+void AOClient::cmdBanInfo(int argc, QStringList argv)
+{
+ QStringList ban_info;
+ ban_info << ("Ban Info for " + argv[0]);
+ ban_info << "-----";
+ QString lookup_type;
+
+ if (argc == 1) {
+ lookup_type = "banid";
+ }
+ else if (argc == 2) {
+ lookup_type = argv[1];
+ if (!((lookup_type == "banid") || (lookup_type == "ipid") || (lookup_type == "hdid"))) {
+ sendServerMessage("Invalid ID type.");
+ return;
+ }
+ }
+ else {
+ sendServerMessage("Invalid command.");
+ return;
+ }
+ QString id = argv[0];
+ for (DBManager::BanInfo ban : server->db_manager->getBanInfo(lookup_type, id)) {
+ QString banned_until;
+ if (ban.duration == -2)
+ banned_until = "The heat death of the universe";
+ else
+ banned_until = QDateTime::fromSecsSinceEpoch(ban.time).addSecs(ban.duration).toString("dd.MM.yyyy, hh:mm");
+ ban_info << "Affected IPID: " + ban.ipid;
+ ban_info << "Affected HDID: " + ban.hdid;
+ ban_info << "Reason for ban: " + ban.reason;
+ ban_info << "Date of ban: " + QDateTime::fromSecsSinceEpoch(ban.time).toString("dd.MM.yyyy, hh:mm");
+ ban_info << "Ban lasts until: " + banned_until;
+ ban_info << "-----";
+ }
+ sendServerMessage(ban_info.join("\n"));
+}
+
+void AOClient::cmdReload(int argc, QStringList argv)
+{
+ server->loadServerConfig();
+ server->loadCommandConfig();
+ emit server->reloadRequest(server->server_name, server->server_desc);
+ sendServerMessage("Reloaded configurations");
+}
+
diff --git a/src/commands/music.cpp b/src/commands/music.cpp
new file mode 100644
index 0000000..4bde396
--- /dev/null
+++ b/src/commands/music.cpp
@@ -0,0 +1,80 @@
+//////////////////////////////////////////////////////////////////////////////////////
+// akashi - a server for Attorney Online 2 //
+// Copyright (C) 2020 scatterflower //
+// //
+// 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 . //
+//////////////////////////////////////////////////////////////////////////////////////
+#include "include/aoclient.h"
+
+// This file is for commands under the music category in aoclient.h
+// Be sure to register the command in the header before adding it here!
+
+void AOClient::cmdPlay(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ QString song = argv.join(" ");
+ area->current_music = song;
+ area->music_played_by = showname;
+ AOPacket music_change("MC", {song, QString::number(server->getCharID(current_char)), showname, "1", "0"});
+ server->broadcast(music_change, current_area);
+}
+
+void AOClient::cmdCurrentMusic(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ if (area->current_music != "" && area->current_music != "~stop.mp3") // dummy track for stopping music
+ sendServerMessage("The current song is " + area->current_music + " played by " + area->music_played_by);
+ else
+ sendServerMessage("There is no music playing.");
+}
+
+void AOClient::cmdBlockDj(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (target->is_dj_blocked)
+ sendServerMessage("That player is already DJ blocked!");
+ else {
+ sendServerMessage("DJ blocked player.");
+ target->sendServerMessage("You were blocked from changing the music by a moderator. " + getReprimand());
+ }
+ target->is_dj_blocked = true;
+}
+
+void AOClient::cmdUnBlockDj(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (!target->is_dj_blocked)
+ sendServerMessage("That player is not DJ blocked!");
+ else {
+ sendServerMessage("DJ permissions restored to player.");
+ target->sendServerMessage("A moderator restored your music permissions. " + getReprimand(true));
+ }
+ target->is_dj_blocked = false;
+}
diff --git a/src/commands/roleplay.cpp b/src/commands/roleplay.cpp
new file mode 100644
index 0000000..ea31a64
--- /dev/null
+++ b/src/commands/roleplay.cpp
@@ -0,0 +1,190 @@
+//////////////////////////////////////////////////////////////////////////////////////
+// akashi - a server for Attorney Online 2 //
+// Copyright (C) 2020 scatterflower //
+// //
+// 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 . //
+//////////////////////////////////////////////////////////////////////////////////////
+#include "include/aoclient.h"
+
+// This file is for commands under the roleplay category in aoclient.h
+// Be sure to register the command in the header before adding it here!
+
+void AOClient::cmdFlip(int argc, QStringList argv)
+{
+ QString sender_name = ooc_name;
+ QStringList faces = {"heads","tails"};
+ QString face = faces[AOClient::genRand(0,1)];
+ sendServerMessage(sender_name + " flipped a coin and got " + face + ".");
+}
+
+void AOClient::cmdRoll(int argc, QStringList argv)
+{
+ diceThrower(argc, argv, RollType::ROLL);
+}
+
+void AOClient::cmdRollP(int argc, QStringList argv)
+{
+ diceThrower(argc, argv, RollType::ROLLP);
+}
+
+void AOClient::cmdTimer(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+
+ // Called without arguments
+ // Shows a brief of all timers
+ if (argc == 0) {
+ QStringList timers;
+ timers.append("Currently active timers:");
+ for (int i = 0; i <= 4; i++) {
+ timers.append(getAreaTimer(area->index, i));
+ }
+ sendServerMessage(timers.join("\n"));
+ return;
+ }
+
+ // Called with more than one argument
+ bool ok;
+ int timer_id = argv[0].toInt(&ok);
+ if (!ok || timer_id < 0 || timer_id > 4) {
+ sendServerMessage("Invalid timer ID. Timer ID must be a whole number between 0 and 4.");
+ return;
+ }
+
+ // Called with one argument
+ // Shows the status of one timer
+ if (argc == 1) {
+ sendServerMessage(getAreaTimer(area->index, timer_id));
+ return;
+ }
+
+ // Called with more than one argument
+ // Updates the state of a timer
+
+ // Select the proper timer
+ // Check against permissions if global timer is selected
+ QTimer* requested_timer;
+ if (timer_id == 0) {
+ if (!checkAuth(ACLFlags.value("GLOBAL_TIMER"))) {
+ sendServerMessage("You are not authorized to alter the global timer.");
+ return;
+ }
+ requested_timer = server->timer;
+ }
+ else
+ requested_timer = area->timers[timer_id - 1];
+
+ AOPacket show_timer("TI", {QString::number(timer_id), "2"});
+ AOPacket hide_timer("TI", {QString::number(timer_id), "3"});
+ bool is_global = timer_id == 0;
+
+ // Set the timer's time remaining if the second
+ // argument is a valid time
+ QTime requested_time = QTime::fromString(argv[1], "hh:mm:ss");
+ if (requested_time.isValid()) {
+ requested_timer->setInterval(QTime(0,0).msecsTo(requested_time));
+ requested_timer->start();
+ sendServerMessage("Set timer " + QString::number(timer_id) + " to " + argv[1] + ".");
+ AOPacket update_timer("TI", {QString::number(timer_id), "0", QString::number(QTime(0,0).msecsTo(requested_time))});
+ is_global ? server->broadcast(show_timer) : server->broadcast(show_timer, current_area); // Show the timer
+ is_global ? server->broadcast(update_timer) : server->broadcast(update_timer, current_area);
+ return;
+ }
+ // Otherwise, update the state of the timer
+ else {
+ if (argv[1] == "start") {
+ requested_timer->start();
+ sendServerMessage("Started timer " + QString::number(timer_id) + ".");
+ AOPacket update_timer("TI", {QString::number(timer_id), "0", QString::number(QTime(0,0).msecsTo(QTime(0,0).addMSecs(requested_timer->remainingTime())))});
+ is_global ? server->broadcast(show_timer) : server->broadcast(show_timer, current_area);
+ is_global ? server->broadcast(update_timer) : server->broadcast(update_timer, current_area);
+ }
+ else if (argv[1] == "pause" || argv[1] == "stop") {
+ requested_timer->setInterval(requested_timer->remainingTime());
+ requested_timer->stop();
+ sendServerMessage("Stopped timer " + QString::number(timer_id) + ".");
+ AOPacket update_timer("TI", {QString::number(timer_id), "1", QString::number(QTime(0,0).msecsTo(QTime(0,0).addMSecs(requested_timer->interval())))});
+ is_global ? server->broadcast(update_timer) : server->broadcast(update_timer, current_area);
+ }
+ else if (argv[1] == "hide" || argv[1] == "unset") {
+ requested_timer->setInterval(0);
+ requested_timer->stop();
+ sendServerMessage("Hid timer " + QString::number(timer_id) + ".");
+ // Hide the timer
+ is_global ? server->broadcast(hide_timer) : server->broadcast(hide_timer, current_area);
+ }
+ }
+}
+
+void AOClient::cmdNoteCard(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ if (area->notecards.keys().contains(current_char))
+ area->notecards.remove(current_char);
+ QString notecard = argv.join(" ");
+ area->notecards[current_char] = notecard;
+ sendServerMessageArea(current_char + " wrote a note card.");
+}
+
+void AOClient::cmdNoteCardClear(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ if (area->notecards.keys().contains(current_char)) {
+ area->notecards.remove(current_char);
+ sendServerMessageArea(current_char + " erased their note card.");
+ }
+ else
+ sendServerMessage("You do not have a note card.");
+}
+
+void AOClient::cmdNoteCardReveal(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ if (area->notecards.isEmpty()) {
+ sendServerMessage("There are no cards to reveal in this area.");
+ return;
+ }
+ QStringList message;
+ message << "Note cards have been revealed.";
+ QMap::iterator i;
+ for (i = area->notecards.begin(); i != area->notecards.end(); ++i)
+ message << i.key() + ": " + i.value();
+ sendServerMessageArea(message.join("\n"));
+ area->notecards.clear();
+}
+
+void AOClient::cmd8Ball(int argc, QStringList argv)
+{
+ if (server->magic_8ball_answers.isEmpty()) {
+ qWarning() << "8ball.txt is empty!";
+ sendServerMessage("8ball.txt is empty.");
+ }
+ else {
+ QString response = server->magic_8ball_answers[(genRand(1, server->magic_8ball_answers.size() - 1))];
+ QString sender_name = ooc_name;
+ QString sender_message = argv.join(" ");
+
+ sendServerMessageArea(sender_name + " asked the magic 8-ball, \"" + sender_message + "\" and the answer is: " + response);
+ }
+}
+
+void AOClient::cmdSubTheme(int argc, QStringList argv)
+{
+ QString subtheme = argv.join(" ");
+ for (AOClient* client : server->clients) {
+ if (client->current_area == current_area)
+ client->sendPacket("ST", {subtheme, "1"});
+ }
+ sendServerMessageArea("Subtheme was set to " + subtheme);
+}
From 58f2d1e2b7f811db8cc7433f6e07c01b4ef7dc86 Mon Sep 17 00:00:00 2001
From: MangosArentLiterature
<58055358+MangosArentLiterature@users.noreply.github.com>
Date: Thu, 15 Apr 2021 18:00:04 -0500
Subject: [PATCH 3/5] Revert "Merge branch 'master' into command-split"
This reverts commit b3d170c01936bc21ee2ac8b6a1fa1a02ff93f5d9, reversing
changes made to 885de7141704b5e97fc87a55278474686e9dcd55.
---
bin/config_sample/areas.ini | 4 +-
include/aoclient.h | 75 +-
include/area_data.h | 5 -
include/server.h | 5 -
src/aoclient.cpp | 17 +-
src/area_data.cpp | 1 -
src/commands.cpp | 1706 -----------------------------------
src/packets.cpp | 65 +-
src/server.cpp | 18 +-
src/testimony_recorder.cpp | 1 -
10 files changed, 17 insertions(+), 1880 deletions(-)
diff --git a/bin/config_sample/areas.ini b/bin/config_sample/areas.ini
index 066fcc8..7dc04e7 100644
--- a/bin/config_sample/areas.ini
+++ b/bin/config_sample/areas.ini
@@ -4,12 +4,10 @@ protected_area=true
iniswap_allowed=false
evidence_mod=cm
blankposting_allowed=true
-force_immediate=true
[1:Courtroom 1]
background=gs4
protected_area=false
iniswap_allowed=true
evidence_mod=ffa
-blankposting_allowed=true
-force_immediate=false
+blankposting_allowed=true
\ No newline at end of file
diff --git a/include/aoclient.h b/include/aoclient.h
index 1bc4f0e..5035b6b 100644
--- a/include/aoclient.h
+++ b/include/aoclient.h
@@ -53,11 +53,7 @@ class AOClient : public QObject {
AOClient(Server* p_server, QTcpSocket* p_socket, QObject* parent = nullptr, int user_id = 0)
: QObject(parent), id(user_id), remote_ip(p_socket->peerAddress()), password(""),
joined(false), current_area(0), current_char(""), socket(p_socket), server(p_server),
- is_partial(false), last_wtce_time(0) {
- afk_timer = new QTimer;
- afk_timer->setSingleShot(true);
- connect(afk_timer, SIGNAL(timeout()), this, SLOT(onAfkTimeout()));
- };
+ is_partial(false), last_wtce_time(0) {};
/**
* @brief Destructor for the AOClient instance.
@@ -222,12 +218,6 @@ class AOClient : public QObject {
{"SUPER", ~0ULL },
};
-
- /**
- * @brief A list of 5 casing preferences (def, pro, judge, jury, steno)
- */
- QList casing_preferences = {false, false, false, false, false};
-
/**
* @brief If true, the client's in-character messages will have their word order randomised.
*/
@@ -243,18 +233,6 @@ class AOClient : public QObject {
*/
bool is_gimped = false;
- /**
- * @brief If true, the client will be marked as AFK in /getarea. Automatically applied when a configurable
- * amount of time has passed since the last interaction, or manually applied by /afk.
- */
- bool is_afk = false;
-
- /**
- * @brief Timer for tracking user interaction. Automatically restarted whenever a user interacts (i.e. sends any packet besides CH)
- */
- QTimer* afk_timer;
-
-
public slots:
/**
* @brief A slot for when the client disconnects from the server.
@@ -283,11 +261,6 @@ class AOClient : public QObject {
*/
void sendPacket(QString header);
- /**
- * @brief A slot for when the client's AFK timer runs out.
- */
- void onAfkTimeout();
-
private:
/**
* @brief The TCP socket used to communicate with the client.
@@ -499,12 +472,6 @@ 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);
-
///@}
/**
@@ -655,8 +622,6 @@ 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 }},
};
/**
@@ -1102,7 +1067,7 @@ class AOClient : public QObject {
*
* @iscommand
*/
- void cmdAllowBlankposting(int argc, QStringList argv);
+ void cmdAllow_Blankposting(int argc, QStringList argv);
/**
* @brief Looks up info on a ban.
@@ -1570,33 +1535,6 @@ class AOClient : public QObject {
void cmdCurrentMusic(int argc, QStringList argv);
- /**
- * @brief Toggles immediate text processing in the current area.
- *
- * @details No arguments.
- *
- * @iscommand
- */
- void cmdForceImmediate(int argc, QStringList argv);
-
- /**
- * @brief Toggles whether iniswaps are allowed in the current area.
- *
- * @details No arguments.
- *
- * @iscommand
- */
- void cmdAllowIniswap(int argc, QStringList argv);
-
- /**
- * @brief Toggles whether this client is considered AFK.
- *
- * @details No arguments.
- *
- * @iscommand
- */
- void cmdAfk(int argc, QStringList argv);
-
///@}
/**
@@ -1829,8 +1767,7 @@ class AOClient : public QObject {
{"8ball", {ACLFlags.value("NONE"), 1, &AOClient::cmd8Ball}},
{"lm", {ACLFlags.value("MODCHAT"), 1, &AOClient::cmdLM}},
{"judgelog", {ACLFlags.value("CM"), 0, &AOClient::cmdJudgeLog}},
- {"allowblankposting", {ACLFlags.value("MODCHAT"), 0, &AOClient::cmdAllowBlankposting}},
- {"allow_blankposting", {ACLFlags.value("MODCHAT"), 0, &AOClient::cmdAllowBlankposting}},
+ {"allow_blankposting", {ACLFlags.value("MODCHAT"), 0, &AOClient::cmdAllow_Blankposting}},
{"gimp", {ACLFlags.value("MUTE"), 1, &AOClient::cmdGimp}},
{"ungimp", {ACLFlags.value("MUTE"), 1, &AOClient::cmdUnGimp}},
{"baninfo", {ACLFlags.value("BAN"), 1, &AOClient::cmdBanInfo}},
@@ -1839,17 +1776,11 @@ class AOClient : public QObject {
{"pause", {ACLFlags.value("CM"), 0, &AOClient::cmdPauseTestimony}},
{"delete", {ACLFlags.value("CM"), 0, &AOClient::cmdDeleteStatement}},
{"update", {ACLFlags.value("CM"), 0, &AOClient::cmdUpdateStatement}},
- {"add", {ACLFlags.value("CM"), 0, &AOClient::cmdAddStatement}},
{"reload", {ACLFlags.value("SUPER"), 0, &AOClient::cmdReload}},
{"disemvowel", {ACLFlags.value("MUTE"), 1, &AOClient::cmdDisemvowel}},
{"undisemvowel", {ACLFlags.value("MUTE"), 1, &AOClient::cmdUnDisemvowel}},
{"shake", {ACLFlags.value("MUTE"), 1, &AOClient::cmdShake}},
{"unshake", {ACLFlags.value("MUTE"), 1, &AOClient::cmdUnShake}},
- {"forceimmediate", {ACLFlags.value("CM"), 0, &AOClient::cmdForceImmediate}},
- {"force_noint_pres", {ACLFlags.value("CM"), 0, &AOClient::cmdForceImmediate}},
- {"allowiniswap", {ACLFlags.value("CM"), 0, &AOClient::cmdAllowIniswap}},
- {"allow_iniswap", {ACLFlags.value("CM"), 0, &AOClient::cmdAllowIniswap}},
- {"afk", {ACLFlags.value("NONE"), 0, &AOClient::cmdAfk}},
};
/**
diff --git a/include/area_data.h b/include/area_data.h
index 23df38f..5cab8ef 100644
--- a/include/area_data.h
+++ b/include/area_data.h
@@ -344,11 +344,6 @@ class AreaData : public QObject {
* @brief The value of logger in config.ini.
*/
QString log_type;
-
- /**
- * @brief Whether or not to force immediate text processing in this area
- */
- bool force_immediate;
};
#endif // AREA_DATA_H
diff --git a/include/server.h b/include/server.h
index 0017621..91fb5ef 100644
--- a/include/server.h
+++ b/include/server.h
@@ -232,11 +232,6 @@ class Server : public QObject {
*/
int max_dice;
- /**
- * @brief The amount of time in seconds to wait before marking a user AFK.
- */
- int afk_timeout;
-
/**
* @brief The server-wide global timer.
*/
diff --git a/src/aoclient.cpp b/src/aoclient.cpp
index 6e8dfbd..762d99f 100644
--- a/src/aoclient.cpp
+++ b/src/aoclient.cpp
@@ -77,13 +77,6 @@ void AOClient::handlePacket(AOPacket packet)
return;
}
- if (packet.header != "CH") {
- if (is_afk)
- sendServerMessage("You are no longer AFK.");
- is_afk = false;
- afk_timer->start(server->afk_timeout * 1000);
- }
-
if (packet.contents.length() < info.minArgs) {
#ifdef NET_DEBUG
qDebug() << "Invalid packet args length. Minimum is" << info.minArgs << "but only" << packet.contents.length() << "were given.";
@@ -318,17 +311,9 @@ bool AOClient::checkAuth(unsigned long long acl_mask)
return true;
}
-
QString AOClient::getIpid() { return ipid; }
-Server* AOClient::getServer() { return server; }
-
-void AOClient::onAfkTimeout()
-{
- if (!is_afk)
- sendServerMessage("You are now AFK.");
- is_afk = true;
-}
+Server* AOClient::getServer() { return server; };
AOClient::~AOClient() {
socket->deleteLater();
diff --git a/src/area_data.cpp b/src/area_data.cpp
index 0653597..c40271c 100644
--- a/src/area_data.cpp
+++ b/src/area_data.cpp
@@ -39,7 +39,6 @@ AreaData::AreaData(QString p_name, int p_index) :
bg_locked = areas_ini.value("bg_locked", "false").toBool();
QString configured_evi_mod = areas_ini.value("evidence_mod", "FFA").toString().toLower();
blankposting_allowed = areas_ini.value("blankposting_allowed","true").toBool();
- force_immediate = areas_ini.value("force_immediate", "false").toBool();
areas_ini.endGroup();
QSettings config_ini("config/config.ini", QSettings::IniFormat);
config_ini.beginGroup("Options");
diff --git a/src/commands.cpp b/src/commands.cpp
index 135c06a..9824cfa 100644
--- a/src/commands.cpp
+++ b/src/commands.cpp
@@ -18,1709 +18,3 @@
#include "include/aoclient.h"
// Be sure to register the command in the header before adding it here!
-
-void AOClient::cmdDefault(int argc, QStringList argv)
-{
- sendServerMessage("Invalid command.");
- return;
-}
-
-void AOClient::cmdLogin(int argc, QStringList argv)
-{
- if (authenticated) {
- sendServerMessage("You are already logged in!");
- return;
- }
-
- if (server->auth_type == "simple") {
- if (server->modpass == "") {
- sendServerMessage("No modpass is set! Please set a modpass before authenticating.");
- }
- else if(argv[0] == server->modpass) {
- sendPacket("AUTH", {"1"}); // Client: "You were granted the Disable Modcalls button."
- sendServerMessage("Logged in as a moderator."); // pre-2.9.1 clients are hardcoded to display the mod UI when this string is sent in OOC
- authenticated = true;
- }
- else {
- sendPacket("AUTH", {"0"}); // Client: "Login unsuccessful."
- sendServerMessage("Incorrect password.");
- }
- server->areas.value(current_area)->logger->logLogin(this, authenticated, "moderator");
- }
- else if (server->auth_type == "advanced") {
- if (argc < 2) {
- sendServerMessage("You must specify a username and a password");
- return;
- }
- QString username = argv[0];
- QString password = argv[1];
- if (server->db_manager->authenticate(username, password)) {
- moderator_name = username;
- authenticated = true;
- sendPacket("AUTH", {"1"}); // Client: "You were granted the Disable Modcalls button."
- if (version.release <= 2 && version.major <= 9 && version.minor <= 0)
- sendServerMessage("Logged in as a moderator."); // pre-2.9.1 clients are hardcoded to display the mod UI when this string is sent in OOC
- sendServerMessage("Welcome, " + username);
- }
- else {
- sendPacket("AUTH", {"0"}); // Client: "Login unsuccessful."
- sendServerMessage("Incorrect password.");
- }
- server->areas.value(current_area)->logger->logLogin(this, authenticated, username);
- }
- else {
- qWarning() << "config.ini has an unrecognized auth_type!";
- sendServerMessage("Config.ini contains an invalid auth_type, please check your config.");
- }
-}
-
-void AOClient::cmdGetAreas(int argc, QStringList argv)
-{
- QStringList entries;
- entries.append("== Area List ==");
- for (int i = 0; i < server->area_names.length(); i++) {
- QStringList cur_area_lines = buildAreaList(i);
- entries.append(cur_area_lines);
- }
- sendServerMessage(entries.join("\n"));
-}
-
-void AOClient::cmdGetArea(int argc, QStringList argv)
-{
- QStringList entries = buildAreaList(current_area);
- sendServerMessage(entries.join("\n"));
-}
-
-void AOClient::cmdBan(int argc, QStringList argv)
-{
- QString args_str = argv[1];
- if (argc > 2) {
- for (int i = 2; i < argc; i++)
- args_str += " " + argv[i];
- }
-
- DBManager::BanInfo ban;
-
- QRegularExpression quoteMatcher("['\"](.+?)[\"']");
- QRegularExpressionMatchIterator matches = quoteMatcher.globalMatch(args_str);
- QList unquoted_args;
- while (matches.hasNext()) {
- QRegularExpressionMatch match = matches.next();
- unquoted_args.append(match.captured(1));
- }
-
- QString duration = "perma";
-
- if (unquoted_args.length() < 1) {
- sendServerMessage("Invalid syntax. Usage:\n/ban \"\" \"\"");
- return;
- }
-
- ban.reason = unquoted_args.at(0);
- if (unquoted_args.length() > 1)
- duration = unquoted_args.at(1);
-
- long long duration_seconds = 0;
- if (duration == "perma")
- duration_seconds = -2;
- else
- duration_seconds = parseTime(duration);
-
- if (duration_seconds == -1) {
- sendServerMessage("Invalid time format. Format example: 1h30m");
- return;
- }
-
- ban.duration = duration_seconds;
-
- ban.ipid = argv[0];
- ban.time = QDateTime::currentDateTime().toSecsSinceEpoch();
- bool ban_logged = false;
- int kick_counter = 0;
-
- if (argc > 2) {
- for (int i = 2; i < argv.length(); i++) {
- ban.reason += " " + argv[i];
- }
- }
-
- for (AOClient* client : server->getClientsByIpid(ban.ipid)) {
- if (!ban_logged) {
- ban.ip = client->remote_ip;
- ban.hdid = client->hwid;
- server->db_manager->addBan(ban);
- sendServerMessage("Banned user with ipid " + ban.ipid + " for reason: " + ban.reason);
- ban_logged = true;
- }
- client->sendPacket("KB", {ban.reason + "\nID: " + QString::number(server->db_manager->getBanID(ban.ip)) + "\nUntil: " + QDateTime::fromSecsSinceEpoch(ban.time).addSecs(ban.duration).toString("dd.MM.yyyy, hh:mm")});
- client->socket->close();
- kick_counter++;
- }
-
- if (kick_counter > 1)
- sendServerMessage("Kicked " + QString::number(kick_counter) + " clients with matching ipids.");
- if (!ban_logged)
- sendServerMessage("User with ipid not found!");
-}
-
-void AOClient::cmdKick(int argc, QStringList argv)
-{
- QString target_ipid = argv[0];
- QString reason = argv[1];
- int kick_counter = 0;
-
- if (argc > 2) {
- for (int i = 2; i < argv.length(); i++) {
- reason += " " + argv[i];
- }
- }
-
- for (AOClient* client : server->getClientsByIpid(target_ipid)) {
- client->sendPacket("KK", {reason});
- client->socket->close();
- kick_counter++;
- }
-
- if (kick_counter > 0)
- sendServerMessage("Kicked " + QString::number(kick_counter) + " client(s) with ipid " + target_ipid + " for reason: " + reason);
- else
- sendServerMessage("User with ipid not found!");
-}
-
-void AOClient::cmdChangeAuth(int argc, QStringList argv)
-{
- if (server->auth_type == "simple") {
- change_auth_started = true;
- sendServerMessage("WARNING!\nThis command will change how logging in as a moderator works.\nOnly proceed if you know what you are doing\nUse the command /rootpass to set the password for your root account.");
- }
-}
-
-void AOClient::cmdSetRootPass(int argc, QStringList argv)
-{
- if (!change_auth_started)
- return;
-
- sendServerMessage("Changing auth type and setting root password.\nLogin again with /login root [password]");
- authenticated = false;
- QSettings settings("config/config.ini", QSettings::IniFormat);
- settings.beginGroup("Options");
- settings.setValue("auth", "advanced");
- server->auth_type = "advanced";
-
-#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
- qsrand(QDateTime::currentMSecsSinceEpoch());
- quint32 upper_salt = qrand();
- quint32 lower_salt = qrand();
- quint64 salt_number = (upper_salt << 32) | lower_salt;
-#else
- quint64 salt_number = QRandomGenerator::system()->generate64();
-#endif
- QString salt = QStringLiteral("%1").arg(salt_number, 16, 16, QLatin1Char('0'));
-
- server->db_manager->createUser("root", salt, argv[0], ACLFlags.value("SUPER"));
-}
-
-void AOClient::cmdSetBackground(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (authenticated || !area->bg_locked) {
- if (server->backgrounds.contains(argv[0])) {
- area->background = argv[0];
- server->broadcast(AOPacket("BN", {argv[0]}), current_area);
- sendServerMessageArea(current_char + " changed the background to " + argv[0]);
- }
- else {
- sendServerMessage("Invalid background name.");
- }
- }
- else {
- sendServerMessage("This area's background is locked.");
- }
-}
-
-void AOClient::cmdBgLock(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- area->bg_locked = true;
- server->broadcast(AOPacket("CT", {"Server", current_char + " locked the background.", "1"}), current_area);
-}
-
-void AOClient::cmdBgUnlock(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- area->bg_locked = false;
- server->broadcast(AOPacket("CT", {"Server", current_char + " unlocked the background.", "1"}), current_area);
-}
-
-void AOClient::cmdAddUser(int argc, QStringList argv)
-{
-#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
- qsrand(QDateTime::currentMSecsSinceEpoch());
- quint32 upper_salt = qrand();
- quint32 lower_salt = qrand();
- quint64 salt_number = (upper_salt << 32) | lower_salt;
-#else
- quint64 salt_number = QRandomGenerator::system()->generate64();
-#endif
- QString salt = QStringLiteral("%1").arg(salt_number, 16, 16, QLatin1Char('0'));
-
- if (server->db_manager->createUser(argv[0], salt, argv[1], ACLFlags.value("NONE")))
- sendServerMessage("Created user " + argv[0] + ".\nUse /addperm to modify their permissions.");
- else
- sendServerMessage("Unable to create user " + argv[0] + ".\nDoes a user with that name already exist?");
-}
-
-void AOClient::cmdRemoveUser(int argc, QStringList argv)
-{
- if (server->db_manager->deleteUser(argv[0]))
- sendServerMessage("Successfully removed user " + argv[0] + ".");
- else
- sendServerMessage("Unable to remove user " + argv[0] + ".\nDoes it exist?");
-}
-
-void AOClient::cmdListPerms(int argc, QStringList argv)
-{
- unsigned long long user_acl = server->db_manager->getACL(moderator_name);
- QStringList message;
- if (argc == 0) {
- // Just print out all permissions available to the user.
- message.append("You have been given the following permissions:");
- for (QString perm : ACLFlags.keys()) {
- if (perm == "NONE"); // don't need to list this one
- else if (perm == "SUPER") {
- if (user_acl == ACLFlags.value("SUPER")) // This has to be checked separately, because SUPER & anything will always be truthy
- message.append("SUPER (Be careful! This grants the user all permissions.)");
- }
- else if ((ACLFlags.value(perm) & user_acl) == 0); // user doesn't have this permission, don't print it
- else
- message.append(perm);
- }
- }
- else {
- if ((user_acl & ACLFlags.value("MODIFY_USERS")) == 0) {
- sendServerMessage("You do not have permission to view other users' permissions.");
- return;
- }
-
- message.append("User " + argv[0] + " has the following permissions:");
- unsigned long long acl = server->db_manager->getACL(argv[0]);
- if (acl == 0) {
- sendServerMessage("This user either doesn't exist, or has no permissions set.");
- return;
- }
-
- for (QString perm : ACLFlags.keys()) {
- if ((ACLFlags.value(perm) & acl) != 0 && perm != "SUPER") {
- message.append(perm);
- }
- }
- }
- sendServerMessage(message.join("\n"));
-}
-
-void AOClient::cmdAddPerms(int argc, QStringList argv)
-{
- unsigned long long user_acl = server->db_manager->getACL(moderator_name);
- argv[1] = argv[1].toUpper();
-
- if (!ACLFlags.keys().contains(argv[1])) {
- sendServerMessage("That permission doesn't exist!");
- return;
- }
-
- if (argv[1] == "SUPER") {
- if (user_acl != ACLFlags.value("SUPER")) {
- // This has to be checked separately, because SUPER & anything will always be truthy
- sendServerMessage("You aren't allowed to add that permission!");
- return;
- }
- }
- if (argv[1] == "NONE") {
- sendServerMessage("Added no permissions!");
- return;
- }
-
- unsigned long long newperm = ACLFlags.value(argv[1]);
- if ((newperm & user_acl) != 0) {
- if (server->db_manager->updateACL(argv[0], newperm, true))
- sendServerMessage("Successfully added permission " + argv[1] + " to user " + argv[0]);
- else
- sendServerMessage(argv[0] + " wasn't found!");
- return;
- }
-
- sendServerMessage("You aren't allowed to add that permission!");
-}
-
-void AOClient::cmdRemovePerms(int argc, QStringList argv)
-{
- unsigned long long user_acl = server->db_manager->getACL(moderator_name);
- argv[1] = argv[1].toUpper();
-
- if (!ACLFlags.keys().contains(argv[1])) {
- sendServerMessage("That permission doesn't exist!");
- return;
- }
-
- if (argv[0] == "root") {
- sendServerMessage("You cannot change the permissions of the root account!");
- return;
- }
-
- if (argv[1] == "SUPER") {
- if (user_acl != ACLFlags.value("SUPER")) {
- // This has to be checked separately, because SUPER & anything will always be truthy
- sendServerMessage("You aren't allowed to remove that permission!");
- return;
- }
- }
- if (argv[1] == "NONE") {
- sendServerMessage("Removed no permissions!");
- return;
- }
-
- unsigned long long newperm = ACLFlags.value(argv[1]);
- if ((newperm & user_acl) != 0) {
- if (server->db_manager->updateACL(argv[0], newperm, false))
- sendServerMessage("Successfully removed permission " + argv[1] + " from user " + argv[0]);
- else
- sendServerMessage(argv[0] + " wasn't found!");
- return;
- }
-
- sendServerMessage("You aren't allowed to remove that permission!");
-}
-
-void AOClient::cmdListUsers(int argc, QStringList argv)
-{
- QStringList users = server->db_manager->getUsers();
- sendServerMessage("All users:\n" + users.join("\n"));
-}
-
-void AOClient::cmdLogout(int argc, QStringList argv)
-{
- if (!authenticated) {
- sendServerMessage("You are not logged in!");
- return;
- }
- authenticated = false;
- moderator_name = "";
- sendPacket("AUTH", {"-1"}); // Client: "You were logged out."
-}
-
-void AOClient::cmdPos(int argc, QStringList argv)
-{
- changePosition(argv[0]);
- updateEvidenceList(server->areas[current_area]);
-}
-
-void AOClient::cmdForcePos(int argc, QStringList argv)
-{
- bool ok;
- QList targets;
- AreaData* area = server->areas[current_area];
- int target_id = argv[1].toInt(&ok);
- int forced_clients = 0;
- if (!ok && argv[1] != "*") {
- sendServerMessage("That does not look like a valid ID.");
- return;
- }
- else if (ok) {
- AOClient* target_client = server->getClientByID(target_id);
- if (target_client != nullptr)
- targets.append(target_client);
- else {
- sendServerMessage("Target ID not found!");
- return;
- }
- }
-
- else if (argv[1] == "*") { // force all clients in the area
- for (AOClient* client : server->clients) {
- if (client->current_area == current_area)
- targets.append(client);
- }
- }
- for (AOClient* target : targets) {
- target->sendServerMessage("Position forcibly changed by CM.");
- target->changePosition(argv[0]);
- forced_clients++;
- }
- sendServerMessage("Forced " + QString::number(forced_clients) + " into pos " + argv[0] + ".");
-}
-
-void AOClient::cmdG(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- QString sender_area = server->area_names.value(current_area);
- QString sender_message = argv.join(" ");
- for (AOClient* client : server->clients) {
- if (client->global_enabled)
- client->sendPacket("CT", {"[G][" + sender_area + "]" + sender_name, sender_message});
- }
- return;
-}
-
-void AOClient::cmdNeed(int argc, QStringList argv)
-{
- QString sender_area = server->area_names.value(current_area);
- QString sender_message = argv.join(" ");
- sendServerBroadcast({"=== Advert ===\n[" + sender_area + "] needs " + sender_message+ "."});
-}
-
-void AOClient::cmdFlip(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- QStringList faces = {"heads","tails"};
- QString face = faces[AOClient::genRand(0,1)];
- sendServerMessage(sender_name + " flipped a coin and got " + face + ".");
-}
-
-void AOClient::cmdRoll(int argc, QStringList argv)
-{
- diceThrower(argc, argv, RollType::ROLL);
-}
-
-void AOClient::cmdRollP(int argc, QStringList argv)
-{
- diceThrower(argc, argv, RollType::ROLLP);
-}
-
-void AOClient::cmdDoc(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- AreaData* area = server->areas[current_area];
- if (argc == 0) {
- sendServerMessage("Document: " + area->document);
- }
- else {
- area->document = argv.join(" ");
- sendServerMessageArea(sender_name + " changed the document.");
- }
-}
-
-void AOClient::cmdClearDoc(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- AreaData* area = server->areas[current_area];
- area->document = "No document.";
- sendServerMessageArea(sender_name + " cleared the document.");
-}
-
-void AOClient::cmdCM(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- AreaData* area = server->areas[current_area];
- if (area->is_protected) {
- sendServerMessage("This area is protected, you may not become CM.");
- return;
- }
- else if (area->owners.isEmpty()) { // no one owns this area, and it's not protected
- area->owners.append(id);
- area->invited.append(id);
- sendServerMessageArea(sender_name + " is now CM in this area.");
- arup(ARUPType::CM, true);
- }
- else if (!area->owners.contains(id)) { // there is already a CM, and it isn't us
- sendServerMessage("You cannot become a CM in this area.");
- }
- else if (argc == 1) { // we are CM, and we want to make ID argv[0] also CM
- bool ok;
- AOClient* owner_candidate = server->getClientByID(argv[0].toInt(&ok));
- if (!ok) {
- sendServerMessage("That doesn't look like a valid ID.");
- return;
- }
- if (owner_candidate == nullptr) {
- sendServerMessage("Unable to find client with ID " + argv[0] + ".");
- return;
- }
- area->owners.append(owner_candidate->id);
- sendServerMessageArea(owner_candidate->ooc_name + " is now CM in this area.");
- arup(ARUPType::CM, true);
- }
- else {
- sendServerMessage("You are already a CM in this area.");
- }
-}
-
-void AOClient::cmdUnCM(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- int removed = area->owners.removeAll(id);
- area->invited.removeAll(id);
- sendServerMessage("You are no longer CM in this area.");
- arup(ARUPType::CM, true);
- if (area->owners.isEmpty()) {
- area->invited.clear();
- if (area->locked != AreaData::FREE) {
- area->locked = AreaData::FREE;
- arup(ARUPType::LOCKED, true);
- }
- }
-}
-
-void AOClient::cmdInvite(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- bool ok;
- int invited_id = argv[0].toInt(&ok);
- if (!ok) {
- sendServerMessage("That does not look like a valid ID.");
- return;
- }
- else if (server->getClientByID(invited_id) == nullptr) {
- sendServerMessage("No client with that ID found.");
- return;
- }
- else if (area->invited.contains(invited_id)) {
- sendServerMessage("That ID is already on the invite list.");
- return;
- }
- area->invited.append(invited_id);
- sendServerMessage("You invited ID " + argv[0]);
-}
-
-void AOClient::cmdUnInvite(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- bool ok;
- int uninvited_id = argv[0].toInt(&ok);
- if (!ok) {
- sendServerMessage("That does not look like a valid ID.");
- return;
- }
- else if (server->getClientByID(uninvited_id) == nullptr) {
- sendServerMessage("No client with that ID found.");
- return;
- }
- else if (area->owners.contains(uninvited_id)) {
- sendServerMessage("You cannot uninvite a CM!");
- return;
- }
- else if (!area->invited.contains(uninvited_id)) {
- sendServerMessage("That ID is not on the invite list.");
- return;
- }
- area->invited.removeAll(uninvited_id);
- sendServerMessage("You uninvited ID " + argv[0]);
-}
-
-void AOClient::cmdLock(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->locked == AreaData::LockStatus::LOCKED) {
- sendServerMessage("This area is already locked.");
- return;
- }
- sendServerMessageArea("This area is now locked.");
- area->locked = AreaData::LockStatus::LOCKED;
- for (AOClient* client : server->clients) {
- if (client->current_area == current_area && client->joined) {
- area->invited.append(client->id);
- }
- }
- arup(ARUPType::LOCKED, true);
-}
-
-void AOClient::cmdSpectatable(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->locked == AreaData::LockStatus::SPECTATABLE) {
- sendServerMessage("This area is already in spectate mode.");
- return;
- }
- sendServerMessageArea("This area is now spectatable.");
- area->locked = AreaData::LockStatus::SPECTATABLE;
- for (AOClient* client : server->clients) {
- if (client->current_area == current_area && client->joined) {
- area->invited.append(client->id);
- }
- }
- arup(ARUPType::LOCKED, true);
-}
-
-void AOClient::cmdUnLock(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->locked == AreaData::LockStatus::FREE) {
- sendServerMessage("This area is not locked.");
- return;
- }
- sendServerMessageArea("This area is now unlocked.");
- area->locked = AreaData::LockStatus::FREE;
- arup(ARUPType::LOCKED, true);
-}
-
-void AOClient::cmdTimer(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
-
- // Called without arguments
- // Shows a brief of all timers
- if (argc == 0) {
- QStringList timers;
- timers.append("Currently active timers:");
- for (int i = 0; i <= 4; i++) {
- timers.append(getAreaTimer(area->index, i));
- }
- sendServerMessage(timers.join("\n"));
- return;
- }
-
- // Called with more than one argument
- bool ok;
- int timer_id = argv[0].toInt(&ok);
- if (!ok || timer_id < 0 || timer_id > 4) {
- sendServerMessage("Invalid timer ID. Timer ID must be a whole number between 0 and 4.");
- return;
- }
-
- // Called with one argument
- // Shows the status of one timer
- if (argc == 1) {
- sendServerMessage(getAreaTimer(area->index, timer_id));
- return;
- }
-
- // Called with more than one argument
- // Updates the state of a timer
-
- // Select the proper timer
- // Check against permissions if global timer is selected
- QTimer* requested_timer;
- if (timer_id == 0) {
- if (!checkAuth(ACLFlags.value("GLOBAL_TIMER"))) {
- sendServerMessage("You are not authorized to alter the global timer.");
- return;
- }
- requested_timer = server->timer;
- }
- else
- requested_timer = area->timers[timer_id - 1];
-
- AOPacket show_timer("TI", {QString::number(timer_id), "2"});
- AOPacket hide_timer("TI", {QString::number(timer_id), "3"});
- bool is_global = timer_id == 0;
-
- // Set the timer's time remaining if the second
- // argument is a valid time
- QTime requested_time = QTime::fromString(argv[1], "hh:mm:ss");
- if (requested_time.isValid()) {
- requested_timer->setInterval(QTime(0,0).msecsTo(requested_time));
- requested_timer->start();
- sendServerMessage("Set timer " + QString::number(timer_id) + " to " + argv[1] + ".");
- AOPacket update_timer("TI", {QString::number(timer_id), "0", QString::number(QTime(0,0).msecsTo(requested_time))});
- is_global ? server->broadcast(show_timer) : server->broadcast(show_timer, current_area); // Show the timer
- is_global ? server->broadcast(update_timer) : server->broadcast(update_timer, current_area);
- return;
- }
- // Otherwise, update the state of the timer
- else {
- if (argv[1] == "start") {
- requested_timer->start();
- sendServerMessage("Started timer " + QString::number(timer_id) + ".");
- AOPacket update_timer("TI", {QString::number(timer_id), "0", QString::number(QTime(0,0).msecsTo(QTime(0,0).addMSecs(requested_timer->remainingTime())))});
- is_global ? server->broadcast(show_timer) : server->broadcast(show_timer, current_area);
- is_global ? server->broadcast(update_timer) : server->broadcast(update_timer, current_area);
- }
- else if (argv[1] == "pause" || argv[1] == "stop") {
- requested_timer->setInterval(requested_timer->remainingTime());
- requested_timer->stop();
- sendServerMessage("Stopped timer " + QString::number(timer_id) + ".");
- AOPacket update_timer("TI", {QString::number(timer_id), "1", QString::number(QTime(0,0).msecsTo(QTime(0,0).addMSecs(requested_timer->interval())))});
- is_global ? server->broadcast(update_timer) : server->broadcast(update_timer, current_area);
- }
- else if (argv[1] == "hide" || argv[1] == "unset") {
- requested_timer->setInterval(0);
- requested_timer->stop();
- sendServerMessage("Hid timer " + QString::number(timer_id) + ".");
- // Hide the timer
- is_global ? server->broadcast(hide_timer) : server->broadcast(hide_timer, current_area);
- }
- }
-}
-
-void AOClient::cmdEvidenceMod(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- argv[0] = argv[0].toLower();
- if (argv[0] == "cm")
- area->evi_mod = AreaData::EvidenceMod::CM;
- else if (argv[0] == "mod")
- area->evi_mod = AreaData::EvidenceMod::MOD;
- else if (argv[0] == "hiddencm")
- area->evi_mod = AreaData::EvidenceMod::HIDDEN_CM;
- else if (argv[0] == "ffa")
- area->evi_mod = AreaData::EvidenceMod::FFA;
- else {
- sendServerMessage("Invalid evidence mod.");
- return;
- }
- sendServerMessage("Changed evidence mod.");
-
- // Resend evidence lists to everyone in the area
- sendEvidenceList(area);
-}
-
-void AOClient::cmdArea(int argc, QStringList argv)
-{
- bool ok;
- int new_area = argv[0].toInt(&ok);
- if (!ok || new_area >= server->areas.size() || new_area < 0) {
- sendServerMessage("That does not look like a valid area ID.");
- return;
- }
- changeArea(new_area);
-}
-
-void AOClient::cmdPlay(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- QString song = argv.join(" ");
- area->current_music = song;
- area->music_played_by = showname;
- AOPacket music_change("MC", {song, QString::number(server->getCharID(current_char)), showname, "1", "0"});
- server->broadcast(music_change, current_area);
-}
-
-void AOClient::cmdAreaKick(int argc, QStringList argv)
-{
- bool ok;
- int idx = argv[0].toInt(&ok);
- if (!ok) {
- sendServerMessage("That does not look like a valid ID.");
- return;
- }
- AOClient* client_to_kick = server->getClientByID(idx);
- if (client_to_kick == nullptr) {
- sendServerMessage("No client with that ID found.");
- return;
- }
- client_to_kick->changeArea(0);
- sendServerMessage("Client " + argv[0] + " kicked back to area 0.");
-}
-
-void AOClient::cmdSwitch(int argc, QStringList argv)
-{
- int char_id = server->getCharID(argv.join(" "));
- if (char_id == -1) {
- sendServerMessage("That does not look like a valid character.");
- return;
- }
- changeCharacter(char_id);
-}
-
-void AOClient::cmdRandomChar(int argc, QStringList argv)
-{
- int char_id = genRand(0, server->characters.size() - 1);
- changeCharacter(char_id);
-}
-
-void AOClient::cmdToggleGlobal(int argc, QStringList argv)
-{
- global_enabled = !global_enabled;
- QString str_en = global_enabled ? "shown" : "hidden";
- sendServerMessage("Global chat set to " + str_en);
-}
-
-void AOClient::cmdMods(int argc, QStringList argv)
-{
- QStringList entries;
- int online_count = 0;
- for (AOClient* client : server->clients) {
- if (client->authenticated) {
- entries << "---";
- if (server->auth_type != "simple")
- entries << "Moderator: " + client->moderator_name;
- entries << "OOC name: " + client->ooc_name;
- entries << "ID: " + QString::number(client->id);
- entries << "Area: " + QString::number(client->current_area);
- entries << "Character: " + client->current_char;
- online_count++;
- }
- }
- entries << "---";
- entries << "Total online: " << QString::number(online_count);
- sendServerMessage(entries.join("\n"));
-}
-
-void AOClient::cmdHelp(int argc, QStringList argv)
-{
- QStringList entries;
- entries << "Allowed commands:";
- QMap::const_iterator i;
- for (i = commands.constBegin(); i!= commands.constEnd(); ++i) {
- CommandInfo info = i.value();
- if (checkAuth(info.acl_mask)) { // if we are allowed to use this command
- entries << "/" + i.key();
- }
- }
- sendServerMessage(entries.join("\n"));
-}
-
-void AOClient::cmdStatus(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- QString arg = argv[0].toLower();
- if (arg == "idle")
- area->status = AreaData::IDLE;
- else if (arg == "rp")
- area->status = AreaData::RP;
- else if (arg == "casing")
- area->status = AreaData::CASING;
- else if (arg == "looking-for-players" || arg == "lfp")
- area->status = AreaData::LOOKING_FOR_PLAYERS;
- else if (arg == "recess")
- area->status = AreaData::RECESS;
- else if (arg == "gaming")
- area->status = AreaData::GAMING;
- else {
- sendServerMessage("That does not look like a valid status. Valid statuses are idle, rp, casing, lfp, recess, gaming");
- return;
- }
- arup(ARUPType::STATUS, true);
-}
-
-void AOClient::cmdCurrentMusic(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->current_music != "" && area->current_music != "~stop.mp3") // dummy track for stopping music
- sendServerMessage("The current song is " + area->current_music + " played by " + area->music_played_by);
- else
- sendServerMessage("There is no music playing.");
-}
-
-void AOClient::cmdPM(int arc, QStringList argv)
-{
- bool ok;
- int target_id = argv.takeFirst().toInt(&ok); // using takeFirst removes the ID from our list of arguments...
- if (!ok) {
- sendServerMessage("That does not look like a valid ID.");
- return;
- }
- AOClient* target_client = server->getClientByID(target_id);
- if (target_client == nullptr) {
- sendServerMessage("No client with that ID found.");
- return;
- }
- QString message = argv.join(" "); //...which means it will not end up as part of the message
- target_client->sendServerMessage("Message from " + ooc_name + " (" + QString::number(id) + "): " + message);
-}
-
-void AOClient::cmdMOTD(int argc, QStringList argv)
-{
- if (argc == 0) {
- sendServerMessage("=== MOTD ===\r\n" + server->MOTD + "\r\n=============");
- }
- else if (argc > 0) {
- if (checkAuth(ACLFlags.value("MOTD"))) {
- QString MOTD = argv.join(" ");
- server->MOTD = MOTD;
- sendServerMessage("MOTD has been changed.");
- }
- else {
- sendServerMessage("You do not have permission to change the MOTD");
- }
- }
-}
-
-void AOClient::cmdAnnounce(int argc, QStringList argv)
-{
- sendServerBroadcast("=== Announcement ===\r\n" + argv.join(" ") + "\r\n=============");
-}
-
-void AOClient::cmdM(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- QString sender_message = argv.join(" ");
- for (AOClient* client : server->clients) {
- if (client->checkAuth(ACLFlags.value("MODCHAT")))
- client->sendPacket("CT", {"[M]" + sender_name, sender_message});
- }
- return;
-}
-
-void AOClient::cmdGM(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- QString sender_area = server->area_names.value(current_area);
- QString sender_message = argv.join(" ");
- for (AOClient* client : server->clients) {
- if (client->global_enabled) {
- client->sendPacket("CT", {"[G][" + sender_area + "]" + "["+sender_name+"][M]", sender_message});
- }
- }
-}
-
-void AOClient::cmdLM(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- QString sender_message = argv.join(" ");
- server->broadcast(AOPacket("CT", {"["+sender_name+"][M]", sender_message}), current_area);
-}
-
-void AOClient::cmdBans(int argc, QStringList argv)
-{
- QStringList recent_bans;
- recent_bans << "Last 5 bans:";
- recent_bans << "-----";
- for (DBManager::BanInfo ban : server->db_manager->getRecentBans()) {
- QString banned_until;
- if (ban.duration == -2)
- banned_until = "The heat death of the universe";
- else
- banned_until = QDateTime::fromSecsSinceEpoch(ban.time).addSecs(ban.duration).toString("dd.MM.yyyy, hh:mm");
- recent_bans << "Affected IPID: " + ban.ipid;
- recent_bans << "Affected HDID: " + ban.hdid;
- recent_bans << "Reason for ban: " + ban.reason;
- recent_bans << "Date of ban: " + QDateTime::fromSecsSinceEpoch(ban.time).toString("dd.MM.yyyy, hh:mm");
- recent_bans << "Ban lasts until: " + banned_until;
- recent_bans << "-----";
- }
- sendServerMessage(recent_bans.join("\n"));
-}
-
-void AOClient::cmdUnBan(int argc, QStringList argv)
-{
- bool ok;
- int target_ban = argv[0].toInt(&ok);
- if (!ok) {
- sendServerMessage("Invalid ban ID.");
- return;
- }
- else if (server->db_manager->invalidateBan(target_ban))
- sendServerMessage("Successfully invalidated ban " + argv[0] + ".");
- else
- sendServerMessage("Couldn't invalidate ban " + argv[0] + ", are you sure it exists?");
-}
-
-void AOClient::cmdSubTheme(int argc, QStringList argv)
-{
- QString subtheme = argv.join(" ");
- for (AOClient* client : server->clients) {
- if (client->current_area == current_area)
- client->sendPacket("ST", {subtheme, "1"});
- }
- sendServerMessageArea("Subtheme was set to " + subtheme);
-}
-
-void AOClient::cmdAbout(int argc, QStringList argv)
-{
- sendPacket("CT", {"The akashi dev team", "Thank you for using akashi! Made with love by scatterflower, with help from in1tiate and Salanto. akashi " + QCoreApplication::applicationVersion()});
-}
-
-void AOClient::cmdEvidence_Swap(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- int ev_size = area->evidence.size() -1;
-
- if (ev_size < 0) {
- sendServerMessage("No evidence in area.");
- return;
- }
-
- bool ok, ok2;
- int ev_id1 = argv[0].toInt(&ok), ev_id2 = argv[1].toInt(&ok2);
-
- if ((!ok || !ok2)) {
- sendServerMessage("Invalid evidence ID.");
- return;
- }
- if ((ev_id1 < 0) || (ev_id2 < 0)) {
- sendServerMessage("Evidence ID can't be negative.");
- return;
- }
- if ((ev_id2 <= ev_size) && (ev_id1 <= ev_size)) {
-#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
- //swapItemsAt does not exist in Qt older than 5.13
- area->evidence.swap(ev_id1, ev_id2);
-#else
- area->evidence.swapItemsAt(ev_id1, ev_id2);
-#endif
- sendEvidenceList(area);
- sendServerMessage("The evidence " + QString::number(ev_id1) + " and " + QString::number(ev_id2) + " have been swapped.");
- }
- else {
- sendServerMessage("Unable to swap evidence. Evidence ID out of range.");
- }
-}
-
-void AOClient::cmdMute(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (target->is_muted)
- sendServerMessage("That player is already muted!");
- else {
- sendServerMessage("Muted player.");
- target->sendServerMessage("You were muted by a moderator. " + getReprimand());
- }
- target->is_muted = true;
-}
-
-void AOClient::cmdUnMute(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (!target->is_muted)
- sendServerMessage("That player is not muted!");
- else {
- sendServerMessage("Unmuted player.");
- target->sendServerMessage("You were unmuted by a moderator. " + getReprimand(true));
- }
- target->is_muted = false;
-}
-
-void AOClient::cmdOocMute(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (target->is_ooc_muted)
- sendServerMessage("That player is already OOC muted!");
- else {
- sendServerMessage("OOC muted player.");
- target->sendServerMessage("You were OOC muted by a moderator. " + getReprimand());
- }
- target->is_ooc_muted = true;
-}
-
-void AOClient::cmdOocUnMute(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (!target->is_ooc_muted)
- sendServerMessage("That player is not OOC muted!");
- else {
- sendServerMessage("OOC unmuted player.");
- target->sendServerMessage("You were OOC unmuted by a moderator. " + getReprimand(true));
- }
- target->is_ooc_muted = false;
-}
-
-void AOClient::cmdBlockDj(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (target->is_dj_blocked)
- sendServerMessage("That player is already DJ blocked!");
- else {
- sendServerMessage("DJ blocked player.");
- target->sendServerMessage("You were blocked from changing the music by a moderator. " + getReprimand());
- }
- target->is_dj_blocked = true;
-}
-
-void AOClient::cmdUnBlockDj(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (!target->is_dj_blocked)
- sendServerMessage("That player is not DJ blocked!");
- else {
- sendServerMessage("DJ permissions restored to player.");
- target->sendServerMessage("A moderator restored your music permissions. " + getReprimand(true));
- }
- target->is_dj_blocked = false;
-}
-
-void AOClient::cmdBlockWtce(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (target->is_wtce_blocked)
- sendServerMessage("That player is already judge blocked!");
- else {
- sendServerMessage("Revoked player's access to judge controls.");
- target->sendServerMessage("A moderator revoked your judge controls access. " + getReprimand());
- }
- target->is_wtce_blocked = true;
-}
-
-void AOClient::cmdUnBlockWtce(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (!target->is_wtce_blocked)
- sendServerMessage("That player is not judge blocked!");
- else {
- sendServerMessage("Restored player's access to judge controls.");
- target->sendServerMessage("A moderator restored your judge controls access. " + getReprimand(true));
- }
- target->is_wtce_blocked = false;
-}
-
-void AOClient::cmdNoteCard(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->notecards.keys().contains(current_char))
- area->notecards.remove(current_char);
- QString notecard = argv.join(" ");
- area->notecards[current_char] = notecard;
- sendServerMessageArea(current_char + " wrote a note card.");
-}
-
-void AOClient::cmdNoteCardClear(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->notecards.keys().contains(current_char)) {
- area->notecards.remove(current_char);
- sendServerMessageArea(current_char + " erased their note card.");
- }
- else
- sendServerMessage("You do not have a note card.");
-}
-
-void AOClient::cmdNoteCardReveal(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->notecards.isEmpty()) {
- sendServerMessage("There are no cards to reveal in this area.");
- return;
- }
- QStringList message;
- message << "Note cards have been revealed.";
- QMap::iterator i;
- for (i = area->notecards.begin(); i != area->notecards.end(); ++i)
- message << i.key() + ": " + i.value();
- sendServerMessageArea(message.join("\n"));
- area->notecards.clear();
-}
-
-void AOClient::cmd8Ball(int argc, QStringList argv)
-{
- if (server->magic_8ball_answers.isEmpty()) {
- qWarning() << "8ball.txt is empty!";
- sendServerMessage("8ball.txt is empty.");
- }
- else {
- QString response = server->magic_8ball_answers[(genRand(1, server->magic_8ball_answers.size() - 1))];
- QString sender_name = ooc_name;
- QString sender_message = argv.join(" ");
-
- sendServerMessageArea(sender_name + " asked the magic 8-ball, \"" + sender_message + "\" and the answer is: " + response);
- }
-}
-
-void AOClient::cmdJudgeLog(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->judgelog.isEmpty()) {
- sendServerMessage("There have been no judge actions in this area.");
- return;
- }
- QString message = area->judgelog.join("\n");
- //Judgelog contains an IPID, so we shouldn't send that unless the caller has appropriate permissions
- if (checkAuth(ACLFlags.value("KICK")) == 1 || checkAuth(ACLFlags.value("BAN")) == 1) {
- sendServerMessage(message);
- }
- else {
- QString filteredmessage = message.remove(QRegularExpression("[(].*[)]")); //Filter out anything between two parentheses. This should only ever be the IPID
- sendServerMessage(filteredmessage);
- }
-}
-
-void AOClient::cmdAllowBlankposting(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- AreaData* area = server->areas[current_area];
- area->blankposting_allowed = !area->blankposting_allowed;
- if (area->blankposting_allowed == false) {
- sendServerMessageArea(sender_name + " has set blankposting in the area to forbidden.");
- }
- else {
- sendServerMessageArea(sender_name + " has set blankposting in the area to allowed.");
- }
-}
-
-void AOClient::cmdGimp(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (target->is_gimped)
- sendServerMessage("That player is already gimped!");
- else {
- sendServerMessage("Gimped player.");
- target->sendServerMessage("You have been gimped! " + getReprimand());
- }
- target->is_gimped = true;
-}
-
-void AOClient::cmdUnGimp(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (!(target->is_gimped))
- sendServerMessage("That player is not gimped!");
- else {
- sendServerMessage("Ungimped player.");
- target->sendServerMessage("A moderator has ungimped you! " + getReprimand(true));
- }
- target->is_gimped = false;
-}
-void AOClient::cmdBanInfo(int argc, QStringList argv)
-{
- QStringList ban_info;
- ban_info << ("Ban Info for " + argv[0]);
- ban_info << "-----";
- QString lookup_type;
-
- if (argc == 1) {
- lookup_type = "banid";
- }
- else if (argc == 2) {
- lookup_type = argv[1];
- if (!((lookup_type == "banid") || (lookup_type == "ipid") || (lookup_type == "hdid"))) {
- sendServerMessage("Invalid ID type.");
- return;
- }
- }
- else {
- sendServerMessage("Invalid command.");
- return;
- }
- QString id = argv[0];
- for (DBManager::BanInfo ban : server->db_manager->getBanInfo(lookup_type, id)) {
- QString banned_until;
- if (ban.duration == -2)
- banned_until = "The heat death of the universe";
- else
- banned_until = QDateTime::fromSecsSinceEpoch(ban.time).addSecs(ban.duration).toString("dd.MM.yyyy, hh:mm");
- ban_info << "Affected IPID: " + ban.ipid;
- ban_info << "Affected HDID: " + ban.hdid;
- ban_info << "Reason for ban: " + ban.reason;
- ban_info << "Date of ban: " + QDateTime::fromSecsSinceEpoch(ban.time).toString("dd.MM.yyyy, hh:mm");
- ban_info << "Ban lasts until: " + banned_until;
- ban_info << "-----";
- }
- sendServerMessage(ban_info.join("\n"));
-}
-
-void AOClient::cmdTestify(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->test_rec == AreaData::TestimonyRecording::RECORDING) {
- sendServerMessage("Testimony recording is already in progress. Please stop it before starting a new one.");
- }
- else {
- clearTestimony();
- area->statement = 0;
- area->test_rec = AreaData::TestimonyRecording::RECORDING;
- sendServerMessage("Started testimony recording.");
- }
-}
-
-void AOClient::cmdExamine(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->testimony.size() -1 > 0)
- {
- area->test_rec = AreaData::TestimonyRecording::PLAYBACK;
- server->broadcast(AOPacket("RT",{"testimony2"}), current_area);
- server->broadcast(AOPacket("MS", {area->testimony[0]}), current_area);
- area->statement = 0;
- return;
- }
- if (area->test_rec == AreaData::TestimonyRecording::PLAYBACK)
- sendServerMessage("Unable to examine while another examination is running");
- else
- sendServerMessage("Unable to start replay without prior examination.");
-}
-
-void AOClient::cmdDeleteStatement(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- int c_statement = area->statement;
- if (area->testimony.size() - 1 == 0) {
- sendServerMessage("Unable to delete statement. No statements saved in this area.");
- }
- if (c_statement > 0 && area->testimony.size() > 2) {
- area->testimony.remove(c_statement);
- sendServerMessage("The statement with id " + QString::number(c_statement) + " has been deleted from the testimony.");
- }
-}
-
-void AOClient::cmdUpdateStatement(int argc, QStringList argv)
-{
- server->areas[current_area]->test_rec = AreaData::TestimonyRecording::UPDATE;
- sendServerMessage("The next IC-Message will replace the last displayed replay message.");
-}
-
-void AOClient::cmdPauseTestimony(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- area->test_rec = AreaData::TestimonyRecording::STOPPED;
- sendServerMessage("Testimony has been stopped.");
-}
-
-void AOClient::cmdAddStatement(int argc, QStringList argv)
-{
- if (server->areas[current_area]->statement < server->maximum_statements) {
- server->areas[current_area]->test_rec = AreaData::TestimonyRecording::ADD;
- sendServerMessage("The next IC-Message will be inserted into the testimony.");
- }
- else
- sendServerMessage("Unable to add anymore statements. Please remove any unused ones.");
-}
-
-void AOClient::cmdReload(int argc, QStringList argv)
-{
- server->loadServerConfig();
- server->loadCommandConfig();
- emit server->reloadRequest(server->server_name, server->server_desc);
- sendServerMessage("Reloaded configurations");
-}
-
-void AOClient::cmdDisemvowel(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (target->is_disemvoweled)
- sendServerMessage("That player is already disemvoweled!");
- else {
- sendServerMessage("Disemvoweled player.");
- target->sendServerMessage("You have been disemvoweled! " + getReprimand());
- }
- target->is_disemvoweled = true;
-}
-
-void AOClient::cmdUnDisemvowel(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (!(target->is_disemvoweled))
- sendServerMessage("That player is not disemvoweled!");
- else {
- sendServerMessage("Undisemvoweled player.");
- target->sendServerMessage("A moderator has undisemvoweled you! " + getReprimand(true));
- }
- target->is_disemvoweled = false;
-}
-
-void AOClient::cmdShake(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (target->is_shaken)
- sendServerMessage("That player is already shaken!");
- else {
- sendServerMessage("Shook player.");
- target->sendServerMessage("A moderator has shaken your words! " + getReprimand());
- }
- target->is_shaken = true;
-}
-
-void AOClient::cmdUnShake(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (!(target->is_shaken))
- sendServerMessage("That player is not shaken!");
- else {
- sendServerMessage("Unshook player.");
- target->sendServerMessage("A moderator has unshook you! " + getReprimand(true));
- }
- target->is_shaken = false;
-}
-
-void AOClient::cmdForceImmediate(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- area->force_immediate = !area->force_immediate;
- QString state = area->force_immediate ? "on." : "off.";
- sendServerMessage("Forced immediate text processing in this area is now " + state);
-}
-
-void AOClient::cmdAllowIniswap(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- area->iniswap_allowed = !area->iniswap_allowed;
- QString state = area->iniswap_allowed ? "allowed." : "disallowed.";
- sendServerMessage("Iniswapping in this area is now " + state);
-}
-
-void AOClient::cmdAfk(int argc, QStringList argv)
-{
- is_afk = true;
- sendServerMessage("You are now AFK.");
-}
-
-QStringList AOClient::buildAreaList(int area_idx)
-{
- QStringList entries;
- QString area_name = server->area_names[area_idx];
- AreaData* area = server->areas[area_idx];
- entries.append("=== " + area_name + " ===");
- switch (area->locked) {
- case AreaData::LockStatus::LOCKED:
- entries.append("[LOCKED]");
- break;
- case AreaData::LockStatus::SPECTATABLE:
- entries.append("[SPECTATABLE]");
- break;
- case AreaData::LockStatus::FREE:
- default:
- break;
- }
- entries.append("[" + QString::number(area->player_count) + " users][" + QVariant::fromValue(area->status).toString().replace("_", "-") + "]");
- for (AOClient* client : server->clients) {
- if (client->current_area == area_idx && client->joined) {
- QString char_entry = "[" + QString::number(client->id) + "] " + client->current_char;
- if (client->current_char == "")
- char_entry += "Spectator";
- if (area->owners.contains(client->id))
- char_entry.insert(0, "[CM] ");
- if (authenticated)
- char_entry += " (" + client->getIpid() + "): " + client->ooc_name;
- if (client->is_afk)
- char_entry += " [AFK]";
- entries.append(char_entry);
- }
- }
- return entries;
-}
-
-int AOClient::genRand(int min, int max)
-{
-#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
- qsrand(QDateTime::currentMSecsSinceEpoch());
- quint32 random_number = (qrand() % (max - min + 1)) + min;
- return random_number;
-
-#else
- quint32 random_number = QRandomGenerator::system()->bounded(min, max + 1);
- return random_number;
-#endif
-}
-
-void AOClient::diceThrower(int argc, QStringList argv, RollType type)
-{
- QString sender_name = ooc_name;
- int max_value = server->dice_value;
- int max_dice = server->max_dice;
- int bounded_value;
- int bounded_amount;
- QString dice_results;
-
- if (argc == 0) {
- dice_results = QString::number(genRand(1, 6)); // Self-explanatory
- }
- else if (argc == 1) {
- bounded_value = qBound(1, argv[0].toInt(), max_value); // faces, max faces
- dice_results = QString::number(genRand(1, bounded_value));
- }
- else if (argc == 2) {
- bounded_value = qBound(1, argv[0].toInt(), max_value); // 1, faces, max faces
- bounded_amount = qBound(1, argv[1].toInt(), max_dice); // 1, amount, max amount
-
- for (int i = 1; i <= bounded_amount ; i++) // Loop as multiple dices are thrown
- {
- QString dice_result = QString::number(genRand(1, bounded_value));
- if (i == bounded_amount) {
- dice_results = dice_results.append(dice_result);
- }
- else {
- dice_results = dice_results.append(dice_result + ",");
- }
- }
- }
- // Switch to change message behaviour, isEmpty check or the entire server crashes due to an out of range issue in the QStringList
- switch(type)
- {
- case ROLL:
- if (argv.isEmpty()) {
- sendServerMessageArea(sender_name + " rolled " + dice_results + " out of 6");
- }
- else {
- sendServerMessageArea(sender_name + " rolled " + dice_results + " out of " + QString::number(bounded_value));
- }
- break;
- case ROLLP:
- if (argv.isEmpty()) {
- sendServerMessage(sender_name + " rolled " + dice_results + " out of 6");
- sendServerMessageArea((sender_name + " rolled in secret."));
- }
- else {
- sendServerMessageArea(sender_name + " rolled " + dice_results + " out of " + QString::number(bounded_value));
- sendServerMessageArea((sender_name + " rolled in secret."));
- }
- break;
- case ROLLA:
- //Not implemented yet
- default : break;
- }
-}
-
-QString AOClient::getAreaTimer(int area_idx, int timer_idx)
-{
- AreaData* area = server->areas[area_idx];
- QTimer* timer;
- QString timer_name = (timer_idx == 0) ? "Global timer" : "Timer " + QString::number(timer_idx);
-
- if (timer_idx == 0)
- timer = server->timer;
- else if (timer_idx > 0 && timer_idx <= 4)
- timer = area->timers[timer_idx - 1];
- else
- return "Invalid timer ID.";
-
- if (timer->isActive()) {
- QTime current_time = QTime(0,0).addMSecs(timer->remainingTime());
-
- return timer_name + " is at " + current_time.toString("hh:mm:ss.zzz");
- }
- else {
- return timer_name + " is inactive.";
- }
-}
-
-long long AOClient::parseTime(QString input)
-{
- QRegularExpression regex("(?:(?:(?.*?)y)*(?:(?.*?)w)*(?:(?.*?)d)*(?:(?
.*?)h)*(?:(?.*?)m)*(?:(?.*?)s)*)");
- QRegularExpressionMatch match = regex.match(input);
- QString str_year, str_week, str_hour, str_day, str_minute, str_second;
- int year, week, day, hour, minute, second;
-
- str_year = match.captured("year");
- str_week = match.captured("week");
- str_day = match.captured("day");
- str_hour = match.captured("hr");
- str_minute = match.captured("min");
- str_second = match.captured("sec");
-
- bool is_well_formed = false;
- QString concat_str(str_year + str_week + str_day + str_hour + str_minute + str_second);
- concat_str.toInt(&is_well_formed);
-
- if (!is_well_formed) {
- return -1;
- }
-
- year = str_year.toInt();
- week = str_week.toInt();
- day = str_day.toInt();
- hour = str_hour.toInt();
- minute = str_minute.toInt();
- second = str_second.toInt();
-
- long long total = 0;
- total += 31622400 * year;
- total += 604800 * week;
- total += 86400 * day;
- total += 3600 * hour;
- total += 60 * minute;
- total += second;
-
- if (total < 0)
- return -1;
-
- return total;
-}
-
-QString AOClient::getReprimand(bool positive)
-{
- if (positive) {
- return server->praise_list[genRand(0, server->praise_list.size() - 1)];
- }
- else {
- return server->reprimands_list[genRand(0, server->reprimands_list.size() - 1)];
- }
-}
diff --git a/src/packets.cpp b/src/packets.cpp
index 6ddce8a..f271216 100644
--- a/src/packets.cpp
+++ b/src/packets.cpp
@@ -344,59 +344,6 @@ void AOClient::pktEditEvidence(AreaData* area, int argc, QStringList argv, AOPac
sendEvidenceList(area);
}
-void AOClient::pktSetCase(AreaData* area, int argc, QStringList argv, AOPacket packet)
-{
- QList prefs_list;
- 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 = prefs_list;
-}
-
-void AOClient::pktAnnounceCase(AreaData* area, int argc, QStringList argv, AOPacket packet)
-{
- 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);
- }
- 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 (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) + "!";
-
- 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_set);
- if (!matches.isEmpty() && !clients_to_alert.contains(client))
- clients_to_alert.append(client);
- }
-
- 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) {
@@ -647,13 +594,11 @@ AOPacket AOClient::validateIcPacket(AOPacket packet)
}
args.append(other_flip);
- // immediate text processing
- int immediate = incoming_args[18].toInt();
- if (area->force_immediate)
- immediate = 1;
- if (immediate != 1 && immediate != 0)
+ // noninterrupting preanim
+ int ni_pa = incoming_args[18].toInt();
+ if (ni_pa != 1 && ni_pa != 0)
return invalid;
- args.append(QString::number(immediate));
+ args.append(QString::number(ni_pa));
}
// 2.8 packet extensions
@@ -772,4 +717,6 @@ void AOClient::updateJudgeLog(AreaData* area, AOClient* client, QString action)
area->judgelog.append(logmessage);
}
else area->judgelog.append(logmessage);
+
+
}
diff --git a/src/server.cpp b/src/server.cpp
index 382e5a2..48d2787 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -53,7 +53,9 @@ void Server::start()
loadServerConfig();
loadCommandConfig();
-
+
+ maximum_statements = config.value("maximum_statements", 50).toInt();
+
proxy = new WSProxy(port, ws_port, this);
if(ws_port != -1)
proxy->start();
@@ -230,17 +232,9 @@ void Server::loadServerConfig()
auth_type = config.value("auth","simple").toString();
modpass = config.value("modpass","").toString();
bool zalgo_tolerance_conversion_success;
- zalgo_tolerance = config.value("zalgo_tolerance", "3").toInt(&zalgo_tolerance_conversion_success);
- if (!zalgo_tolerance_conversion_success)
- zalgo_tolerance = 3;
- bool maximum_statements_conversion_success;
- maximum_statements = config.value("maximum_statements", "10").toInt(&maximum_statements_conversion_success);
- if (!maximum_statements_conversion_success)
- maximum_statements = 10;
- bool afk_timeout_conversion_success;
- afk_timeout = config.value("afk_timeout", "300").toInt(&afk_timeout_conversion_success);
- if (!afk_timeout_conversion_success)
- afk_timeout = 300;
+ zalgo_tolerance = config.value("zalgo_tolerance", "3").toInt(&zalgo_tolerance_conversion_success);
+ if (!zalgo_tolerance_conversion_success)
+ zalgo_tolerance = 3;
config.endGroup();
//Load dice values
diff --git a/src/testimony_recorder.cpp b/src/testimony_recorder.cpp
index 01178b5..3c6897d 100644
--- a/src/testimony_recorder.cpp
+++ b/src/testimony_recorder.cpp
@@ -39,7 +39,6 @@ void AOClient::addStatement(QStringList packet)
}
}
else if (area->test_rec == AreaData::TestimonyRecording::ADD) {
- packet[14] = "1";
area->testimony.insert(c_statement,packet);
area->test_rec = AreaData::TestimonyRecording::PLAYBACK;
}
From 577e2b50957afb1caeac09c1b3ca734d39f1ed61 Mon Sep 17 00:00:00 2001
From: MangosArentLiterature
<58055358+MangosArentLiterature@users.noreply.github.com>
Date: Thu, 15 Apr 2021 18:01:51 -0500
Subject: [PATCH 4/5] Revert "Revert "Merge branch 'master' into
command-split""
This reverts commit 58f2d1e2b7f811db8cc7433f6e07c01b4ef7dc86.
---
bin/config_sample/areas.ini | 4 +-
include/aoclient.h | 75 +-
include/area_data.h | 5 +
include/server.h | 5 +
src/aoclient.cpp | 17 +-
src/area_data.cpp | 1 +
src/commands.cpp | 1706 +++++++++++++++++++++++++++++++++++
src/packets.cpp | 65 +-
src/server.cpp | 18 +-
src/testimony_recorder.cpp | 1 +
10 files changed, 1880 insertions(+), 17 deletions(-)
diff --git a/bin/config_sample/areas.ini b/bin/config_sample/areas.ini
index 7dc04e7..066fcc8 100644
--- a/bin/config_sample/areas.ini
+++ b/bin/config_sample/areas.ini
@@ -4,10 +4,12 @@ protected_area=true
iniswap_allowed=false
evidence_mod=cm
blankposting_allowed=true
+force_immediate=true
[1:Courtroom 1]
background=gs4
protected_area=false
iniswap_allowed=true
evidence_mod=ffa
-blankposting_allowed=true
\ No newline at end of file
+blankposting_allowed=true
+force_immediate=false
diff --git a/include/aoclient.h b/include/aoclient.h
index 5035b6b..1bc4f0e 100644
--- a/include/aoclient.h
+++ b/include/aoclient.h
@@ -53,7 +53,11 @@ class AOClient : public QObject {
AOClient(Server* p_server, QTcpSocket* p_socket, QObject* parent = nullptr, int user_id = 0)
: QObject(parent), id(user_id), remote_ip(p_socket->peerAddress()), password(""),
joined(false), current_area(0), current_char(""), socket(p_socket), server(p_server),
- is_partial(false), last_wtce_time(0) {};
+ is_partial(false), last_wtce_time(0) {
+ afk_timer = new QTimer;
+ afk_timer->setSingleShot(true);
+ connect(afk_timer, SIGNAL(timeout()), this, SLOT(onAfkTimeout()));
+ };
/**
* @brief Destructor for the AOClient instance.
@@ -218,6 +222,12 @@ class AOClient : public QObject {
{"SUPER", ~0ULL },
};
+
+ /**
+ * @brief A list of 5 casing preferences (def, pro, judge, jury, steno)
+ */
+ QList casing_preferences = {false, false, false, false, false};
+
/**
* @brief If true, the client's in-character messages will have their word order randomised.
*/
@@ -233,6 +243,18 @@ class AOClient : public QObject {
*/
bool is_gimped = false;
+ /**
+ * @brief If true, the client will be marked as AFK in /getarea. Automatically applied when a configurable
+ * amount of time has passed since the last interaction, or manually applied by /afk.
+ */
+ bool is_afk = false;
+
+ /**
+ * @brief Timer for tracking user interaction. Automatically restarted whenever a user interacts (i.e. sends any packet besides CH)
+ */
+ QTimer* afk_timer;
+
+
public slots:
/**
* @brief A slot for when the client disconnects from the server.
@@ -261,6 +283,11 @@ class AOClient : public QObject {
*/
void sendPacket(QString header);
+ /**
+ * @brief A slot for when the client's AFK timer runs out.
+ */
+ void onAfkTimeout();
+
private:
/**
* @brief The TCP socket used to communicate with the client.
@@ -472,6 +499,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 +655,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 }},
};
/**
@@ -1067,7 +1102,7 @@ class AOClient : public QObject {
*
* @iscommand
*/
- void cmdAllow_Blankposting(int argc, QStringList argv);
+ void cmdAllowBlankposting(int argc, QStringList argv);
/**
* @brief Looks up info on a ban.
@@ -1535,6 +1570,33 @@ class AOClient : public QObject {
void cmdCurrentMusic(int argc, QStringList argv);
+ /**
+ * @brief Toggles immediate text processing in the current area.
+ *
+ * @details No arguments.
+ *
+ * @iscommand
+ */
+ void cmdForceImmediate(int argc, QStringList argv);
+
+ /**
+ * @brief Toggles whether iniswaps are allowed in the current area.
+ *
+ * @details No arguments.
+ *
+ * @iscommand
+ */
+ void cmdAllowIniswap(int argc, QStringList argv);
+
+ /**
+ * @brief Toggles whether this client is considered AFK.
+ *
+ * @details No arguments.
+ *
+ * @iscommand
+ */
+ void cmdAfk(int argc, QStringList argv);
+
///@}
/**
@@ -1767,7 +1829,8 @@ class AOClient : public QObject {
{"8ball", {ACLFlags.value("NONE"), 1, &AOClient::cmd8Ball}},
{"lm", {ACLFlags.value("MODCHAT"), 1, &AOClient::cmdLM}},
{"judgelog", {ACLFlags.value("CM"), 0, &AOClient::cmdJudgeLog}},
- {"allow_blankposting", {ACLFlags.value("MODCHAT"), 0, &AOClient::cmdAllow_Blankposting}},
+ {"allowblankposting", {ACLFlags.value("MODCHAT"), 0, &AOClient::cmdAllowBlankposting}},
+ {"allow_blankposting", {ACLFlags.value("MODCHAT"), 0, &AOClient::cmdAllowBlankposting}},
{"gimp", {ACLFlags.value("MUTE"), 1, &AOClient::cmdGimp}},
{"ungimp", {ACLFlags.value("MUTE"), 1, &AOClient::cmdUnGimp}},
{"baninfo", {ACLFlags.value("BAN"), 1, &AOClient::cmdBanInfo}},
@@ -1776,11 +1839,17 @@ class AOClient : public QObject {
{"pause", {ACLFlags.value("CM"), 0, &AOClient::cmdPauseTestimony}},
{"delete", {ACLFlags.value("CM"), 0, &AOClient::cmdDeleteStatement}},
{"update", {ACLFlags.value("CM"), 0, &AOClient::cmdUpdateStatement}},
+ {"add", {ACLFlags.value("CM"), 0, &AOClient::cmdAddStatement}},
{"reload", {ACLFlags.value("SUPER"), 0, &AOClient::cmdReload}},
{"disemvowel", {ACLFlags.value("MUTE"), 1, &AOClient::cmdDisemvowel}},
{"undisemvowel", {ACLFlags.value("MUTE"), 1, &AOClient::cmdUnDisemvowel}},
{"shake", {ACLFlags.value("MUTE"), 1, &AOClient::cmdShake}},
{"unshake", {ACLFlags.value("MUTE"), 1, &AOClient::cmdUnShake}},
+ {"forceimmediate", {ACLFlags.value("CM"), 0, &AOClient::cmdForceImmediate}},
+ {"force_noint_pres", {ACLFlags.value("CM"), 0, &AOClient::cmdForceImmediate}},
+ {"allowiniswap", {ACLFlags.value("CM"), 0, &AOClient::cmdAllowIniswap}},
+ {"allow_iniswap", {ACLFlags.value("CM"), 0, &AOClient::cmdAllowIniswap}},
+ {"afk", {ACLFlags.value("NONE"), 0, &AOClient::cmdAfk}},
};
/**
diff --git a/include/area_data.h b/include/area_data.h
index 5cab8ef..23df38f 100644
--- a/include/area_data.h
+++ b/include/area_data.h
@@ -344,6 +344,11 @@ class AreaData : public QObject {
* @brief The value of logger in config.ini.
*/
QString log_type;
+
+ /**
+ * @brief Whether or not to force immediate text processing in this area
+ */
+ bool force_immediate;
};
#endif // AREA_DATA_H
diff --git a/include/server.h b/include/server.h
index 91fb5ef..0017621 100644
--- a/include/server.h
+++ b/include/server.h
@@ -232,6 +232,11 @@ class Server : public QObject {
*/
int max_dice;
+ /**
+ * @brief The amount of time in seconds to wait before marking a user AFK.
+ */
+ int afk_timeout;
+
/**
* @brief The server-wide global timer.
*/
diff --git a/src/aoclient.cpp b/src/aoclient.cpp
index 762d99f..6e8dfbd 100644
--- a/src/aoclient.cpp
+++ b/src/aoclient.cpp
@@ -77,6 +77,13 @@ void AOClient::handlePacket(AOPacket packet)
return;
}
+ if (packet.header != "CH") {
+ if (is_afk)
+ sendServerMessage("You are no longer AFK.");
+ is_afk = false;
+ afk_timer->start(server->afk_timeout * 1000);
+ }
+
if (packet.contents.length() < info.minArgs) {
#ifdef NET_DEBUG
qDebug() << "Invalid packet args length. Minimum is" << info.minArgs << "but only" << packet.contents.length() << "were given.";
@@ -311,9 +318,17 @@ bool AOClient::checkAuth(unsigned long long acl_mask)
return true;
}
+
QString AOClient::getIpid() { return ipid; }
-Server* AOClient::getServer() { return server; };
+Server* AOClient::getServer() { return server; }
+
+void AOClient::onAfkTimeout()
+{
+ if (!is_afk)
+ sendServerMessage("You are now AFK.");
+ is_afk = true;
+}
AOClient::~AOClient() {
socket->deleteLater();
diff --git a/src/area_data.cpp b/src/area_data.cpp
index c40271c..0653597 100644
--- a/src/area_data.cpp
+++ b/src/area_data.cpp
@@ -39,6 +39,7 @@ AreaData::AreaData(QString p_name, int p_index) :
bg_locked = areas_ini.value("bg_locked", "false").toBool();
QString configured_evi_mod = areas_ini.value("evidence_mod", "FFA").toString().toLower();
blankposting_allowed = areas_ini.value("blankposting_allowed","true").toBool();
+ force_immediate = areas_ini.value("force_immediate", "false").toBool();
areas_ini.endGroup();
QSettings config_ini("config/config.ini", QSettings::IniFormat);
config_ini.beginGroup("Options");
diff --git a/src/commands.cpp b/src/commands.cpp
index 9824cfa..135c06a 100644
--- a/src/commands.cpp
+++ b/src/commands.cpp
@@ -18,3 +18,1709 @@
#include "include/aoclient.h"
// Be sure to register the command in the header before adding it here!
+
+void AOClient::cmdDefault(int argc, QStringList argv)
+{
+ sendServerMessage("Invalid command.");
+ return;
+}
+
+void AOClient::cmdLogin(int argc, QStringList argv)
+{
+ if (authenticated) {
+ sendServerMessage("You are already logged in!");
+ return;
+ }
+
+ if (server->auth_type == "simple") {
+ if (server->modpass == "") {
+ sendServerMessage("No modpass is set! Please set a modpass before authenticating.");
+ }
+ else if(argv[0] == server->modpass) {
+ sendPacket("AUTH", {"1"}); // Client: "You were granted the Disable Modcalls button."
+ sendServerMessage("Logged in as a moderator."); // pre-2.9.1 clients are hardcoded to display the mod UI when this string is sent in OOC
+ authenticated = true;
+ }
+ else {
+ sendPacket("AUTH", {"0"}); // Client: "Login unsuccessful."
+ sendServerMessage("Incorrect password.");
+ }
+ server->areas.value(current_area)->logger->logLogin(this, authenticated, "moderator");
+ }
+ else if (server->auth_type == "advanced") {
+ if (argc < 2) {
+ sendServerMessage("You must specify a username and a password");
+ return;
+ }
+ QString username = argv[0];
+ QString password = argv[1];
+ if (server->db_manager->authenticate(username, password)) {
+ moderator_name = username;
+ authenticated = true;
+ sendPacket("AUTH", {"1"}); // Client: "You were granted the Disable Modcalls button."
+ if (version.release <= 2 && version.major <= 9 && version.minor <= 0)
+ sendServerMessage("Logged in as a moderator."); // pre-2.9.1 clients are hardcoded to display the mod UI when this string is sent in OOC
+ sendServerMessage("Welcome, " + username);
+ }
+ else {
+ sendPacket("AUTH", {"0"}); // Client: "Login unsuccessful."
+ sendServerMessage("Incorrect password.");
+ }
+ server->areas.value(current_area)->logger->logLogin(this, authenticated, username);
+ }
+ else {
+ qWarning() << "config.ini has an unrecognized auth_type!";
+ sendServerMessage("Config.ini contains an invalid auth_type, please check your config.");
+ }
+}
+
+void AOClient::cmdGetAreas(int argc, QStringList argv)
+{
+ QStringList entries;
+ entries.append("== Area List ==");
+ for (int i = 0; i < server->area_names.length(); i++) {
+ QStringList cur_area_lines = buildAreaList(i);
+ entries.append(cur_area_lines);
+ }
+ sendServerMessage(entries.join("\n"));
+}
+
+void AOClient::cmdGetArea(int argc, QStringList argv)
+{
+ QStringList entries = buildAreaList(current_area);
+ sendServerMessage(entries.join("\n"));
+}
+
+void AOClient::cmdBan(int argc, QStringList argv)
+{
+ QString args_str = argv[1];
+ if (argc > 2) {
+ for (int i = 2; i < argc; i++)
+ args_str += " " + argv[i];
+ }
+
+ DBManager::BanInfo ban;
+
+ QRegularExpression quoteMatcher("['\"](.+?)[\"']");
+ QRegularExpressionMatchIterator matches = quoteMatcher.globalMatch(args_str);
+ QList unquoted_args;
+ while (matches.hasNext()) {
+ QRegularExpressionMatch match = matches.next();
+ unquoted_args.append(match.captured(1));
+ }
+
+ QString duration = "perma";
+
+ if (unquoted_args.length() < 1) {
+ sendServerMessage("Invalid syntax. Usage:\n/ban \"\" \"\"");
+ return;
+ }
+
+ ban.reason = unquoted_args.at(0);
+ if (unquoted_args.length() > 1)
+ duration = unquoted_args.at(1);
+
+ long long duration_seconds = 0;
+ if (duration == "perma")
+ duration_seconds = -2;
+ else
+ duration_seconds = parseTime(duration);
+
+ if (duration_seconds == -1) {
+ sendServerMessage("Invalid time format. Format example: 1h30m");
+ return;
+ }
+
+ ban.duration = duration_seconds;
+
+ ban.ipid = argv[0];
+ ban.time = QDateTime::currentDateTime().toSecsSinceEpoch();
+ bool ban_logged = false;
+ int kick_counter = 0;
+
+ if (argc > 2) {
+ for (int i = 2; i < argv.length(); i++) {
+ ban.reason += " " + argv[i];
+ }
+ }
+
+ for (AOClient* client : server->getClientsByIpid(ban.ipid)) {
+ if (!ban_logged) {
+ ban.ip = client->remote_ip;
+ ban.hdid = client->hwid;
+ server->db_manager->addBan(ban);
+ sendServerMessage("Banned user with ipid " + ban.ipid + " for reason: " + ban.reason);
+ ban_logged = true;
+ }
+ client->sendPacket("KB", {ban.reason + "\nID: " + QString::number(server->db_manager->getBanID(ban.ip)) + "\nUntil: " + QDateTime::fromSecsSinceEpoch(ban.time).addSecs(ban.duration).toString("dd.MM.yyyy, hh:mm")});
+ client->socket->close();
+ kick_counter++;
+ }
+
+ if (kick_counter > 1)
+ sendServerMessage("Kicked " + QString::number(kick_counter) + " clients with matching ipids.");
+ if (!ban_logged)
+ sendServerMessage("User with ipid not found!");
+}
+
+void AOClient::cmdKick(int argc, QStringList argv)
+{
+ QString target_ipid = argv[0];
+ QString reason = argv[1];
+ int kick_counter = 0;
+
+ if (argc > 2) {
+ for (int i = 2; i < argv.length(); i++) {
+ reason += " " + argv[i];
+ }
+ }
+
+ for (AOClient* client : server->getClientsByIpid(target_ipid)) {
+ client->sendPacket("KK", {reason});
+ client->socket->close();
+ kick_counter++;
+ }
+
+ if (kick_counter > 0)
+ sendServerMessage("Kicked " + QString::number(kick_counter) + " client(s) with ipid " + target_ipid + " for reason: " + reason);
+ else
+ sendServerMessage("User with ipid not found!");
+}
+
+void AOClient::cmdChangeAuth(int argc, QStringList argv)
+{
+ if (server->auth_type == "simple") {
+ change_auth_started = true;
+ sendServerMessage("WARNING!\nThis command will change how logging in as a moderator works.\nOnly proceed if you know what you are doing\nUse the command /rootpass to set the password for your root account.");
+ }
+}
+
+void AOClient::cmdSetRootPass(int argc, QStringList argv)
+{
+ if (!change_auth_started)
+ return;
+
+ sendServerMessage("Changing auth type and setting root password.\nLogin again with /login root [password]");
+ authenticated = false;
+ QSettings settings("config/config.ini", QSettings::IniFormat);
+ settings.beginGroup("Options");
+ settings.setValue("auth", "advanced");
+ server->auth_type = "advanced";
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
+ qsrand(QDateTime::currentMSecsSinceEpoch());
+ quint32 upper_salt = qrand();
+ quint32 lower_salt = qrand();
+ quint64 salt_number = (upper_salt << 32) | lower_salt;
+#else
+ quint64 salt_number = QRandomGenerator::system()->generate64();
+#endif
+ QString salt = QStringLiteral("%1").arg(salt_number, 16, 16, QLatin1Char('0'));
+
+ server->db_manager->createUser("root", salt, argv[0], ACLFlags.value("SUPER"));
+}
+
+void AOClient::cmdSetBackground(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ if (authenticated || !area->bg_locked) {
+ if (server->backgrounds.contains(argv[0])) {
+ area->background = argv[0];
+ server->broadcast(AOPacket("BN", {argv[0]}), current_area);
+ sendServerMessageArea(current_char + " changed the background to " + argv[0]);
+ }
+ else {
+ sendServerMessage("Invalid background name.");
+ }
+ }
+ else {
+ sendServerMessage("This area's background is locked.");
+ }
+}
+
+void AOClient::cmdBgLock(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ area->bg_locked = true;
+ server->broadcast(AOPacket("CT", {"Server", current_char + " locked the background.", "1"}), current_area);
+}
+
+void AOClient::cmdBgUnlock(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ area->bg_locked = false;
+ server->broadcast(AOPacket("CT", {"Server", current_char + " unlocked the background.", "1"}), current_area);
+}
+
+void AOClient::cmdAddUser(int argc, QStringList argv)
+{
+#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
+ qsrand(QDateTime::currentMSecsSinceEpoch());
+ quint32 upper_salt = qrand();
+ quint32 lower_salt = qrand();
+ quint64 salt_number = (upper_salt << 32) | lower_salt;
+#else
+ quint64 salt_number = QRandomGenerator::system()->generate64();
+#endif
+ QString salt = QStringLiteral("%1").arg(salt_number, 16, 16, QLatin1Char('0'));
+
+ if (server->db_manager->createUser(argv[0], salt, argv[1], ACLFlags.value("NONE")))
+ sendServerMessage("Created user " + argv[0] + ".\nUse /addperm to modify their permissions.");
+ else
+ sendServerMessage("Unable to create user " + argv[0] + ".\nDoes a user with that name already exist?");
+}
+
+void AOClient::cmdRemoveUser(int argc, QStringList argv)
+{
+ if (server->db_manager->deleteUser(argv[0]))
+ sendServerMessage("Successfully removed user " + argv[0] + ".");
+ else
+ sendServerMessage("Unable to remove user " + argv[0] + ".\nDoes it exist?");
+}
+
+void AOClient::cmdListPerms(int argc, QStringList argv)
+{
+ unsigned long long user_acl = server->db_manager->getACL(moderator_name);
+ QStringList message;
+ if (argc == 0) {
+ // Just print out all permissions available to the user.
+ message.append("You have been given the following permissions:");
+ for (QString perm : ACLFlags.keys()) {
+ if (perm == "NONE"); // don't need to list this one
+ else if (perm == "SUPER") {
+ if (user_acl == ACLFlags.value("SUPER")) // This has to be checked separately, because SUPER & anything will always be truthy
+ message.append("SUPER (Be careful! This grants the user all permissions.)");
+ }
+ else if ((ACLFlags.value(perm) & user_acl) == 0); // user doesn't have this permission, don't print it
+ else
+ message.append(perm);
+ }
+ }
+ else {
+ if ((user_acl & ACLFlags.value("MODIFY_USERS")) == 0) {
+ sendServerMessage("You do not have permission to view other users' permissions.");
+ return;
+ }
+
+ message.append("User " + argv[0] + " has the following permissions:");
+ unsigned long long acl = server->db_manager->getACL(argv[0]);
+ if (acl == 0) {
+ sendServerMessage("This user either doesn't exist, or has no permissions set.");
+ return;
+ }
+
+ for (QString perm : ACLFlags.keys()) {
+ if ((ACLFlags.value(perm) & acl) != 0 && perm != "SUPER") {
+ message.append(perm);
+ }
+ }
+ }
+ sendServerMessage(message.join("\n"));
+}
+
+void AOClient::cmdAddPerms(int argc, QStringList argv)
+{
+ unsigned long long user_acl = server->db_manager->getACL(moderator_name);
+ argv[1] = argv[1].toUpper();
+
+ if (!ACLFlags.keys().contains(argv[1])) {
+ sendServerMessage("That permission doesn't exist!");
+ return;
+ }
+
+ if (argv[1] == "SUPER") {
+ if (user_acl != ACLFlags.value("SUPER")) {
+ // This has to be checked separately, because SUPER & anything will always be truthy
+ sendServerMessage("You aren't allowed to add that permission!");
+ return;
+ }
+ }
+ if (argv[1] == "NONE") {
+ sendServerMessage("Added no permissions!");
+ return;
+ }
+
+ unsigned long long newperm = ACLFlags.value(argv[1]);
+ if ((newperm & user_acl) != 0) {
+ if (server->db_manager->updateACL(argv[0], newperm, true))
+ sendServerMessage("Successfully added permission " + argv[1] + " to user " + argv[0]);
+ else
+ sendServerMessage(argv[0] + " wasn't found!");
+ return;
+ }
+
+ sendServerMessage("You aren't allowed to add that permission!");
+}
+
+void AOClient::cmdRemovePerms(int argc, QStringList argv)
+{
+ unsigned long long user_acl = server->db_manager->getACL(moderator_name);
+ argv[1] = argv[1].toUpper();
+
+ if (!ACLFlags.keys().contains(argv[1])) {
+ sendServerMessage("That permission doesn't exist!");
+ return;
+ }
+
+ if (argv[0] == "root") {
+ sendServerMessage("You cannot change the permissions of the root account!");
+ return;
+ }
+
+ if (argv[1] == "SUPER") {
+ if (user_acl != ACLFlags.value("SUPER")) {
+ // This has to be checked separately, because SUPER & anything will always be truthy
+ sendServerMessage("You aren't allowed to remove that permission!");
+ return;
+ }
+ }
+ if (argv[1] == "NONE") {
+ sendServerMessage("Removed no permissions!");
+ return;
+ }
+
+ unsigned long long newperm = ACLFlags.value(argv[1]);
+ if ((newperm & user_acl) != 0) {
+ if (server->db_manager->updateACL(argv[0], newperm, false))
+ sendServerMessage("Successfully removed permission " + argv[1] + " from user " + argv[0]);
+ else
+ sendServerMessage(argv[0] + " wasn't found!");
+ return;
+ }
+
+ sendServerMessage("You aren't allowed to remove that permission!");
+}
+
+void AOClient::cmdListUsers(int argc, QStringList argv)
+{
+ QStringList users = server->db_manager->getUsers();
+ sendServerMessage("All users:\n" + users.join("\n"));
+}
+
+void AOClient::cmdLogout(int argc, QStringList argv)
+{
+ if (!authenticated) {
+ sendServerMessage("You are not logged in!");
+ return;
+ }
+ authenticated = false;
+ moderator_name = "";
+ sendPacket("AUTH", {"-1"}); // Client: "You were logged out."
+}
+
+void AOClient::cmdPos(int argc, QStringList argv)
+{
+ changePosition(argv[0]);
+ updateEvidenceList(server->areas[current_area]);
+}
+
+void AOClient::cmdForcePos(int argc, QStringList argv)
+{
+ bool ok;
+ QList targets;
+ AreaData* area = server->areas[current_area];
+ int target_id = argv[1].toInt(&ok);
+ int forced_clients = 0;
+ if (!ok && argv[1] != "*") {
+ sendServerMessage("That does not look like a valid ID.");
+ return;
+ }
+ else if (ok) {
+ AOClient* target_client = server->getClientByID(target_id);
+ if (target_client != nullptr)
+ targets.append(target_client);
+ else {
+ sendServerMessage("Target ID not found!");
+ return;
+ }
+ }
+
+ else if (argv[1] == "*") { // force all clients in the area
+ for (AOClient* client : server->clients) {
+ if (client->current_area == current_area)
+ targets.append(client);
+ }
+ }
+ for (AOClient* target : targets) {
+ target->sendServerMessage("Position forcibly changed by CM.");
+ target->changePosition(argv[0]);
+ forced_clients++;
+ }
+ sendServerMessage("Forced " + QString::number(forced_clients) + " into pos " + argv[0] + ".");
+}
+
+void AOClient::cmdG(int argc, QStringList argv)
+{
+ QString sender_name = ooc_name;
+ QString sender_area = server->area_names.value(current_area);
+ QString sender_message = argv.join(" ");
+ for (AOClient* client : server->clients) {
+ if (client->global_enabled)
+ client->sendPacket("CT", {"[G][" + sender_area + "]" + sender_name, sender_message});
+ }
+ return;
+}
+
+void AOClient::cmdNeed(int argc, QStringList argv)
+{
+ QString sender_area = server->area_names.value(current_area);
+ QString sender_message = argv.join(" ");
+ sendServerBroadcast({"=== Advert ===\n[" + sender_area + "] needs " + sender_message+ "."});
+}
+
+void AOClient::cmdFlip(int argc, QStringList argv)
+{
+ QString sender_name = ooc_name;
+ QStringList faces = {"heads","tails"};
+ QString face = faces[AOClient::genRand(0,1)];
+ sendServerMessage(sender_name + " flipped a coin and got " + face + ".");
+}
+
+void AOClient::cmdRoll(int argc, QStringList argv)
+{
+ diceThrower(argc, argv, RollType::ROLL);
+}
+
+void AOClient::cmdRollP(int argc, QStringList argv)
+{
+ diceThrower(argc, argv, RollType::ROLLP);
+}
+
+void AOClient::cmdDoc(int argc, QStringList argv)
+{
+ QString sender_name = ooc_name;
+ AreaData* area = server->areas[current_area];
+ if (argc == 0) {
+ sendServerMessage("Document: " + area->document);
+ }
+ else {
+ area->document = argv.join(" ");
+ sendServerMessageArea(sender_name + " changed the document.");
+ }
+}
+
+void AOClient::cmdClearDoc(int argc, QStringList argv)
+{
+ QString sender_name = ooc_name;
+ AreaData* area = server->areas[current_area];
+ area->document = "No document.";
+ sendServerMessageArea(sender_name + " cleared the document.");
+}
+
+void AOClient::cmdCM(int argc, QStringList argv)
+{
+ QString sender_name = ooc_name;
+ AreaData* area = server->areas[current_area];
+ if (area->is_protected) {
+ sendServerMessage("This area is protected, you may not become CM.");
+ return;
+ }
+ else if (area->owners.isEmpty()) { // no one owns this area, and it's not protected
+ area->owners.append(id);
+ area->invited.append(id);
+ sendServerMessageArea(sender_name + " is now CM in this area.");
+ arup(ARUPType::CM, true);
+ }
+ else if (!area->owners.contains(id)) { // there is already a CM, and it isn't us
+ sendServerMessage("You cannot become a CM in this area.");
+ }
+ else if (argc == 1) { // we are CM, and we want to make ID argv[0] also CM
+ bool ok;
+ AOClient* owner_candidate = server->getClientByID(argv[0].toInt(&ok));
+ if (!ok) {
+ sendServerMessage("That doesn't look like a valid ID.");
+ return;
+ }
+ if (owner_candidate == nullptr) {
+ sendServerMessage("Unable to find client with ID " + argv[0] + ".");
+ return;
+ }
+ area->owners.append(owner_candidate->id);
+ sendServerMessageArea(owner_candidate->ooc_name + " is now CM in this area.");
+ arup(ARUPType::CM, true);
+ }
+ else {
+ sendServerMessage("You are already a CM in this area.");
+ }
+}
+
+void AOClient::cmdUnCM(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ int removed = area->owners.removeAll(id);
+ area->invited.removeAll(id);
+ sendServerMessage("You are no longer CM in this area.");
+ arup(ARUPType::CM, true);
+ if (area->owners.isEmpty()) {
+ area->invited.clear();
+ if (area->locked != AreaData::FREE) {
+ area->locked = AreaData::FREE;
+ arup(ARUPType::LOCKED, true);
+ }
+ }
+}
+
+void AOClient::cmdInvite(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ bool ok;
+ int invited_id = argv[0].toInt(&ok);
+ if (!ok) {
+ sendServerMessage("That does not look like a valid ID.");
+ return;
+ }
+ else if (server->getClientByID(invited_id) == nullptr) {
+ sendServerMessage("No client with that ID found.");
+ return;
+ }
+ else if (area->invited.contains(invited_id)) {
+ sendServerMessage("That ID is already on the invite list.");
+ return;
+ }
+ area->invited.append(invited_id);
+ sendServerMessage("You invited ID " + argv[0]);
+}
+
+void AOClient::cmdUnInvite(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ bool ok;
+ int uninvited_id = argv[0].toInt(&ok);
+ if (!ok) {
+ sendServerMessage("That does not look like a valid ID.");
+ return;
+ }
+ else if (server->getClientByID(uninvited_id) == nullptr) {
+ sendServerMessage("No client with that ID found.");
+ return;
+ }
+ else if (area->owners.contains(uninvited_id)) {
+ sendServerMessage("You cannot uninvite a CM!");
+ return;
+ }
+ else if (!area->invited.contains(uninvited_id)) {
+ sendServerMessage("That ID is not on the invite list.");
+ return;
+ }
+ area->invited.removeAll(uninvited_id);
+ sendServerMessage("You uninvited ID " + argv[0]);
+}
+
+void AOClient::cmdLock(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ if (area->locked == AreaData::LockStatus::LOCKED) {
+ sendServerMessage("This area is already locked.");
+ return;
+ }
+ sendServerMessageArea("This area is now locked.");
+ area->locked = AreaData::LockStatus::LOCKED;
+ for (AOClient* client : server->clients) {
+ if (client->current_area == current_area && client->joined) {
+ area->invited.append(client->id);
+ }
+ }
+ arup(ARUPType::LOCKED, true);
+}
+
+void AOClient::cmdSpectatable(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ if (area->locked == AreaData::LockStatus::SPECTATABLE) {
+ sendServerMessage("This area is already in spectate mode.");
+ return;
+ }
+ sendServerMessageArea("This area is now spectatable.");
+ area->locked = AreaData::LockStatus::SPECTATABLE;
+ for (AOClient* client : server->clients) {
+ if (client->current_area == current_area && client->joined) {
+ area->invited.append(client->id);
+ }
+ }
+ arup(ARUPType::LOCKED, true);
+}
+
+void AOClient::cmdUnLock(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ if (area->locked == AreaData::LockStatus::FREE) {
+ sendServerMessage("This area is not locked.");
+ return;
+ }
+ sendServerMessageArea("This area is now unlocked.");
+ area->locked = AreaData::LockStatus::FREE;
+ arup(ARUPType::LOCKED, true);
+}
+
+void AOClient::cmdTimer(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+
+ // Called without arguments
+ // Shows a brief of all timers
+ if (argc == 0) {
+ QStringList timers;
+ timers.append("Currently active timers:");
+ for (int i = 0; i <= 4; i++) {
+ timers.append(getAreaTimer(area->index, i));
+ }
+ sendServerMessage(timers.join("\n"));
+ return;
+ }
+
+ // Called with more than one argument
+ bool ok;
+ int timer_id = argv[0].toInt(&ok);
+ if (!ok || timer_id < 0 || timer_id > 4) {
+ sendServerMessage("Invalid timer ID. Timer ID must be a whole number between 0 and 4.");
+ return;
+ }
+
+ // Called with one argument
+ // Shows the status of one timer
+ if (argc == 1) {
+ sendServerMessage(getAreaTimer(area->index, timer_id));
+ return;
+ }
+
+ // Called with more than one argument
+ // Updates the state of a timer
+
+ // Select the proper timer
+ // Check against permissions if global timer is selected
+ QTimer* requested_timer;
+ if (timer_id == 0) {
+ if (!checkAuth(ACLFlags.value("GLOBAL_TIMER"))) {
+ sendServerMessage("You are not authorized to alter the global timer.");
+ return;
+ }
+ requested_timer = server->timer;
+ }
+ else
+ requested_timer = area->timers[timer_id - 1];
+
+ AOPacket show_timer("TI", {QString::number(timer_id), "2"});
+ AOPacket hide_timer("TI", {QString::number(timer_id), "3"});
+ bool is_global = timer_id == 0;
+
+ // Set the timer's time remaining if the second
+ // argument is a valid time
+ QTime requested_time = QTime::fromString(argv[1], "hh:mm:ss");
+ if (requested_time.isValid()) {
+ requested_timer->setInterval(QTime(0,0).msecsTo(requested_time));
+ requested_timer->start();
+ sendServerMessage("Set timer " + QString::number(timer_id) + " to " + argv[1] + ".");
+ AOPacket update_timer("TI", {QString::number(timer_id), "0", QString::number(QTime(0,0).msecsTo(requested_time))});
+ is_global ? server->broadcast(show_timer) : server->broadcast(show_timer, current_area); // Show the timer
+ is_global ? server->broadcast(update_timer) : server->broadcast(update_timer, current_area);
+ return;
+ }
+ // Otherwise, update the state of the timer
+ else {
+ if (argv[1] == "start") {
+ requested_timer->start();
+ sendServerMessage("Started timer " + QString::number(timer_id) + ".");
+ AOPacket update_timer("TI", {QString::number(timer_id), "0", QString::number(QTime(0,0).msecsTo(QTime(0,0).addMSecs(requested_timer->remainingTime())))});
+ is_global ? server->broadcast(show_timer) : server->broadcast(show_timer, current_area);
+ is_global ? server->broadcast(update_timer) : server->broadcast(update_timer, current_area);
+ }
+ else if (argv[1] == "pause" || argv[1] == "stop") {
+ requested_timer->setInterval(requested_timer->remainingTime());
+ requested_timer->stop();
+ sendServerMessage("Stopped timer " + QString::number(timer_id) + ".");
+ AOPacket update_timer("TI", {QString::number(timer_id), "1", QString::number(QTime(0,0).msecsTo(QTime(0,0).addMSecs(requested_timer->interval())))});
+ is_global ? server->broadcast(update_timer) : server->broadcast(update_timer, current_area);
+ }
+ else if (argv[1] == "hide" || argv[1] == "unset") {
+ requested_timer->setInterval(0);
+ requested_timer->stop();
+ sendServerMessage("Hid timer " + QString::number(timer_id) + ".");
+ // Hide the timer
+ is_global ? server->broadcast(hide_timer) : server->broadcast(hide_timer, current_area);
+ }
+ }
+}
+
+void AOClient::cmdEvidenceMod(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ argv[0] = argv[0].toLower();
+ if (argv[0] == "cm")
+ area->evi_mod = AreaData::EvidenceMod::CM;
+ else if (argv[0] == "mod")
+ area->evi_mod = AreaData::EvidenceMod::MOD;
+ else if (argv[0] == "hiddencm")
+ area->evi_mod = AreaData::EvidenceMod::HIDDEN_CM;
+ else if (argv[0] == "ffa")
+ area->evi_mod = AreaData::EvidenceMod::FFA;
+ else {
+ sendServerMessage("Invalid evidence mod.");
+ return;
+ }
+ sendServerMessage("Changed evidence mod.");
+
+ // Resend evidence lists to everyone in the area
+ sendEvidenceList(area);
+}
+
+void AOClient::cmdArea(int argc, QStringList argv)
+{
+ bool ok;
+ int new_area = argv[0].toInt(&ok);
+ if (!ok || new_area >= server->areas.size() || new_area < 0) {
+ sendServerMessage("That does not look like a valid area ID.");
+ return;
+ }
+ changeArea(new_area);
+}
+
+void AOClient::cmdPlay(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ QString song = argv.join(" ");
+ area->current_music = song;
+ area->music_played_by = showname;
+ AOPacket music_change("MC", {song, QString::number(server->getCharID(current_char)), showname, "1", "0"});
+ server->broadcast(music_change, current_area);
+}
+
+void AOClient::cmdAreaKick(int argc, QStringList argv)
+{
+ bool ok;
+ int idx = argv[0].toInt(&ok);
+ if (!ok) {
+ sendServerMessage("That does not look like a valid ID.");
+ return;
+ }
+ AOClient* client_to_kick = server->getClientByID(idx);
+ if (client_to_kick == nullptr) {
+ sendServerMessage("No client with that ID found.");
+ return;
+ }
+ client_to_kick->changeArea(0);
+ sendServerMessage("Client " + argv[0] + " kicked back to area 0.");
+}
+
+void AOClient::cmdSwitch(int argc, QStringList argv)
+{
+ int char_id = server->getCharID(argv.join(" "));
+ if (char_id == -1) {
+ sendServerMessage("That does not look like a valid character.");
+ return;
+ }
+ changeCharacter(char_id);
+}
+
+void AOClient::cmdRandomChar(int argc, QStringList argv)
+{
+ int char_id = genRand(0, server->characters.size() - 1);
+ changeCharacter(char_id);
+}
+
+void AOClient::cmdToggleGlobal(int argc, QStringList argv)
+{
+ global_enabled = !global_enabled;
+ QString str_en = global_enabled ? "shown" : "hidden";
+ sendServerMessage("Global chat set to " + str_en);
+}
+
+void AOClient::cmdMods(int argc, QStringList argv)
+{
+ QStringList entries;
+ int online_count = 0;
+ for (AOClient* client : server->clients) {
+ if (client->authenticated) {
+ entries << "---";
+ if (server->auth_type != "simple")
+ entries << "Moderator: " + client->moderator_name;
+ entries << "OOC name: " + client->ooc_name;
+ entries << "ID: " + QString::number(client->id);
+ entries << "Area: " + QString::number(client->current_area);
+ entries << "Character: " + client->current_char;
+ online_count++;
+ }
+ }
+ entries << "---";
+ entries << "Total online: " << QString::number(online_count);
+ sendServerMessage(entries.join("\n"));
+}
+
+void AOClient::cmdHelp(int argc, QStringList argv)
+{
+ QStringList entries;
+ entries << "Allowed commands:";
+ QMap::const_iterator i;
+ for (i = commands.constBegin(); i!= commands.constEnd(); ++i) {
+ CommandInfo info = i.value();
+ if (checkAuth(info.acl_mask)) { // if we are allowed to use this command
+ entries << "/" + i.key();
+ }
+ }
+ sendServerMessage(entries.join("\n"));
+}
+
+void AOClient::cmdStatus(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ QString arg = argv[0].toLower();
+ if (arg == "idle")
+ area->status = AreaData::IDLE;
+ else if (arg == "rp")
+ area->status = AreaData::RP;
+ else if (arg == "casing")
+ area->status = AreaData::CASING;
+ else if (arg == "looking-for-players" || arg == "lfp")
+ area->status = AreaData::LOOKING_FOR_PLAYERS;
+ else if (arg == "recess")
+ area->status = AreaData::RECESS;
+ else if (arg == "gaming")
+ area->status = AreaData::GAMING;
+ else {
+ sendServerMessage("That does not look like a valid status. Valid statuses are idle, rp, casing, lfp, recess, gaming");
+ return;
+ }
+ arup(ARUPType::STATUS, true);
+}
+
+void AOClient::cmdCurrentMusic(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ if (area->current_music != "" && area->current_music != "~stop.mp3") // dummy track for stopping music
+ sendServerMessage("The current song is " + area->current_music + " played by " + area->music_played_by);
+ else
+ sendServerMessage("There is no music playing.");
+}
+
+void AOClient::cmdPM(int arc, QStringList argv)
+{
+ bool ok;
+ int target_id = argv.takeFirst().toInt(&ok); // using takeFirst removes the ID from our list of arguments...
+ if (!ok) {
+ sendServerMessage("That does not look like a valid ID.");
+ return;
+ }
+ AOClient* target_client = server->getClientByID(target_id);
+ if (target_client == nullptr) {
+ sendServerMessage("No client with that ID found.");
+ return;
+ }
+ QString message = argv.join(" "); //...which means it will not end up as part of the message
+ target_client->sendServerMessage("Message from " + ooc_name + " (" + QString::number(id) + "): " + message);
+}
+
+void AOClient::cmdMOTD(int argc, QStringList argv)
+{
+ if (argc == 0) {
+ sendServerMessage("=== MOTD ===\r\n" + server->MOTD + "\r\n=============");
+ }
+ else if (argc > 0) {
+ if (checkAuth(ACLFlags.value("MOTD"))) {
+ QString MOTD = argv.join(" ");
+ server->MOTD = MOTD;
+ sendServerMessage("MOTD has been changed.");
+ }
+ else {
+ sendServerMessage("You do not have permission to change the MOTD");
+ }
+ }
+}
+
+void AOClient::cmdAnnounce(int argc, QStringList argv)
+{
+ sendServerBroadcast("=== Announcement ===\r\n" + argv.join(" ") + "\r\n=============");
+}
+
+void AOClient::cmdM(int argc, QStringList argv)
+{
+ QString sender_name = ooc_name;
+ QString sender_message = argv.join(" ");
+ for (AOClient* client : server->clients) {
+ if (client->checkAuth(ACLFlags.value("MODCHAT")))
+ client->sendPacket("CT", {"[M]" + sender_name, sender_message});
+ }
+ return;
+}
+
+void AOClient::cmdGM(int argc, QStringList argv)
+{
+ QString sender_name = ooc_name;
+ QString sender_area = server->area_names.value(current_area);
+ QString sender_message = argv.join(" ");
+ for (AOClient* client : server->clients) {
+ if (client->global_enabled) {
+ client->sendPacket("CT", {"[G][" + sender_area + "]" + "["+sender_name+"][M]", sender_message});
+ }
+ }
+}
+
+void AOClient::cmdLM(int argc, QStringList argv)
+{
+ QString sender_name = ooc_name;
+ QString sender_message = argv.join(" ");
+ server->broadcast(AOPacket("CT", {"["+sender_name+"][M]", sender_message}), current_area);
+}
+
+void AOClient::cmdBans(int argc, QStringList argv)
+{
+ QStringList recent_bans;
+ recent_bans << "Last 5 bans:";
+ recent_bans << "-----";
+ for (DBManager::BanInfo ban : server->db_manager->getRecentBans()) {
+ QString banned_until;
+ if (ban.duration == -2)
+ banned_until = "The heat death of the universe";
+ else
+ banned_until = QDateTime::fromSecsSinceEpoch(ban.time).addSecs(ban.duration).toString("dd.MM.yyyy, hh:mm");
+ recent_bans << "Affected IPID: " + ban.ipid;
+ recent_bans << "Affected HDID: " + ban.hdid;
+ recent_bans << "Reason for ban: " + ban.reason;
+ recent_bans << "Date of ban: " + QDateTime::fromSecsSinceEpoch(ban.time).toString("dd.MM.yyyy, hh:mm");
+ recent_bans << "Ban lasts until: " + banned_until;
+ recent_bans << "-----";
+ }
+ sendServerMessage(recent_bans.join("\n"));
+}
+
+void AOClient::cmdUnBan(int argc, QStringList argv)
+{
+ bool ok;
+ int target_ban = argv[0].toInt(&ok);
+ if (!ok) {
+ sendServerMessage("Invalid ban ID.");
+ return;
+ }
+ else if (server->db_manager->invalidateBan(target_ban))
+ sendServerMessage("Successfully invalidated ban " + argv[0] + ".");
+ else
+ sendServerMessage("Couldn't invalidate ban " + argv[0] + ", are you sure it exists?");
+}
+
+void AOClient::cmdSubTheme(int argc, QStringList argv)
+{
+ QString subtheme = argv.join(" ");
+ for (AOClient* client : server->clients) {
+ if (client->current_area == current_area)
+ client->sendPacket("ST", {subtheme, "1"});
+ }
+ sendServerMessageArea("Subtheme was set to " + subtheme);
+}
+
+void AOClient::cmdAbout(int argc, QStringList argv)
+{
+ sendPacket("CT", {"The akashi dev team", "Thank you for using akashi! Made with love by scatterflower, with help from in1tiate and Salanto. akashi " + QCoreApplication::applicationVersion()});
+}
+
+void AOClient::cmdEvidence_Swap(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ int ev_size = area->evidence.size() -1;
+
+ if (ev_size < 0) {
+ sendServerMessage("No evidence in area.");
+ return;
+ }
+
+ bool ok, ok2;
+ int ev_id1 = argv[0].toInt(&ok), ev_id2 = argv[1].toInt(&ok2);
+
+ if ((!ok || !ok2)) {
+ sendServerMessage("Invalid evidence ID.");
+ return;
+ }
+ if ((ev_id1 < 0) || (ev_id2 < 0)) {
+ sendServerMessage("Evidence ID can't be negative.");
+ return;
+ }
+ if ((ev_id2 <= ev_size) && (ev_id1 <= ev_size)) {
+#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
+ //swapItemsAt does not exist in Qt older than 5.13
+ area->evidence.swap(ev_id1, ev_id2);
+#else
+ area->evidence.swapItemsAt(ev_id1, ev_id2);
+#endif
+ sendEvidenceList(area);
+ sendServerMessage("The evidence " + QString::number(ev_id1) + " and " + QString::number(ev_id2) + " have been swapped.");
+ }
+ else {
+ sendServerMessage("Unable to swap evidence. Evidence ID out of range.");
+ }
+}
+
+void AOClient::cmdMute(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (target->is_muted)
+ sendServerMessage("That player is already muted!");
+ else {
+ sendServerMessage("Muted player.");
+ target->sendServerMessage("You were muted by a moderator. " + getReprimand());
+ }
+ target->is_muted = true;
+}
+
+void AOClient::cmdUnMute(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (!target->is_muted)
+ sendServerMessage("That player is not muted!");
+ else {
+ sendServerMessage("Unmuted player.");
+ target->sendServerMessage("You were unmuted by a moderator. " + getReprimand(true));
+ }
+ target->is_muted = false;
+}
+
+void AOClient::cmdOocMute(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (target->is_ooc_muted)
+ sendServerMessage("That player is already OOC muted!");
+ else {
+ sendServerMessage("OOC muted player.");
+ target->sendServerMessage("You were OOC muted by a moderator. " + getReprimand());
+ }
+ target->is_ooc_muted = true;
+}
+
+void AOClient::cmdOocUnMute(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (!target->is_ooc_muted)
+ sendServerMessage("That player is not OOC muted!");
+ else {
+ sendServerMessage("OOC unmuted player.");
+ target->sendServerMessage("You were OOC unmuted by a moderator. " + getReprimand(true));
+ }
+ target->is_ooc_muted = false;
+}
+
+void AOClient::cmdBlockDj(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (target->is_dj_blocked)
+ sendServerMessage("That player is already DJ blocked!");
+ else {
+ sendServerMessage("DJ blocked player.");
+ target->sendServerMessage("You were blocked from changing the music by a moderator. " + getReprimand());
+ }
+ target->is_dj_blocked = true;
+}
+
+void AOClient::cmdUnBlockDj(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (!target->is_dj_blocked)
+ sendServerMessage("That player is not DJ blocked!");
+ else {
+ sendServerMessage("DJ permissions restored to player.");
+ target->sendServerMessage("A moderator restored your music permissions. " + getReprimand(true));
+ }
+ target->is_dj_blocked = false;
+}
+
+void AOClient::cmdBlockWtce(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (target->is_wtce_blocked)
+ sendServerMessage("That player is already judge blocked!");
+ else {
+ sendServerMessage("Revoked player's access to judge controls.");
+ target->sendServerMessage("A moderator revoked your judge controls access. " + getReprimand());
+ }
+ target->is_wtce_blocked = true;
+}
+
+void AOClient::cmdUnBlockWtce(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (!target->is_wtce_blocked)
+ sendServerMessage("That player is not judge blocked!");
+ else {
+ sendServerMessage("Restored player's access to judge controls.");
+ target->sendServerMessage("A moderator restored your judge controls access. " + getReprimand(true));
+ }
+ target->is_wtce_blocked = false;
+}
+
+void AOClient::cmdNoteCard(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ if (area->notecards.keys().contains(current_char))
+ area->notecards.remove(current_char);
+ QString notecard = argv.join(" ");
+ area->notecards[current_char] = notecard;
+ sendServerMessageArea(current_char + " wrote a note card.");
+}
+
+void AOClient::cmdNoteCardClear(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ if (area->notecards.keys().contains(current_char)) {
+ area->notecards.remove(current_char);
+ sendServerMessageArea(current_char + " erased their note card.");
+ }
+ else
+ sendServerMessage("You do not have a note card.");
+}
+
+void AOClient::cmdNoteCardReveal(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ if (area->notecards.isEmpty()) {
+ sendServerMessage("There are no cards to reveal in this area.");
+ return;
+ }
+ QStringList message;
+ message << "Note cards have been revealed.";
+ QMap::iterator i;
+ for (i = area->notecards.begin(); i != area->notecards.end(); ++i)
+ message << i.key() + ": " + i.value();
+ sendServerMessageArea(message.join("\n"));
+ area->notecards.clear();
+}
+
+void AOClient::cmd8Ball(int argc, QStringList argv)
+{
+ if (server->magic_8ball_answers.isEmpty()) {
+ qWarning() << "8ball.txt is empty!";
+ sendServerMessage("8ball.txt is empty.");
+ }
+ else {
+ QString response = server->magic_8ball_answers[(genRand(1, server->magic_8ball_answers.size() - 1))];
+ QString sender_name = ooc_name;
+ QString sender_message = argv.join(" ");
+
+ sendServerMessageArea(sender_name + " asked the magic 8-ball, \"" + sender_message + "\" and the answer is: " + response);
+ }
+}
+
+void AOClient::cmdJudgeLog(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ if (area->judgelog.isEmpty()) {
+ sendServerMessage("There have been no judge actions in this area.");
+ return;
+ }
+ QString message = area->judgelog.join("\n");
+ //Judgelog contains an IPID, so we shouldn't send that unless the caller has appropriate permissions
+ if (checkAuth(ACLFlags.value("KICK")) == 1 || checkAuth(ACLFlags.value("BAN")) == 1) {
+ sendServerMessage(message);
+ }
+ else {
+ QString filteredmessage = message.remove(QRegularExpression("[(].*[)]")); //Filter out anything between two parentheses. This should only ever be the IPID
+ sendServerMessage(filteredmessage);
+ }
+}
+
+void AOClient::cmdAllowBlankposting(int argc, QStringList argv)
+{
+ QString sender_name = ooc_name;
+ AreaData* area = server->areas[current_area];
+ area->blankposting_allowed = !area->blankposting_allowed;
+ if (area->blankposting_allowed == false) {
+ sendServerMessageArea(sender_name + " has set blankposting in the area to forbidden.");
+ }
+ else {
+ sendServerMessageArea(sender_name + " has set blankposting in the area to allowed.");
+ }
+}
+
+void AOClient::cmdGimp(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (target->is_gimped)
+ sendServerMessage("That player is already gimped!");
+ else {
+ sendServerMessage("Gimped player.");
+ target->sendServerMessage("You have been gimped! " + getReprimand());
+ }
+ target->is_gimped = true;
+}
+
+void AOClient::cmdUnGimp(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (!(target->is_gimped))
+ sendServerMessage("That player is not gimped!");
+ else {
+ sendServerMessage("Ungimped player.");
+ target->sendServerMessage("A moderator has ungimped you! " + getReprimand(true));
+ }
+ target->is_gimped = false;
+}
+void AOClient::cmdBanInfo(int argc, QStringList argv)
+{
+ QStringList ban_info;
+ ban_info << ("Ban Info for " + argv[0]);
+ ban_info << "-----";
+ QString lookup_type;
+
+ if (argc == 1) {
+ lookup_type = "banid";
+ }
+ else if (argc == 2) {
+ lookup_type = argv[1];
+ if (!((lookup_type == "banid") || (lookup_type == "ipid") || (lookup_type == "hdid"))) {
+ sendServerMessage("Invalid ID type.");
+ return;
+ }
+ }
+ else {
+ sendServerMessage("Invalid command.");
+ return;
+ }
+ QString id = argv[0];
+ for (DBManager::BanInfo ban : server->db_manager->getBanInfo(lookup_type, id)) {
+ QString banned_until;
+ if (ban.duration == -2)
+ banned_until = "The heat death of the universe";
+ else
+ banned_until = QDateTime::fromSecsSinceEpoch(ban.time).addSecs(ban.duration).toString("dd.MM.yyyy, hh:mm");
+ ban_info << "Affected IPID: " + ban.ipid;
+ ban_info << "Affected HDID: " + ban.hdid;
+ ban_info << "Reason for ban: " + ban.reason;
+ ban_info << "Date of ban: " + QDateTime::fromSecsSinceEpoch(ban.time).toString("dd.MM.yyyy, hh:mm");
+ ban_info << "Ban lasts until: " + banned_until;
+ ban_info << "-----";
+ }
+ sendServerMessage(ban_info.join("\n"));
+}
+
+void AOClient::cmdTestify(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ if (area->test_rec == AreaData::TestimonyRecording::RECORDING) {
+ sendServerMessage("Testimony recording is already in progress. Please stop it before starting a new one.");
+ }
+ else {
+ clearTestimony();
+ area->statement = 0;
+ area->test_rec = AreaData::TestimonyRecording::RECORDING;
+ sendServerMessage("Started testimony recording.");
+ }
+}
+
+void AOClient::cmdExamine(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ if (area->testimony.size() -1 > 0)
+ {
+ area->test_rec = AreaData::TestimonyRecording::PLAYBACK;
+ server->broadcast(AOPacket("RT",{"testimony2"}), current_area);
+ server->broadcast(AOPacket("MS", {area->testimony[0]}), current_area);
+ area->statement = 0;
+ return;
+ }
+ if (area->test_rec == AreaData::TestimonyRecording::PLAYBACK)
+ sendServerMessage("Unable to examine while another examination is running");
+ else
+ sendServerMessage("Unable to start replay without prior examination.");
+}
+
+void AOClient::cmdDeleteStatement(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ int c_statement = area->statement;
+ if (area->testimony.size() - 1 == 0) {
+ sendServerMessage("Unable to delete statement. No statements saved in this area.");
+ }
+ if (c_statement > 0 && area->testimony.size() > 2) {
+ area->testimony.remove(c_statement);
+ sendServerMessage("The statement with id " + QString::number(c_statement) + " has been deleted from the testimony.");
+ }
+}
+
+void AOClient::cmdUpdateStatement(int argc, QStringList argv)
+{
+ server->areas[current_area]->test_rec = AreaData::TestimonyRecording::UPDATE;
+ sendServerMessage("The next IC-Message will replace the last displayed replay message.");
+}
+
+void AOClient::cmdPauseTestimony(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ area->test_rec = AreaData::TestimonyRecording::STOPPED;
+ sendServerMessage("Testimony has been stopped.");
+}
+
+void AOClient::cmdAddStatement(int argc, QStringList argv)
+{
+ if (server->areas[current_area]->statement < server->maximum_statements) {
+ server->areas[current_area]->test_rec = AreaData::TestimonyRecording::ADD;
+ sendServerMessage("The next IC-Message will be inserted into the testimony.");
+ }
+ else
+ sendServerMessage("Unable to add anymore statements. Please remove any unused ones.");
+}
+
+void AOClient::cmdReload(int argc, QStringList argv)
+{
+ server->loadServerConfig();
+ server->loadCommandConfig();
+ emit server->reloadRequest(server->server_name, server->server_desc);
+ sendServerMessage("Reloaded configurations");
+}
+
+void AOClient::cmdDisemvowel(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (target->is_disemvoweled)
+ sendServerMessage("That player is already disemvoweled!");
+ else {
+ sendServerMessage("Disemvoweled player.");
+ target->sendServerMessage("You have been disemvoweled! " + getReprimand());
+ }
+ target->is_disemvoweled = true;
+}
+
+void AOClient::cmdUnDisemvowel(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (!(target->is_disemvoweled))
+ sendServerMessage("That player is not disemvoweled!");
+ else {
+ sendServerMessage("Undisemvoweled player.");
+ target->sendServerMessage("A moderator has undisemvoweled you! " + getReprimand(true));
+ }
+ target->is_disemvoweled = false;
+}
+
+void AOClient::cmdShake(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (target->is_shaken)
+ sendServerMessage("That player is already shaken!");
+ else {
+ sendServerMessage("Shook player.");
+ target->sendServerMessage("A moderator has shaken your words! " + getReprimand());
+ }
+ target->is_shaken = true;
+}
+
+void AOClient::cmdUnShake(int argc, QStringList argv)
+{
+ bool conv_ok = false;
+ int uid = argv[0].toInt(&conv_ok);
+ if (!conv_ok) {
+ sendServerMessage("Invalid user ID.");
+ return;
+ }
+
+ AOClient* target = server->getClientByID(uid);
+
+ if (!(target->is_shaken))
+ sendServerMessage("That player is not shaken!");
+ else {
+ sendServerMessage("Unshook player.");
+ target->sendServerMessage("A moderator has unshook you! " + getReprimand(true));
+ }
+ target->is_shaken = false;
+}
+
+void AOClient::cmdForceImmediate(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ area->force_immediate = !area->force_immediate;
+ QString state = area->force_immediate ? "on." : "off.";
+ sendServerMessage("Forced immediate text processing in this area is now " + state);
+}
+
+void AOClient::cmdAllowIniswap(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ area->iniswap_allowed = !area->iniswap_allowed;
+ QString state = area->iniswap_allowed ? "allowed." : "disallowed.";
+ sendServerMessage("Iniswapping in this area is now " + state);
+}
+
+void AOClient::cmdAfk(int argc, QStringList argv)
+{
+ is_afk = true;
+ sendServerMessage("You are now AFK.");
+}
+
+QStringList AOClient::buildAreaList(int area_idx)
+{
+ QStringList entries;
+ QString area_name = server->area_names[area_idx];
+ AreaData* area = server->areas[area_idx];
+ entries.append("=== " + area_name + " ===");
+ switch (area->locked) {
+ case AreaData::LockStatus::LOCKED:
+ entries.append("[LOCKED]");
+ break;
+ case AreaData::LockStatus::SPECTATABLE:
+ entries.append("[SPECTATABLE]");
+ break;
+ case AreaData::LockStatus::FREE:
+ default:
+ break;
+ }
+ entries.append("[" + QString::number(area->player_count) + " users][" + QVariant::fromValue(area->status).toString().replace("_", "-") + "]");
+ for (AOClient* client : server->clients) {
+ if (client->current_area == area_idx && client->joined) {
+ QString char_entry = "[" + QString::number(client->id) + "] " + client->current_char;
+ if (client->current_char == "")
+ char_entry += "Spectator";
+ if (area->owners.contains(client->id))
+ char_entry.insert(0, "[CM] ");
+ if (authenticated)
+ char_entry += " (" + client->getIpid() + "): " + client->ooc_name;
+ if (client->is_afk)
+ char_entry += " [AFK]";
+ entries.append(char_entry);
+ }
+ }
+ return entries;
+}
+
+int AOClient::genRand(int min, int max)
+{
+#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
+ qsrand(QDateTime::currentMSecsSinceEpoch());
+ quint32 random_number = (qrand() % (max - min + 1)) + min;
+ return random_number;
+
+#else
+ quint32 random_number = QRandomGenerator::system()->bounded(min, max + 1);
+ return random_number;
+#endif
+}
+
+void AOClient::diceThrower(int argc, QStringList argv, RollType type)
+{
+ QString sender_name = ooc_name;
+ int max_value = server->dice_value;
+ int max_dice = server->max_dice;
+ int bounded_value;
+ int bounded_amount;
+ QString dice_results;
+
+ if (argc == 0) {
+ dice_results = QString::number(genRand(1, 6)); // Self-explanatory
+ }
+ else if (argc == 1) {
+ bounded_value = qBound(1, argv[0].toInt(), max_value); // faces, max faces
+ dice_results = QString::number(genRand(1, bounded_value));
+ }
+ else if (argc == 2) {
+ bounded_value = qBound(1, argv[0].toInt(), max_value); // 1, faces, max faces
+ bounded_amount = qBound(1, argv[1].toInt(), max_dice); // 1, amount, max amount
+
+ for (int i = 1; i <= bounded_amount ; i++) // Loop as multiple dices are thrown
+ {
+ QString dice_result = QString::number(genRand(1, bounded_value));
+ if (i == bounded_amount) {
+ dice_results = dice_results.append(dice_result);
+ }
+ else {
+ dice_results = dice_results.append(dice_result + ",");
+ }
+ }
+ }
+ // Switch to change message behaviour, isEmpty check or the entire server crashes due to an out of range issue in the QStringList
+ switch(type)
+ {
+ case ROLL:
+ if (argv.isEmpty()) {
+ sendServerMessageArea(sender_name + " rolled " + dice_results + " out of 6");
+ }
+ else {
+ sendServerMessageArea(sender_name + " rolled " + dice_results + " out of " + QString::number(bounded_value));
+ }
+ break;
+ case ROLLP:
+ if (argv.isEmpty()) {
+ sendServerMessage(sender_name + " rolled " + dice_results + " out of 6");
+ sendServerMessageArea((sender_name + " rolled in secret."));
+ }
+ else {
+ sendServerMessageArea(sender_name + " rolled " + dice_results + " out of " + QString::number(bounded_value));
+ sendServerMessageArea((sender_name + " rolled in secret."));
+ }
+ break;
+ case ROLLA:
+ //Not implemented yet
+ default : break;
+ }
+}
+
+QString AOClient::getAreaTimer(int area_idx, int timer_idx)
+{
+ AreaData* area = server->areas[area_idx];
+ QTimer* timer;
+ QString timer_name = (timer_idx == 0) ? "Global timer" : "Timer " + QString::number(timer_idx);
+
+ if (timer_idx == 0)
+ timer = server->timer;
+ else if (timer_idx > 0 && timer_idx <= 4)
+ timer = area->timers[timer_idx - 1];
+ else
+ return "Invalid timer ID.";
+
+ if (timer->isActive()) {
+ QTime current_time = QTime(0,0).addMSecs(timer->remainingTime());
+
+ return timer_name + " is at " + current_time.toString("hh:mm:ss.zzz");
+ }
+ else {
+ return timer_name + " is inactive.";
+ }
+}
+
+long long AOClient::parseTime(QString input)
+{
+ QRegularExpression regex("(?:(?:(?.*?)y)*(?:(?.*?)w)*(?:(?.*?)d)*(?:(?
.*?)h)*(?:(?.*?)m)*(?:(?.*?)s)*)");
+ QRegularExpressionMatch match = regex.match(input);
+ QString str_year, str_week, str_hour, str_day, str_minute, str_second;
+ int year, week, day, hour, minute, second;
+
+ str_year = match.captured("year");
+ str_week = match.captured("week");
+ str_day = match.captured("day");
+ str_hour = match.captured("hr");
+ str_minute = match.captured("min");
+ str_second = match.captured("sec");
+
+ bool is_well_formed = false;
+ QString concat_str(str_year + str_week + str_day + str_hour + str_minute + str_second);
+ concat_str.toInt(&is_well_formed);
+
+ if (!is_well_formed) {
+ return -1;
+ }
+
+ year = str_year.toInt();
+ week = str_week.toInt();
+ day = str_day.toInt();
+ hour = str_hour.toInt();
+ minute = str_minute.toInt();
+ second = str_second.toInt();
+
+ long long total = 0;
+ total += 31622400 * year;
+ total += 604800 * week;
+ total += 86400 * day;
+ total += 3600 * hour;
+ total += 60 * minute;
+ total += second;
+
+ if (total < 0)
+ return -1;
+
+ return total;
+}
+
+QString AOClient::getReprimand(bool positive)
+{
+ if (positive) {
+ return server->praise_list[genRand(0, server->praise_list.size() - 1)];
+ }
+ else {
+ return server->reprimands_list[genRand(0, server->reprimands_list.size() - 1)];
+ }
+}
diff --git a/src/packets.cpp b/src/packets.cpp
index f271216..6ddce8a 100644
--- a/src/packets.cpp
+++ b/src/packets.cpp
@@ -344,6 +344,59 @@ void AOClient::pktEditEvidence(AreaData* area, int argc, QStringList argv, AOPac
sendEvidenceList(area);
}
+void AOClient::pktSetCase(AreaData* area, int argc, QStringList argv, AOPacket packet)
+{
+ QList prefs_list;
+ 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 = prefs_list;
+}
+
+void AOClient::pktAnnounceCase(AreaData* area, int argc, QStringList argv, AOPacket packet)
+{
+ 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);
+ }
+ 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 (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) + "!";
+
+ 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_set);
+ if (!matches.isEmpty() && !clients_to_alert.contains(client))
+ clients_to_alert.append(client);
+ }
+
+ 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) {
@@ -594,11 +647,13 @@ AOPacket AOClient::validateIcPacket(AOPacket packet)
}
args.append(other_flip);
- // noninterrupting preanim
- int ni_pa = incoming_args[18].toInt();
- if (ni_pa != 1 && ni_pa != 0)
+ // immediate text processing
+ int immediate = incoming_args[18].toInt();
+ if (area->force_immediate)
+ immediate = 1;
+ if (immediate != 1 && immediate != 0)
return invalid;
- args.append(QString::number(ni_pa));
+ args.append(QString::number(immediate));
}
// 2.8 packet extensions
@@ -717,6 +772,4 @@ void AOClient::updateJudgeLog(AreaData* area, AOClient* client, QString action)
area->judgelog.append(logmessage);
}
else area->judgelog.append(logmessage);
-
-
}
diff --git a/src/server.cpp b/src/server.cpp
index 48d2787..382e5a2 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -53,9 +53,7 @@ void Server::start()
loadServerConfig();
loadCommandConfig();
-
- maximum_statements = config.value("maximum_statements", 50).toInt();
-
+
proxy = new WSProxy(port, ws_port, this);
if(ws_port != -1)
proxy->start();
@@ -232,9 +230,17 @@ void Server::loadServerConfig()
auth_type = config.value("auth","simple").toString();
modpass = config.value("modpass","").toString();
bool zalgo_tolerance_conversion_success;
- zalgo_tolerance = config.value("zalgo_tolerance", "3").toInt(&zalgo_tolerance_conversion_success);
- if (!zalgo_tolerance_conversion_success)
- zalgo_tolerance = 3;
+ zalgo_tolerance = config.value("zalgo_tolerance", "3").toInt(&zalgo_tolerance_conversion_success);
+ if (!zalgo_tolerance_conversion_success)
+ zalgo_tolerance = 3;
+ bool maximum_statements_conversion_success;
+ maximum_statements = config.value("maximum_statements", "10").toInt(&maximum_statements_conversion_success);
+ if (!maximum_statements_conversion_success)
+ maximum_statements = 10;
+ bool afk_timeout_conversion_success;
+ afk_timeout = config.value("afk_timeout", "300").toInt(&afk_timeout_conversion_success);
+ if (!afk_timeout_conversion_success)
+ afk_timeout = 300;
config.endGroup();
//Load dice values
diff --git a/src/testimony_recorder.cpp b/src/testimony_recorder.cpp
index 3c6897d..01178b5 100644
--- a/src/testimony_recorder.cpp
+++ b/src/testimony_recorder.cpp
@@ -39,6 +39,7 @@ void AOClient::addStatement(QStringList packet)
}
}
else if (area->test_rec == AreaData::TestimonyRecording::ADD) {
+ packet[14] = "1";
area->testimony.insert(c_statement,packet);
area->test_rec = AreaData::TestimonyRecording::PLAYBACK;
}
From ea50100acf71c398070192e32123ac6ee286cf39 Mon Sep 17 00:00:00 2001
From: MangosArentLiterature
<58055358+MangosArentLiterature@users.noreply.github.com>
Date: Thu, 15 Apr 2021 18:13:15 -0500
Subject: [PATCH 5/5] Sort out new commands from master, delete commands.cpp
:crab: :crab:
---
akashi.pro | 1 -
include/aoclient.h | 36 +-
src/commands.cpp | 1726 -------------------------------
src/commands/area.cpp | 6 +
src/commands/command_helper.cpp | 2 +
src/commands/moderation.cpp | 17 +-
6 files changed, 42 insertions(+), 1746 deletions(-)
delete mode 100644 src/commands.cpp
diff --git a/akashi.pro b/akashi.pro
index 28d80f4..8e995b4 100644
--- a/akashi.pro
+++ b/akashi.pro
@@ -30,7 +30,6 @@ SOURCES += src/advertiser.cpp \
src/aoclient.cpp \
src/aopacket.cpp \
src/area_data.cpp \
- src/commands.cpp \
src/commands/area.cpp \
src/commands/authentication.cpp \
src/commands/casing.cpp \
diff --git a/include/aoclient.h b/include/aoclient.h
index 1bc4f0e..3ab8429 100644
--- a/include/aoclient.h
+++ b/include/aoclient.h
@@ -1125,6 +1125,24 @@ class AOClient : public QObject {
*/
void cmdReload(int argc, QStringList argv);
+ /**
+ * @brief Toggles immediate text processing in the current area.
+ *
+ * @details No arguments.
+ *
+ * @iscommand
+ */
+ void cmdForceImmediate(int argc, QStringList argv);
+
+ /**
+ * @brief Toggles whether iniswaps are allowed in the current area.
+ *
+ * @details No arguments.
+ *
+ * @iscommand
+ */
+ void cmdAllowIniswap(int argc, QStringList argv);
+
///@}
/**
@@ -1570,24 +1588,6 @@ class AOClient : public QObject {
void cmdCurrentMusic(int argc, QStringList argv);
- /**
- * @brief Toggles immediate text processing in the current area.
- *
- * @details No arguments.
- *
- * @iscommand
- */
- void cmdForceImmediate(int argc, QStringList argv);
-
- /**
- * @brief Toggles whether iniswaps are allowed in the current area.
- *
- * @details No arguments.
- *
- * @iscommand
- */
- void cmdAllowIniswap(int argc, QStringList argv);
-
/**
* @brief Toggles whether this client is considered AFK.
*
diff --git a/src/commands.cpp b/src/commands.cpp
deleted file mode 100644
index 135c06a..0000000
--- a/src/commands.cpp
+++ /dev/null
@@ -1,1726 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////////////
-// akashi - a server for Attorney Online 2 //
-// Copyright (C) 2020 scatterflower //
-// //
-// 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 . //
-//////////////////////////////////////////////////////////////////////////////////////
-#include "include/aoclient.h"
-
-// Be sure to register the command in the header before adding it here!
-
-void AOClient::cmdDefault(int argc, QStringList argv)
-{
- sendServerMessage("Invalid command.");
- return;
-}
-
-void AOClient::cmdLogin(int argc, QStringList argv)
-{
- if (authenticated) {
- sendServerMessage("You are already logged in!");
- return;
- }
-
- if (server->auth_type == "simple") {
- if (server->modpass == "") {
- sendServerMessage("No modpass is set! Please set a modpass before authenticating.");
- }
- else if(argv[0] == server->modpass) {
- sendPacket("AUTH", {"1"}); // Client: "You were granted the Disable Modcalls button."
- sendServerMessage("Logged in as a moderator."); // pre-2.9.1 clients are hardcoded to display the mod UI when this string is sent in OOC
- authenticated = true;
- }
- else {
- sendPacket("AUTH", {"0"}); // Client: "Login unsuccessful."
- sendServerMessage("Incorrect password.");
- }
- server->areas.value(current_area)->logger->logLogin(this, authenticated, "moderator");
- }
- else if (server->auth_type == "advanced") {
- if (argc < 2) {
- sendServerMessage("You must specify a username and a password");
- return;
- }
- QString username = argv[0];
- QString password = argv[1];
- if (server->db_manager->authenticate(username, password)) {
- moderator_name = username;
- authenticated = true;
- sendPacket("AUTH", {"1"}); // Client: "You were granted the Disable Modcalls button."
- if (version.release <= 2 && version.major <= 9 && version.minor <= 0)
- sendServerMessage("Logged in as a moderator."); // pre-2.9.1 clients are hardcoded to display the mod UI when this string is sent in OOC
- sendServerMessage("Welcome, " + username);
- }
- else {
- sendPacket("AUTH", {"0"}); // Client: "Login unsuccessful."
- sendServerMessage("Incorrect password.");
- }
- server->areas.value(current_area)->logger->logLogin(this, authenticated, username);
- }
- else {
- qWarning() << "config.ini has an unrecognized auth_type!";
- sendServerMessage("Config.ini contains an invalid auth_type, please check your config.");
- }
-}
-
-void AOClient::cmdGetAreas(int argc, QStringList argv)
-{
- QStringList entries;
- entries.append("== Area List ==");
- for (int i = 0; i < server->area_names.length(); i++) {
- QStringList cur_area_lines = buildAreaList(i);
- entries.append(cur_area_lines);
- }
- sendServerMessage(entries.join("\n"));
-}
-
-void AOClient::cmdGetArea(int argc, QStringList argv)
-{
- QStringList entries = buildAreaList(current_area);
- sendServerMessage(entries.join("\n"));
-}
-
-void AOClient::cmdBan(int argc, QStringList argv)
-{
- QString args_str = argv[1];
- if (argc > 2) {
- for (int i = 2; i < argc; i++)
- args_str += " " + argv[i];
- }
-
- DBManager::BanInfo ban;
-
- QRegularExpression quoteMatcher("['\"](.+?)[\"']");
- QRegularExpressionMatchIterator matches = quoteMatcher.globalMatch(args_str);
- QList unquoted_args;
- while (matches.hasNext()) {
- QRegularExpressionMatch match = matches.next();
- unquoted_args.append(match.captured(1));
- }
-
- QString duration = "perma";
-
- if (unquoted_args.length() < 1) {
- sendServerMessage("Invalid syntax. Usage:\n/ban \"\" \"\"");
- return;
- }
-
- ban.reason = unquoted_args.at(0);
- if (unquoted_args.length() > 1)
- duration = unquoted_args.at(1);
-
- long long duration_seconds = 0;
- if (duration == "perma")
- duration_seconds = -2;
- else
- duration_seconds = parseTime(duration);
-
- if (duration_seconds == -1) {
- sendServerMessage("Invalid time format. Format example: 1h30m");
- return;
- }
-
- ban.duration = duration_seconds;
-
- ban.ipid = argv[0];
- ban.time = QDateTime::currentDateTime().toSecsSinceEpoch();
- bool ban_logged = false;
- int kick_counter = 0;
-
- if (argc > 2) {
- for (int i = 2; i < argv.length(); i++) {
- ban.reason += " " + argv[i];
- }
- }
-
- for (AOClient* client : server->getClientsByIpid(ban.ipid)) {
- if (!ban_logged) {
- ban.ip = client->remote_ip;
- ban.hdid = client->hwid;
- server->db_manager->addBan(ban);
- sendServerMessage("Banned user with ipid " + ban.ipid + " for reason: " + ban.reason);
- ban_logged = true;
- }
- client->sendPacket("KB", {ban.reason + "\nID: " + QString::number(server->db_manager->getBanID(ban.ip)) + "\nUntil: " + QDateTime::fromSecsSinceEpoch(ban.time).addSecs(ban.duration).toString("dd.MM.yyyy, hh:mm")});
- client->socket->close();
- kick_counter++;
- }
-
- if (kick_counter > 1)
- sendServerMessage("Kicked " + QString::number(kick_counter) + " clients with matching ipids.");
- if (!ban_logged)
- sendServerMessage("User with ipid not found!");
-}
-
-void AOClient::cmdKick(int argc, QStringList argv)
-{
- QString target_ipid = argv[0];
- QString reason = argv[1];
- int kick_counter = 0;
-
- if (argc > 2) {
- for (int i = 2; i < argv.length(); i++) {
- reason += " " + argv[i];
- }
- }
-
- for (AOClient* client : server->getClientsByIpid(target_ipid)) {
- client->sendPacket("KK", {reason});
- client->socket->close();
- kick_counter++;
- }
-
- if (kick_counter > 0)
- sendServerMessage("Kicked " + QString::number(kick_counter) + " client(s) with ipid " + target_ipid + " for reason: " + reason);
- else
- sendServerMessage("User with ipid not found!");
-}
-
-void AOClient::cmdChangeAuth(int argc, QStringList argv)
-{
- if (server->auth_type == "simple") {
- change_auth_started = true;
- sendServerMessage("WARNING!\nThis command will change how logging in as a moderator works.\nOnly proceed if you know what you are doing\nUse the command /rootpass to set the password for your root account.");
- }
-}
-
-void AOClient::cmdSetRootPass(int argc, QStringList argv)
-{
- if (!change_auth_started)
- return;
-
- sendServerMessage("Changing auth type and setting root password.\nLogin again with /login root [password]");
- authenticated = false;
- QSettings settings("config/config.ini", QSettings::IniFormat);
- settings.beginGroup("Options");
- settings.setValue("auth", "advanced");
- server->auth_type = "advanced";
-
-#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
- qsrand(QDateTime::currentMSecsSinceEpoch());
- quint32 upper_salt = qrand();
- quint32 lower_salt = qrand();
- quint64 salt_number = (upper_salt << 32) | lower_salt;
-#else
- quint64 salt_number = QRandomGenerator::system()->generate64();
-#endif
- QString salt = QStringLiteral("%1").arg(salt_number, 16, 16, QLatin1Char('0'));
-
- server->db_manager->createUser("root", salt, argv[0], ACLFlags.value("SUPER"));
-}
-
-void AOClient::cmdSetBackground(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (authenticated || !area->bg_locked) {
- if (server->backgrounds.contains(argv[0])) {
- area->background = argv[0];
- server->broadcast(AOPacket("BN", {argv[0]}), current_area);
- sendServerMessageArea(current_char + " changed the background to " + argv[0]);
- }
- else {
- sendServerMessage("Invalid background name.");
- }
- }
- else {
- sendServerMessage("This area's background is locked.");
- }
-}
-
-void AOClient::cmdBgLock(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- area->bg_locked = true;
- server->broadcast(AOPacket("CT", {"Server", current_char + " locked the background.", "1"}), current_area);
-}
-
-void AOClient::cmdBgUnlock(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- area->bg_locked = false;
- server->broadcast(AOPacket("CT", {"Server", current_char + " unlocked the background.", "1"}), current_area);
-}
-
-void AOClient::cmdAddUser(int argc, QStringList argv)
-{
-#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
- qsrand(QDateTime::currentMSecsSinceEpoch());
- quint32 upper_salt = qrand();
- quint32 lower_salt = qrand();
- quint64 salt_number = (upper_salt << 32) | lower_salt;
-#else
- quint64 salt_number = QRandomGenerator::system()->generate64();
-#endif
- QString salt = QStringLiteral("%1").arg(salt_number, 16, 16, QLatin1Char('0'));
-
- if (server->db_manager->createUser(argv[0], salt, argv[1], ACLFlags.value("NONE")))
- sendServerMessage("Created user " + argv[0] + ".\nUse /addperm to modify their permissions.");
- else
- sendServerMessage("Unable to create user " + argv[0] + ".\nDoes a user with that name already exist?");
-}
-
-void AOClient::cmdRemoveUser(int argc, QStringList argv)
-{
- if (server->db_manager->deleteUser(argv[0]))
- sendServerMessage("Successfully removed user " + argv[0] + ".");
- else
- sendServerMessage("Unable to remove user " + argv[0] + ".\nDoes it exist?");
-}
-
-void AOClient::cmdListPerms(int argc, QStringList argv)
-{
- unsigned long long user_acl = server->db_manager->getACL(moderator_name);
- QStringList message;
- if (argc == 0) {
- // Just print out all permissions available to the user.
- message.append("You have been given the following permissions:");
- for (QString perm : ACLFlags.keys()) {
- if (perm == "NONE"); // don't need to list this one
- else if (perm == "SUPER") {
- if (user_acl == ACLFlags.value("SUPER")) // This has to be checked separately, because SUPER & anything will always be truthy
- message.append("SUPER (Be careful! This grants the user all permissions.)");
- }
- else if ((ACLFlags.value(perm) & user_acl) == 0); // user doesn't have this permission, don't print it
- else
- message.append(perm);
- }
- }
- else {
- if ((user_acl & ACLFlags.value("MODIFY_USERS")) == 0) {
- sendServerMessage("You do not have permission to view other users' permissions.");
- return;
- }
-
- message.append("User " + argv[0] + " has the following permissions:");
- unsigned long long acl = server->db_manager->getACL(argv[0]);
- if (acl == 0) {
- sendServerMessage("This user either doesn't exist, or has no permissions set.");
- return;
- }
-
- for (QString perm : ACLFlags.keys()) {
- if ((ACLFlags.value(perm) & acl) != 0 && perm != "SUPER") {
- message.append(perm);
- }
- }
- }
- sendServerMessage(message.join("\n"));
-}
-
-void AOClient::cmdAddPerms(int argc, QStringList argv)
-{
- unsigned long long user_acl = server->db_manager->getACL(moderator_name);
- argv[1] = argv[1].toUpper();
-
- if (!ACLFlags.keys().contains(argv[1])) {
- sendServerMessage("That permission doesn't exist!");
- return;
- }
-
- if (argv[1] == "SUPER") {
- if (user_acl != ACLFlags.value("SUPER")) {
- // This has to be checked separately, because SUPER & anything will always be truthy
- sendServerMessage("You aren't allowed to add that permission!");
- return;
- }
- }
- if (argv[1] == "NONE") {
- sendServerMessage("Added no permissions!");
- return;
- }
-
- unsigned long long newperm = ACLFlags.value(argv[1]);
- if ((newperm & user_acl) != 0) {
- if (server->db_manager->updateACL(argv[0], newperm, true))
- sendServerMessage("Successfully added permission " + argv[1] + " to user " + argv[0]);
- else
- sendServerMessage(argv[0] + " wasn't found!");
- return;
- }
-
- sendServerMessage("You aren't allowed to add that permission!");
-}
-
-void AOClient::cmdRemovePerms(int argc, QStringList argv)
-{
- unsigned long long user_acl = server->db_manager->getACL(moderator_name);
- argv[1] = argv[1].toUpper();
-
- if (!ACLFlags.keys().contains(argv[1])) {
- sendServerMessage("That permission doesn't exist!");
- return;
- }
-
- if (argv[0] == "root") {
- sendServerMessage("You cannot change the permissions of the root account!");
- return;
- }
-
- if (argv[1] == "SUPER") {
- if (user_acl != ACLFlags.value("SUPER")) {
- // This has to be checked separately, because SUPER & anything will always be truthy
- sendServerMessage("You aren't allowed to remove that permission!");
- return;
- }
- }
- if (argv[1] == "NONE") {
- sendServerMessage("Removed no permissions!");
- return;
- }
-
- unsigned long long newperm = ACLFlags.value(argv[1]);
- if ((newperm & user_acl) != 0) {
- if (server->db_manager->updateACL(argv[0], newperm, false))
- sendServerMessage("Successfully removed permission " + argv[1] + " from user " + argv[0]);
- else
- sendServerMessage(argv[0] + " wasn't found!");
- return;
- }
-
- sendServerMessage("You aren't allowed to remove that permission!");
-}
-
-void AOClient::cmdListUsers(int argc, QStringList argv)
-{
- QStringList users = server->db_manager->getUsers();
- sendServerMessage("All users:\n" + users.join("\n"));
-}
-
-void AOClient::cmdLogout(int argc, QStringList argv)
-{
- if (!authenticated) {
- sendServerMessage("You are not logged in!");
- return;
- }
- authenticated = false;
- moderator_name = "";
- sendPacket("AUTH", {"-1"}); // Client: "You were logged out."
-}
-
-void AOClient::cmdPos(int argc, QStringList argv)
-{
- changePosition(argv[0]);
- updateEvidenceList(server->areas[current_area]);
-}
-
-void AOClient::cmdForcePos(int argc, QStringList argv)
-{
- bool ok;
- QList targets;
- AreaData* area = server->areas[current_area];
- int target_id = argv[1].toInt(&ok);
- int forced_clients = 0;
- if (!ok && argv[1] != "*") {
- sendServerMessage("That does not look like a valid ID.");
- return;
- }
- else if (ok) {
- AOClient* target_client = server->getClientByID(target_id);
- if (target_client != nullptr)
- targets.append(target_client);
- else {
- sendServerMessage("Target ID not found!");
- return;
- }
- }
-
- else if (argv[1] == "*") { // force all clients in the area
- for (AOClient* client : server->clients) {
- if (client->current_area == current_area)
- targets.append(client);
- }
- }
- for (AOClient* target : targets) {
- target->sendServerMessage("Position forcibly changed by CM.");
- target->changePosition(argv[0]);
- forced_clients++;
- }
- sendServerMessage("Forced " + QString::number(forced_clients) + " into pos " + argv[0] + ".");
-}
-
-void AOClient::cmdG(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- QString sender_area = server->area_names.value(current_area);
- QString sender_message = argv.join(" ");
- for (AOClient* client : server->clients) {
- if (client->global_enabled)
- client->sendPacket("CT", {"[G][" + sender_area + "]" + sender_name, sender_message});
- }
- return;
-}
-
-void AOClient::cmdNeed(int argc, QStringList argv)
-{
- QString sender_area = server->area_names.value(current_area);
- QString sender_message = argv.join(" ");
- sendServerBroadcast({"=== Advert ===\n[" + sender_area + "] needs " + sender_message+ "."});
-}
-
-void AOClient::cmdFlip(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- QStringList faces = {"heads","tails"};
- QString face = faces[AOClient::genRand(0,1)];
- sendServerMessage(sender_name + " flipped a coin and got " + face + ".");
-}
-
-void AOClient::cmdRoll(int argc, QStringList argv)
-{
- diceThrower(argc, argv, RollType::ROLL);
-}
-
-void AOClient::cmdRollP(int argc, QStringList argv)
-{
- diceThrower(argc, argv, RollType::ROLLP);
-}
-
-void AOClient::cmdDoc(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- AreaData* area = server->areas[current_area];
- if (argc == 0) {
- sendServerMessage("Document: " + area->document);
- }
- else {
- area->document = argv.join(" ");
- sendServerMessageArea(sender_name + " changed the document.");
- }
-}
-
-void AOClient::cmdClearDoc(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- AreaData* area = server->areas[current_area];
- area->document = "No document.";
- sendServerMessageArea(sender_name + " cleared the document.");
-}
-
-void AOClient::cmdCM(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- AreaData* area = server->areas[current_area];
- if (area->is_protected) {
- sendServerMessage("This area is protected, you may not become CM.");
- return;
- }
- else if (area->owners.isEmpty()) { // no one owns this area, and it's not protected
- area->owners.append(id);
- area->invited.append(id);
- sendServerMessageArea(sender_name + " is now CM in this area.");
- arup(ARUPType::CM, true);
- }
- else if (!area->owners.contains(id)) { // there is already a CM, and it isn't us
- sendServerMessage("You cannot become a CM in this area.");
- }
- else if (argc == 1) { // we are CM, and we want to make ID argv[0] also CM
- bool ok;
- AOClient* owner_candidate = server->getClientByID(argv[0].toInt(&ok));
- if (!ok) {
- sendServerMessage("That doesn't look like a valid ID.");
- return;
- }
- if (owner_candidate == nullptr) {
- sendServerMessage("Unable to find client with ID " + argv[0] + ".");
- return;
- }
- area->owners.append(owner_candidate->id);
- sendServerMessageArea(owner_candidate->ooc_name + " is now CM in this area.");
- arup(ARUPType::CM, true);
- }
- else {
- sendServerMessage("You are already a CM in this area.");
- }
-}
-
-void AOClient::cmdUnCM(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- int removed = area->owners.removeAll(id);
- area->invited.removeAll(id);
- sendServerMessage("You are no longer CM in this area.");
- arup(ARUPType::CM, true);
- if (area->owners.isEmpty()) {
- area->invited.clear();
- if (area->locked != AreaData::FREE) {
- area->locked = AreaData::FREE;
- arup(ARUPType::LOCKED, true);
- }
- }
-}
-
-void AOClient::cmdInvite(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- bool ok;
- int invited_id = argv[0].toInt(&ok);
- if (!ok) {
- sendServerMessage("That does not look like a valid ID.");
- return;
- }
- else if (server->getClientByID(invited_id) == nullptr) {
- sendServerMessage("No client with that ID found.");
- return;
- }
- else if (area->invited.contains(invited_id)) {
- sendServerMessage("That ID is already on the invite list.");
- return;
- }
- area->invited.append(invited_id);
- sendServerMessage("You invited ID " + argv[0]);
-}
-
-void AOClient::cmdUnInvite(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- bool ok;
- int uninvited_id = argv[0].toInt(&ok);
- if (!ok) {
- sendServerMessage("That does not look like a valid ID.");
- return;
- }
- else if (server->getClientByID(uninvited_id) == nullptr) {
- sendServerMessage("No client with that ID found.");
- return;
- }
- else if (area->owners.contains(uninvited_id)) {
- sendServerMessage("You cannot uninvite a CM!");
- return;
- }
- else if (!area->invited.contains(uninvited_id)) {
- sendServerMessage("That ID is not on the invite list.");
- return;
- }
- area->invited.removeAll(uninvited_id);
- sendServerMessage("You uninvited ID " + argv[0]);
-}
-
-void AOClient::cmdLock(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->locked == AreaData::LockStatus::LOCKED) {
- sendServerMessage("This area is already locked.");
- return;
- }
- sendServerMessageArea("This area is now locked.");
- area->locked = AreaData::LockStatus::LOCKED;
- for (AOClient* client : server->clients) {
- if (client->current_area == current_area && client->joined) {
- area->invited.append(client->id);
- }
- }
- arup(ARUPType::LOCKED, true);
-}
-
-void AOClient::cmdSpectatable(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->locked == AreaData::LockStatus::SPECTATABLE) {
- sendServerMessage("This area is already in spectate mode.");
- return;
- }
- sendServerMessageArea("This area is now spectatable.");
- area->locked = AreaData::LockStatus::SPECTATABLE;
- for (AOClient* client : server->clients) {
- if (client->current_area == current_area && client->joined) {
- area->invited.append(client->id);
- }
- }
- arup(ARUPType::LOCKED, true);
-}
-
-void AOClient::cmdUnLock(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->locked == AreaData::LockStatus::FREE) {
- sendServerMessage("This area is not locked.");
- return;
- }
- sendServerMessageArea("This area is now unlocked.");
- area->locked = AreaData::LockStatus::FREE;
- arup(ARUPType::LOCKED, true);
-}
-
-void AOClient::cmdTimer(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
-
- // Called without arguments
- // Shows a brief of all timers
- if (argc == 0) {
- QStringList timers;
- timers.append("Currently active timers:");
- for (int i = 0; i <= 4; i++) {
- timers.append(getAreaTimer(area->index, i));
- }
- sendServerMessage(timers.join("\n"));
- return;
- }
-
- // Called with more than one argument
- bool ok;
- int timer_id = argv[0].toInt(&ok);
- if (!ok || timer_id < 0 || timer_id > 4) {
- sendServerMessage("Invalid timer ID. Timer ID must be a whole number between 0 and 4.");
- return;
- }
-
- // Called with one argument
- // Shows the status of one timer
- if (argc == 1) {
- sendServerMessage(getAreaTimer(area->index, timer_id));
- return;
- }
-
- // Called with more than one argument
- // Updates the state of a timer
-
- // Select the proper timer
- // Check against permissions if global timer is selected
- QTimer* requested_timer;
- if (timer_id == 0) {
- if (!checkAuth(ACLFlags.value("GLOBAL_TIMER"))) {
- sendServerMessage("You are not authorized to alter the global timer.");
- return;
- }
- requested_timer = server->timer;
- }
- else
- requested_timer = area->timers[timer_id - 1];
-
- AOPacket show_timer("TI", {QString::number(timer_id), "2"});
- AOPacket hide_timer("TI", {QString::number(timer_id), "3"});
- bool is_global = timer_id == 0;
-
- // Set the timer's time remaining if the second
- // argument is a valid time
- QTime requested_time = QTime::fromString(argv[1], "hh:mm:ss");
- if (requested_time.isValid()) {
- requested_timer->setInterval(QTime(0,0).msecsTo(requested_time));
- requested_timer->start();
- sendServerMessage("Set timer " + QString::number(timer_id) + " to " + argv[1] + ".");
- AOPacket update_timer("TI", {QString::number(timer_id), "0", QString::number(QTime(0,0).msecsTo(requested_time))});
- is_global ? server->broadcast(show_timer) : server->broadcast(show_timer, current_area); // Show the timer
- is_global ? server->broadcast(update_timer) : server->broadcast(update_timer, current_area);
- return;
- }
- // Otherwise, update the state of the timer
- else {
- if (argv[1] == "start") {
- requested_timer->start();
- sendServerMessage("Started timer " + QString::number(timer_id) + ".");
- AOPacket update_timer("TI", {QString::number(timer_id), "0", QString::number(QTime(0,0).msecsTo(QTime(0,0).addMSecs(requested_timer->remainingTime())))});
- is_global ? server->broadcast(show_timer) : server->broadcast(show_timer, current_area);
- is_global ? server->broadcast(update_timer) : server->broadcast(update_timer, current_area);
- }
- else if (argv[1] == "pause" || argv[1] == "stop") {
- requested_timer->setInterval(requested_timer->remainingTime());
- requested_timer->stop();
- sendServerMessage("Stopped timer " + QString::number(timer_id) + ".");
- AOPacket update_timer("TI", {QString::number(timer_id), "1", QString::number(QTime(0,0).msecsTo(QTime(0,0).addMSecs(requested_timer->interval())))});
- is_global ? server->broadcast(update_timer) : server->broadcast(update_timer, current_area);
- }
- else if (argv[1] == "hide" || argv[1] == "unset") {
- requested_timer->setInterval(0);
- requested_timer->stop();
- sendServerMessage("Hid timer " + QString::number(timer_id) + ".");
- // Hide the timer
- is_global ? server->broadcast(hide_timer) : server->broadcast(hide_timer, current_area);
- }
- }
-}
-
-void AOClient::cmdEvidenceMod(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- argv[0] = argv[0].toLower();
- if (argv[0] == "cm")
- area->evi_mod = AreaData::EvidenceMod::CM;
- else if (argv[0] == "mod")
- area->evi_mod = AreaData::EvidenceMod::MOD;
- else if (argv[0] == "hiddencm")
- area->evi_mod = AreaData::EvidenceMod::HIDDEN_CM;
- else if (argv[0] == "ffa")
- area->evi_mod = AreaData::EvidenceMod::FFA;
- else {
- sendServerMessage("Invalid evidence mod.");
- return;
- }
- sendServerMessage("Changed evidence mod.");
-
- // Resend evidence lists to everyone in the area
- sendEvidenceList(area);
-}
-
-void AOClient::cmdArea(int argc, QStringList argv)
-{
- bool ok;
- int new_area = argv[0].toInt(&ok);
- if (!ok || new_area >= server->areas.size() || new_area < 0) {
- sendServerMessage("That does not look like a valid area ID.");
- return;
- }
- changeArea(new_area);
-}
-
-void AOClient::cmdPlay(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- QString song = argv.join(" ");
- area->current_music = song;
- area->music_played_by = showname;
- AOPacket music_change("MC", {song, QString::number(server->getCharID(current_char)), showname, "1", "0"});
- server->broadcast(music_change, current_area);
-}
-
-void AOClient::cmdAreaKick(int argc, QStringList argv)
-{
- bool ok;
- int idx = argv[0].toInt(&ok);
- if (!ok) {
- sendServerMessage("That does not look like a valid ID.");
- return;
- }
- AOClient* client_to_kick = server->getClientByID(idx);
- if (client_to_kick == nullptr) {
- sendServerMessage("No client with that ID found.");
- return;
- }
- client_to_kick->changeArea(0);
- sendServerMessage("Client " + argv[0] + " kicked back to area 0.");
-}
-
-void AOClient::cmdSwitch(int argc, QStringList argv)
-{
- int char_id = server->getCharID(argv.join(" "));
- if (char_id == -1) {
- sendServerMessage("That does not look like a valid character.");
- return;
- }
- changeCharacter(char_id);
-}
-
-void AOClient::cmdRandomChar(int argc, QStringList argv)
-{
- int char_id = genRand(0, server->characters.size() - 1);
- changeCharacter(char_id);
-}
-
-void AOClient::cmdToggleGlobal(int argc, QStringList argv)
-{
- global_enabled = !global_enabled;
- QString str_en = global_enabled ? "shown" : "hidden";
- sendServerMessage("Global chat set to " + str_en);
-}
-
-void AOClient::cmdMods(int argc, QStringList argv)
-{
- QStringList entries;
- int online_count = 0;
- for (AOClient* client : server->clients) {
- if (client->authenticated) {
- entries << "---";
- if (server->auth_type != "simple")
- entries << "Moderator: " + client->moderator_name;
- entries << "OOC name: " + client->ooc_name;
- entries << "ID: " + QString::number(client->id);
- entries << "Area: " + QString::number(client->current_area);
- entries << "Character: " + client->current_char;
- online_count++;
- }
- }
- entries << "---";
- entries << "Total online: " << QString::number(online_count);
- sendServerMessage(entries.join("\n"));
-}
-
-void AOClient::cmdHelp(int argc, QStringList argv)
-{
- QStringList entries;
- entries << "Allowed commands:";
- QMap::const_iterator i;
- for (i = commands.constBegin(); i!= commands.constEnd(); ++i) {
- CommandInfo info = i.value();
- if (checkAuth(info.acl_mask)) { // if we are allowed to use this command
- entries << "/" + i.key();
- }
- }
- sendServerMessage(entries.join("\n"));
-}
-
-void AOClient::cmdStatus(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- QString arg = argv[0].toLower();
- if (arg == "idle")
- area->status = AreaData::IDLE;
- else if (arg == "rp")
- area->status = AreaData::RP;
- else if (arg == "casing")
- area->status = AreaData::CASING;
- else if (arg == "looking-for-players" || arg == "lfp")
- area->status = AreaData::LOOKING_FOR_PLAYERS;
- else if (arg == "recess")
- area->status = AreaData::RECESS;
- else if (arg == "gaming")
- area->status = AreaData::GAMING;
- else {
- sendServerMessage("That does not look like a valid status. Valid statuses are idle, rp, casing, lfp, recess, gaming");
- return;
- }
- arup(ARUPType::STATUS, true);
-}
-
-void AOClient::cmdCurrentMusic(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->current_music != "" && area->current_music != "~stop.mp3") // dummy track for stopping music
- sendServerMessage("The current song is " + area->current_music + " played by " + area->music_played_by);
- else
- sendServerMessage("There is no music playing.");
-}
-
-void AOClient::cmdPM(int arc, QStringList argv)
-{
- bool ok;
- int target_id = argv.takeFirst().toInt(&ok); // using takeFirst removes the ID from our list of arguments...
- if (!ok) {
- sendServerMessage("That does not look like a valid ID.");
- return;
- }
- AOClient* target_client = server->getClientByID(target_id);
- if (target_client == nullptr) {
- sendServerMessage("No client with that ID found.");
- return;
- }
- QString message = argv.join(" "); //...which means it will not end up as part of the message
- target_client->sendServerMessage("Message from " + ooc_name + " (" + QString::number(id) + "): " + message);
-}
-
-void AOClient::cmdMOTD(int argc, QStringList argv)
-{
- if (argc == 0) {
- sendServerMessage("=== MOTD ===\r\n" + server->MOTD + "\r\n=============");
- }
- else if (argc > 0) {
- if (checkAuth(ACLFlags.value("MOTD"))) {
- QString MOTD = argv.join(" ");
- server->MOTD = MOTD;
- sendServerMessage("MOTD has been changed.");
- }
- else {
- sendServerMessage("You do not have permission to change the MOTD");
- }
- }
-}
-
-void AOClient::cmdAnnounce(int argc, QStringList argv)
-{
- sendServerBroadcast("=== Announcement ===\r\n" + argv.join(" ") + "\r\n=============");
-}
-
-void AOClient::cmdM(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- QString sender_message = argv.join(" ");
- for (AOClient* client : server->clients) {
- if (client->checkAuth(ACLFlags.value("MODCHAT")))
- client->sendPacket("CT", {"[M]" + sender_name, sender_message});
- }
- return;
-}
-
-void AOClient::cmdGM(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- QString sender_area = server->area_names.value(current_area);
- QString sender_message = argv.join(" ");
- for (AOClient* client : server->clients) {
- if (client->global_enabled) {
- client->sendPacket("CT", {"[G][" + sender_area + "]" + "["+sender_name+"][M]", sender_message});
- }
- }
-}
-
-void AOClient::cmdLM(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- QString sender_message = argv.join(" ");
- server->broadcast(AOPacket("CT", {"["+sender_name+"][M]", sender_message}), current_area);
-}
-
-void AOClient::cmdBans(int argc, QStringList argv)
-{
- QStringList recent_bans;
- recent_bans << "Last 5 bans:";
- recent_bans << "-----";
- for (DBManager::BanInfo ban : server->db_manager->getRecentBans()) {
- QString banned_until;
- if (ban.duration == -2)
- banned_until = "The heat death of the universe";
- else
- banned_until = QDateTime::fromSecsSinceEpoch(ban.time).addSecs(ban.duration).toString("dd.MM.yyyy, hh:mm");
- recent_bans << "Affected IPID: " + ban.ipid;
- recent_bans << "Affected HDID: " + ban.hdid;
- recent_bans << "Reason for ban: " + ban.reason;
- recent_bans << "Date of ban: " + QDateTime::fromSecsSinceEpoch(ban.time).toString("dd.MM.yyyy, hh:mm");
- recent_bans << "Ban lasts until: " + banned_until;
- recent_bans << "-----";
- }
- sendServerMessage(recent_bans.join("\n"));
-}
-
-void AOClient::cmdUnBan(int argc, QStringList argv)
-{
- bool ok;
- int target_ban = argv[0].toInt(&ok);
- if (!ok) {
- sendServerMessage("Invalid ban ID.");
- return;
- }
- else if (server->db_manager->invalidateBan(target_ban))
- sendServerMessage("Successfully invalidated ban " + argv[0] + ".");
- else
- sendServerMessage("Couldn't invalidate ban " + argv[0] + ", are you sure it exists?");
-}
-
-void AOClient::cmdSubTheme(int argc, QStringList argv)
-{
- QString subtheme = argv.join(" ");
- for (AOClient* client : server->clients) {
- if (client->current_area == current_area)
- client->sendPacket("ST", {subtheme, "1"});
- }
- sendServerMessageArea("Subtheme was set to " + subtheme);
-}
-
-void AOClient::cmdAbout(int argc, QStringList argv)
-{
- sendPacket("CT", {"The akashi dev team", "Thank you for using akashi! Made with love by scatterflower, with help from in1tiate and Salanto. akashi " + QCoreApplication::applicationVersion()});
-}
-
-void AOClient::cmdEvidence_Swap(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- int ev_size = area->evidence.size() -1;
-
- if (ev_size < 0) {
- sendServerMessage("No evidence in area.");
- return;
- }
-
- bool ok, ok2;
- int ev_id1 = argv[0].toInt(&ok), ev_id2 = argv[1].toInt(&ok2);
-
- if ((!ok || !ok2)) {
- sendServerMessage("Invalid evidence ID.");
- return;
- }
- if ((ev_id1 < 0) || (ev_id2 < 0)) {
- sendServerMessage("Evidence ID can't be negative.");
- return;
- }
- if ((ev_id2 <= ev_size) && (ev_id1 <= ev_size)) {
-#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
- //swapItemsAt does not exist in Qt older than 5.13
- area->evidence.swap(ev_id1, ev_id2);
-#else
- area->evidence.swapItemsAt(ev_id1, ev_id2);
-#endif
- sendEvidenceList(area);
- sendServerMessage("The evidence " + QString::number(ev_id1) + " and " + QString::number(ev_id2) + " have been swapped.");
- }
- else {
- sendServerMessage("Unable to swap evidence. Evidence ID out of range.");
- }
-}
-
-void AOClient::cmdMute(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (target->is_muted)
- sendServerMessage("That player is already muted!");
- else {
- sendServerMessage("Muted player.");
- target->sendServerMessage("You were muted by a moderator. " + getReprimand());
- }
- target->is_muted = true;
-}
-
-void AOClient::cmdUnMute(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (!target->is_muted)
- sendServerMessage("That player is not muted!");
- else {
- sendServerMessage("Unmuted player.");
- target->sendServerMessage("You were unmuted by a moderator. " + getReprimand(true));
- }
- target->is_muted = false;
-}
-
-void AOClient::cmdOocMute(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (target->is_ooc_muted)
- sendServerMessage("That player is already OOC muted!");
- else {
- sendServerMessage("OOC muted player.");
- target->sendServerMessage("You were OOC muted by a moderator. " + getReprimand());
- }
- target->is_ooc_muted = true;
-}
-
-void AOClient::cmdOocUnMute(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (!target->is_ooc_muted)
- sendServerMessage("That player is not OOC muted!");
- else {
- sendServerMessage("OOC unmuted player.");
- target->sendServerMessage("You were OOC unmuted by a moderator. " + getReprimand(true));
- }
- target->is_ooc_muted = false;
-}
-
-void AOClient::cmdBlockDj(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (target->is_dj_blocked)
- sendServerMessage("That player is already DJ blocked!");
- else {
- sendServerMessage("DJ blocked player.");
- target->sendServerMessage("You were blocked from changing the music by a moderator. " + getReprimand());
- }
- target->is_dj_blocked = true;
-}
-
-void AOClient::cmdUnBlockDj(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (!target->is_dj_blocked)
- sendServerMessage("That player is not DJ blocked!");
- else {
- sendServerMessage("DJ permissions restored to player.");
- target->sendServerMessage("A moderator restored your music permissions. " + getReprimand(true));
- }
- target->is_dj_blocked = false;
-}
-
-void AOClient::cmdBlockWtce(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (target->is_wtce_blocked)
- sendServerMessage("That player is already judge blocked!");
- else {
- sendServerMessage("Revoked player's access to judge controls.");
- target->sendServerMessage("A moderator revoked your judge controls access. " + getReprimand());
- }
- target->is_wtce_blocked = true;
-}
-
-void AOClient::cmdUnBlockWtce(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (!target->is_wtce_blocked)
- sendServerMessage("That player is not judge blocked!");
- else {
- sendServerMessage("Restored player's access to judge controls.");
- target->sendServerMessage("A moderator restored your judge controls access. " + getReprimand(true));
- }
- target->is_wtce_blocked = false;
-}
-
-void AOClient::cmdNoteCard(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->notecards.keys().contains(current_char))
- area->notecards.remove(current_char);
- QString notecard = argv.join(" ");
- area->notecards[current_char] = notecard;
- sendServerMessageArea(current_char + " wrote a note card.");
-}
-
-void AOClient::cmdNoteCardClear(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->notecards.keys().contains(current_char)) {
- area->notecards.remove(current_char);
- sendServerMessageArea(current_char + " erased their note card.");
- }
- else
- sendServerMessage("You do not have a note card.");
-}
-
-void AOClient::cmdNoteCardReveal(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->notecards.isEmpty()) {
- sendServerMessage("There are no cards to reveal in this area.");
- return;
- }
- QStringList message;
- message << "Note cards have been revealed.";
- QMap::iterator i;
- for (i = area->notecards.begin(); i != area->notecards.end(); ++i)
- message << i.key() + ": " + i.value();
- sendServerMessageArea(message.join("\n"));
- area->notecards.clear();
-}
-
-void AOClient::cmd8Ball(int argc, QStringList argv)
-{
- if (server->magic_8ball_answers.isEmpty()) {
- qWarning() << "8ball.txt is empty!";
- sendServerMessage("8ball.txt is empty.");
- }
- else {
- QString response = server->magic_8ball_answers[(genRand(1, server->magic_8ball_answers.size() - 1))];
- QString sender_name = ooc_name;
- QString sender_message = argv.join(" ");
-
- sendServerMessageArea(sender_name + " asked the magic 8-ball, \"" + sender_message + "\" and the answer is: " + response);
- }
-}
-
-void AOClient::cmdJudgeLog(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->judgelog.isEmpty()) {
- sendServerMessage("There have been no judge actions in this area.");
- return;
- }
- QString message = area->judgelog.join("\n");
- //Judgelog contains an IPID, so we shouldn't send that unless the caller has appropriate permissions
- if (checkAuth(ACLFlags.value("KICK")) == 1 || checkAuth(ACLFlags.value("BAN")) == 1) {
- sendServerMessage(message);
- }
- else {
- QString filteredmessage = message.remove(QRegularExpression("[(].*[)]")); //Filter out anything between two parentheses. This should only ever be the IPID
- sendServerMessage(filteredmessage);
- }
-}
-
-void AOClient::cmdAllowBlankposting(int argc, QStringList argv)
-{
- QString sender_name = ooc_name;
- AreaData* area = server->areas[current_area];
- area->blankposting_allowed = !area->blankposting_allowed;
- if (area->blankposting_allowed == false) {
- sendServerMessageArea(sender_name + " has set blankposting in the area to forbidden.");
- }
- else {
- sendServerMessageArea(sender_name + " has set blankposting in the area to allowed.");
- }
-}
-
-void AOClient::cmdGimp(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (target->is_gimped)
- sendServerMessage("That player is already gimped!");
- else {
- sendServerMessage("Gimped player.");
- target->sendServerMessage("You have been gimped! " + getReprimand());
- }
- target->is_gimped = true;
-}
-
-void AOClient::cmdUnGimp(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (!(target->is_gimped))
- sendServerMessage("That player is not gimped!");
- else {
- sendServerMessage("Ungimped player.");
- target->sendServerMessage("A moderator has ungimped you! " + getReprimand(true));
- }
- target->is_gimped = false;
-}
-void AOClient::cmdBanInfo(int argc, QStringList argv)
-{
- QStringList ban_info;
- ban_info << ("Ban Info for " + argv[0]);
- ban_info << "-----";
- QString lookup_type;
-
- if (argc == 1) {
- lookup_type = "banid";
- }
- else if (argc == 2) {
- lookup_type = argv[1];
- if (!((lookup_type == "banid") || (lookup_type == "ipid") || (lookup_type == "hdid"))) {
- sendServerMessage("Invalid ID type.");
- return;
- }
- }
- else {
- sendServerMessage("Invalid command.");
- return;
- }
- QString id = argv[0];
- for (DBManager::BanInfo ban : server->db_manager->getBanInfo(lookup_type, id)) {
- QString banned_until;
- if (ban.duration == -2)
- banned_until = "The heat death of the universe";
- else
- banned_until = QDateTime::fromSecsSinceEpoch(ban.time).addSecs(ban.duration).toString("dd.MM.yyyy, hh:mm");
- ban_info << "Affected IPID: " + ban.ipid;
- ban_info << "Affected HDID: " + ban.hdid;
- ban_info << "Reason for ban: " + ban.reason;
- ban_info << "Date of ban: " + QDateTime::fromSecsSinceEpoch(ban.time).toString("dd.MM.yyyy, hh:mm");
- ban_info << "Ban lasts until: " + banned_until;
- ban_info << "-----";
- }
- sendServerMessage(ban_info.join("\n"));
-}
-
-void AOClient::cmdTestify(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->test_rec == AreaData::TestimonyRecording::RECORDING) {
- sendServerMessage("Testimony recording is already in progress. Please stop it before starting a new one.");
- }
- else {
- clearTestimony();
- area->statement = 0;
- area->test_rec = AreaData::TestimonyRecording::RECORDING;
- sendServerMessage("Started testimony recording.");
- }
-}
-
-void AOClient::cmdExamine(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- if (area->testimony.size() -1 > 0)
- {
- area->test_rec = AreaData::TestimonyRecording::PLAYBACK;
- server->broadcast(AOPacket("RT",{"testimony2"}), current_area);
- server->broadcast(AOPacket("MS", {area->testimony[0]}), current_area);
- area->statement = 0;
- return;
- }
- if (area->test_rec == AreaData::TestimonyRecording::PLAYBACK)
- sendServerMessage("Unable to examine while another examination is running");
- else
- sendServerMessage("Unable to start replay without prior examination.");
-}
-
-void AOClient::cmdDeleteStatement(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- int c_statement = area->statement;
- if (area->testimony.size() - 1 == 0) {
- sendServerMessage("Unable to delete statement. No statements saved in this area.");
- }
- if (c_statement > 0 && area->testimony.size() > 2) {
- area->testimony.remove(c_statement);
- sendServerMessage("The statement with id " + QString::number(c_statement) + " has been deleted from the testimony.");
- }
-}
-
-void AOClient::cmdUpdateStatement(int argc, QStringList argv)
-{
- server->areas[current_area]->test_rec = AreaData::TestimonyRecording::UPDATE;
- sendServerMessage("The next IC-Message will replace the last displayed replay message.");
-}
-
-void AOClient::cmdPauseTestimony(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- area->test_rec = AreaData::TestimonyRecording::STOPPED;
- sendServerMessage("Testimony has been stopped.");
-}
-
-void AOClient::cmdAddStatement(int argc, QStringList argv)
-{
- if (server->areas[current_area]->statement < server->maximum_statements) {
- server->areas[current_area]->test_rec = AreaData::TestimonyRecording::ADD;
- sendServerMessage("The next IC-Message will be inserted into the testimony.");
- }
- else
- sendServerMessage("Unable to add anymore statements. Please remove any unused ones.");
-}
-
-void AOClient::cmdReload(int argc, QStringList argv)
-{
- server->loadServerConfig();
- server->loadCommandConfig();
- emit server->reloadRequest(server->server_name, server->server_desc);
- sendServerMessage("Reloaded configurations");
-}
-
-void AOClient::cmdDisemvowel(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (target->is_disemvoweled)
- sendServerMessage("That player is already disemvoweled!");
- else {
- sendServerMessage("Disemvoweled player.");
- target->sendServerMessage("You have been disemvoweled! " + getReprimand());
- }
- target->is_disemvoweled = true;
-}
-
-void AOClient::cmdUnDisemvowel(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (!(target->is_disemvoweled))
- sendServerMessage("That player is not disemvoweled!");
- else {
- sendServerMessage("Undisemvoweled player.");
- target->sendServerMessage("A moderator has undisemvoweled you! " + getReprimand(true));
- }
- target->is_disemvoweled = false;
-}
-
-void AOClient::cmdShake(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (target->is_shaken)
- sendServerMessage("That player is already shaken!");
- else {
- sendServerMessage("Shook player.");
- target->sendServerMessage("A moderator has shaken your words! " + getReprimand());
- }
- target->is_shaken = true;
-}
-
-void AOClient::cmdUnShake(int argc, QStringList argv)
-{
- bool conv_ok = false;
- int uid = argv[0].toInt(&conv_ok);
- if (!conv_ok) {
- sendServerMessage("Invalid user ID.");
- return;
- }
-
- AOClient* target = server->getClientByID(uid);
-
- if (!(target->is_shaken))
- sendServerMessage("That player is not shaken!");
- else {
- sendServerMessage("Unshook player.");
- target->sendServerMessage("A moderator has unshook you! " + getReprimand(true));
- }
- target->is_shaken = false;
-}
-
-void AOClient::cmdForceImmediate(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- area->force_immediate = !area->force_immediate;
- QString state = area->force_immediate ? "on." : "off.";
- sendServerMessage("Forced immediate text processing in this area is now " + state);
-}
-
-void AOClient::cmdAllowIniswap(int argc, QStringList argv)
-{
- AreaData* area = server->areas[current_area];
- area->iniswap_allowed = !area->iniswap_allowed;
- QString state = area->iniswap_allowed ? "allowed." : "disallowed.";
- sendServerMessage("Iniswapping in this area is now " + state);
-}
-
-void AOClient::cmdAfk(int argc, QStringList argv)
-{
- is_afk = true;
- sendServerMessage("You are now AFK.");
-}
-
-QStringList AOClient::buildAreaList(int area_idx)
-{
- QStringList entries;
- QString area_name = server->area_names[area_idx];
- AreaData* area = server->areas[area_idx];
- entries.append("=== " + area_name + " ===");
- switch (area->locked) {
- case AreaData::LockStatus::LOCKED:
- entries.append("[LOCKED]");
- break;
- case AreaData::LockStatus::SPECTATABLE:
- entries.append("[SPECTATABLE]");
- break;
- case AreaData::LockStatus::FREE:
- default:
- break;
- }
- entries.append("[" + QString::number(area->player_count) + " users][" + QVariant::fromValue(area->status).toString().replace("_", "-") + "]");
- for (AOClient* client : server->clients) {
- if (client->current_area == area_idx && client->joined) {
- QString char_entry = "[" + QString::number(client->id) + "] " + client->current_char;
- if (client->current_char == "")
- char_entry += "Spectator";
- if (area->owners.contains(client->id))
- char_entry.insert(0, "[CM] ");
- if (authenticated)
- char_entry += " (" + client->getIpid() + "): " + client->ooc_name;
- if (client->is_afk)
- char_entry += " [AFK]";
- entries.append(char_entry);
- }
- }
- return entries;
-}
-
-int AOClient::genRand(int min, int max)
-{
-#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
- qsrand(QDateTime::currentMSecsSinceEpoch());
- quint32 random_number = (qrand() % (max - min + 1)) + min;
- return random_number;
-
-#else
- quint32 random_number = QRandomGenerator::system()->bounded(min, max + 1);
- return random_number;
-#endif
-}
-
-void AOClient::diceThrower(int argc, QStringList argv, RollType type)
-{
- QString sender_name = ooc_name;
- int max_value = server->dice_value;
- int max_dice = server->max_dice;
- int bounded_value;
- int bounded_amount;
- QString dice_results;
-
- if (argc == 0) {
- dice_results = QString::number(genRand(1, 6)); // Self-explanatory
- }
- else if (argc == 1) {
- bounded_value = qBound(1, argv[0].toInt(), max_value); // faces, max faces
- dice_results = QString::number(genRand(1, bounded_value));
- }
- else if (argc == 2) {
- bounded_value = qBound(1, argv[0].toInt(), max_value); // 1, faces, max faces
- bounded_amount = qBound(1, argv[1].toInt(), max_dice); // 1, amount, max amount
-
- for (int i = 1; i <= bounded_amount ; i++) // Loop as multiple dices are thrown
- {
- QString dice_result = QString::number(genRand(1, bounded_value));
- if (i == bounded_amount) {
- dice_results = dice_results.append(dice_result);
- }
- else {
- dice_results = dice_results.append(dice_result + ",");
- }
- }
- }
- // Switch to change message behaviour, isEmpty check or the entire server crashes due to an out of range issue in the QStringList
- switch(type)
- {
- case ROLL:
- if (argv.isEmpty()) {
- sendServerMessageArea(sender_name + " rolled " + dice_results + " out of 6");
- }
- else {
- sendServerMessageArea(sender_name + " rolled " + dice_results + " out of " + QString::number(bounded_value));
- }
- break;
- case ROLLP:
- if (argv.isEmpty()) {
- sendServerMessage(sender_name + " rolled " + dice_results + " out of 6");
- sendServerMessageArea((sender_name + " rolled in secret."));
- }
- else {
- sendServerMessageArea(sender_name + " rolled " + dice_results + " out of " + QString::number(bounded_value));
- sendServerMessageArea((sender_name + " rolled in secret."));
- }
- break;
- case ROLLA:
- //Not implemented yet
- default : break;
- }
-}
-
-QString AOClient::getAreaTimer(int area_idx, int timer_idx)
-{
- AreaData* area = server->areas[area_idx];
- QTimer* timer;
- QString timer_name = (timer_idx == 0) ? "Global timer" : "Timer " + QString::number(timer_idx);
-
- if (timer_idx == 0)
- timer = server->timer;
- else if (timer_idx > 0 && timer_idx <= 4)
- timer = area->timers[timer_idx - 1];
- else
- return "Invalid timer ID.";
-
- if (timer->isActive()) {
- QTime current_time = QTime(0,0).addMSecs(timer->remainingTime());
-
- return timer_name + " is at " + current_time.toString("hh:mm:ss.zzz");
- }
- else {
- return timer_name + " is inactive.";
- }
-}
-
-long long AOClient::parseTime(QString input)
-{
- QRegularExpression regex("(?:(?:(?.*?)y)*(?:(?.*?)w)*(?:(?.*?)d)*(?:(?
.*?)h)*(?:(?.*?)m)*(?:(?.*?)s)*)");
- QRegularExpressionMatch match = regex.match(input);
- QString str_year, str_week, str_hour, str_day, str_minute, str_second;
- int year, week, day, hour, minute, second;
-
- str_year = match.captured("year");
- str_week = match.captured("week");
- str_day = match.captured("day");
- str_hour = match.captured("hr");
- str_minute = match.captured("min");
- str_second = match.captured("sec");
-
- bool is_well_formed = false;
- QString concat_str(str_year + str_week + str_day + str_hour + str_minute + str_second);
- concat_str.toInt(&is_well_formed);
-
- if (!is_well_formed) {
- return -1;
- }
-
- year = str_year.toInt();
- week = str_week.toInt();
- day = str_day.toInt();
- hour = str_hour.toInt();
- minute = str_minute.toInt();
- second = str_second.toInt();
-
- long long total = 0;
- total += 31622400 * year;
- total += 604800 * week;
- total += 86400 * day;
- total += 3600 * hour;
- total += 60 * minute;
- total += second;
-
- if (total < 0)
- return -1;
-
- return total;
-}
-
-QString AOClient::getReprimand(bool positive)
-{
- if (positive) {
- return server->praise_list[genRand(0, server->praise_list.size() - 1)];
- }
- else {
- return server->reprimands_list[genRand(0, server->reprimands_list.size() - 1)];
- }
-}
diff --git a/src/commands/area.cpp b/src/commands/area.cpp
index d471ef6..f81c618 100644
--- a/src/commands/area.cpp
+++ b/src/commands/area.cpp
@@ -283,3 +283,9 @@ void AOClient::cmdJudgeLog(int argc, QStringList argv)
sendServerMessage(filteredmessage);
}
}
+
+void AOClient::cmdAfk(int argc, QStringList argv)
+{
+ is_afk = true;
+ sendServerMessage("You are now AFK.");
+}
diff --git a/src/commands/command_helper.cpp b/src/commands/command_helper.cpp
index 908f82b..f295037 100644
--- a/src/commands/command_helper.cpp
+++ b/src/commands/command_helper.cpp
@@ -53,6 +53,8 @@ QStringList AOClient::buildAreaList(int area_idx)
char_entry.insert(0, "[CM] ");
if (authenticated)
char_entry += " (" + client->getIpid() + "): " + client->ooc_name;
+ if (client->is_afk)
+ char_entry += " [AFK]";
entries.append(char_entry);
}
}
diff --git a/src/commands/moderation.cpp b/src/commands/moderation.cpp
index 09e8b66..88cd784 100644
--- a/src/commands/moderation.cpp
+++ b/src/commands/moderation.cpp
@@ -328,7 +328,7 @@ void AOClient::cmdUnBlockWtce(int argc, QStringList argv)
target->is_wtce_blocked = false;
}
-void AOClient::cmdAllow_Blankposting(int argc, QStringList argv)
+void AOClient::cmdAllowBlankposting(int argc, QStringList argv)
{
QString sender_name = ooc_name;
AreaData* area = server->areas[current_area];
@@ -387,3 +387,18 @@ void AOClient::cmdReload(int argc, QStringList argv)
sendServerMessage("Reloaded configurations");
}
+void AOClient::cmdForceImmediate(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ area->force_immediate = !area->force_immediate;
+ QString state = area->force_immediate ? "on." : "off.";
+ sendServerMessage("Forced immediate text processing in this area is now " + state);
+}
+
+void AOClient::cmdAllowIniswap(int argc, QStringList argv)
+{
+ AreaData* area = server->areas[current_area];
+ area->iniswap_allowed = !area->iniswap_allowed;
+ QString state = area->iniswap_allowed ? "allowed." : "disallowed.";
+ sendServerMessage("Iniswapping in this area is now " + state);
+}