Privatization rework (#2)

* Add clang-format

* Multiple privatization changes

"Participation handshake" this refers to the moment that the user's client sends the `askchaa` packet.

* Server::m_clients is now private. Get a copy with Server::getClients()
* Server::m_player_count is now private. Get a copy with Server::getPlayerCount() (Additional logic was added to handle the player count.)
* AOClient::m_joined is now private. Get a copy with AOClient::hasJoined()
* Added signal AOClient::joined(); will be emitted when the client first complete the participation handshake.
* Renamed Server::updatePlayerCount to Server::playerCountUpdated

* Privatized Server

* Made Server members private: m_characters, m_areas, m_area_names
* Added Server methods: getCharacters(), getAreas(), getAreaById(f_area_id), getAreaByName(f_area_name), getAreaNames(), getAreaName(f_area_id), getMusicList
* Added Server helper methods: getCharacterCount(), getAreaCount()
- This reduce code repetition of the following example: server->getCharacters().length(), server->getAreas().size()

* Solved other merge conflicts

* Added Server methods, various fixes

* Added Server methods: getCharacterById(f_chr_id)
* Various optimizations

* More Server privatization changes

* Made Server members private: db_manager, next_message_timer, can_send_ic_messages
* Renamed Server members:
  * next_message_timer -> m_message_floodguard_timer
  * can_send_ic_message -> m_can_send_ic_message
Added Server methods: getDatabaseManager, isMessageAllowed, startMessageFloodguard(f_duration)
Made Server methods private: allowMessage

* Added new fields to load for AreaData

* Added fields: `area_message` (default: empty string) and `send_area_message_on_join` (default: false)

* Added Server::clearAreaMessage

* Cleaned up headers include (AOPacket excluded)

* Removed most project file includes, moved to source file (cpp)
  * AOPacket was excluded because some methods modify the copy

* Fix compile error when using MingW compiler

* Appease clang by using proper or and putting it in parentheses
* Remove extra semicolon
This commit is contained in:
Leifa♥ 2022-04-25 21:54:15 +02:00 committed by Rosemary Witchaven
parent 2e7ad02bc3
commit b0555207d6
44 changed files with 2045 additions and 1675 deletions

21
.clang-format Normal file
View File

@ -0,0 +1,21 @@
AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
BreakBeforeBraces: Custom
BreakConstructorInitializers: AfterColon
BraceWrapping:
AfterCaseLabel: true
AfterClass: true
AfterEnum: true
AfterFunction: true
AfterStruct: true
AfterExternBlock: true
BeforeElse: true
SplitEmptyFunction: false
ColumnLimit: 0
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: Always
FixNamespaceComments: false
IndentWidth: 4
PackConstructorInitializers: CurrentLine

View File

@ -15,21 +15,22 @@
// You should have received a copy of the GNU Affero General Public License //
// along with this program. If not, see <https://www.gnu.org/licenses/>. //
//////////////////////////////////////////////////////////////////////////////////////
#include <include/server.h>
#include <include/config_manager.h>
#include <include/server.h>
#include <cstdlib>
#include <QCoreApplication>
#include <QDebug>
Server* server;
Server *server;
void cleanup() {
void cleanup()
{
server->deleteLater();
}
int main(int argc, char* argv[])
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QCoreApplication::setApplicationName("akashi");

View File

@ -58,6 +58,7 @@ HEADERS += include/aoclient.h \
include/db_manager.h \
include/discord.h \
include/server.h \
include/typedefs.h \
include/ws_client.h \
include/ws_proxy.h \
include/advertiser.h \

View File

@ -18,9 +18,8 @@
#ifndef ADVERTISER_H
#define ADVERTISER_H
#include <QtNetwork>
#include <QObject>
#include "include/config_manager.h"
#include <QtNetwork>
/**
* @brief Represents the advertiser of the server. Sends current server information to masterserver.
@ -28,19 +27,19 @@
class Advertiser : public QObject
{
Q_OBJECT
public:
public:
/**
* @brief Constructor for the HTTP_Advertiser class.
*/
explicit Advertiser();
/**
* @brief Deconstructor for the HTTP_Advertiser class. Yes, that's it. Can't say more about it.
*/
~Advertiser();
public slots:
public slots:
/**
* @brief Establishes a connection with masterserver to register or update the listing on the masterserver.
@ -63,12 +62,11 @@ public slots:
*/
void updateAdvertiserSettings();
private:
private:
/**
* @brief Pointer to the network manager, necessary to execute POST requests to the masterserver.
*/
QNetworkAccessManager* m_manager;
QNetworkAccessManager *m_manager;
/**
* @brief Name of the server send to the masterserver. Changing this will change the display name in the serverlist

File diff suppressed because it is too large Load Diff

View File

@ -29,7 +29,8 @@
* @see https://github.com/AttorneyOnline/docs/blob/master/docs/development/network.md for a general explanation
* on Attorney Online 2's network protocol.
*/
class AOPacket {
class AOPacket
{
public:
/**
* @brief Creates an AOPacket with the given header and contents.

View File

@ -18,25 +18,27 @@
#ifndef AREA_DATA_H
#define AREA_DATA_H
#include "aopacket.h"
#include "config_manager.h"
#include "music_manager.h"
#include <QMap>
#include <QString>
#include <QSettings>
#include <QDebug>
#include <QTimer>
#include <QElapsedTimer>
#include <QMap>
#include <QRandomGenerator>
#include <QSettings>
#include <QString>
#include <QTimer>
#include "include/aopacket.h"
class ConfigManager;
class Logger;
class MusicManager;
/**
* @brief Represents an area on the server, a distinct "room" for people to chat in.
*/
class AreaData : public QObject {
Q_OBJECT
class AreaData : public QObject
{
Q_OBJECT
public:
/**
* @brief Constructor for the AreaData class.
@ -45,15 +47,16 @@ class AreaData : public QObject {
* and `YYYYYY` is the actual name of the area.
* @param p_index The index of the area in the area list.
*/
AreaData(QString p_name, int p_index, MusicManager* p_music_manager);
AreaData(QString p_name, int p_index, MusicManager *p_music_manager);
/**
* @brief The data for evidence in the area.
*/
struct Evidence {
QString name; //!< The name of the evidence, shown when hovered over clientside.
struct Evidence
{
QString name; //!< The name of the evidence, shown when hovered over clientside.
QString description; //!< The longer description of the evidence, when the user opens the evidence window.
QString image; //!< A path originating from `base/evidence/` that points to an image file.
QString image; //!< A path originating from `base/evidence/` that points to an image file.
};
/**
@ -62,13 +65,14 @@ class AreaData : public QObject {
* @details This is purely aesthetic, and serves no functional purpose from a gameplay perspective.
* It's only benefit is giving the users a rough idea as to what is going on in an area.
*/
enum Status {
IDLE, //!< The area is currently not busy with anything, or the area is empty.
RP, //!< There is some (non-Ace Attorney-related) roleplay going on in the area.
CASING, //!< An Ace Attorney or Danganronpa-styled case is currently being held in the area.
LOOKING_FOR_PLAYERS, //!< Something is being planned in the area, but it needs more players.
RECESS, //!< The area is currently taking a break from casing, but will continue later.
GAMING //!< The users inside the area are playing some game outside of AO, and are using the area to communicate.
enum Status
{
IDLE, //!< The area is currently not busy with anything, or the area is empty.
RP, //!< There is some (non-Ace Attorney-related) roleplay going on in the area.
CASING, //!< An Ace Attorney or Danganronpa-styled case is currently being held in the area.
LOOKING_FOR_PLAYERS, //!< Something is being planned in the area, but it needs more players.
RECESS, //!< The area is currently taking a break from casing, but will continue later.
GAMING //!< The users inside the area are playing some game outside of AO, and are using the area to communicate.
};
/// Exposes the metadata of the Status enum.
@ -77,10 +81,11 @@ class AreaData : public QObject {
/**
* @brief Determines who may traverse and communicate in the area.
*/
enum LockStatus {
FREE,
LOCKED,
SPECTATABLE
enum LockStatus
{
FREE,
LOCKED,
SPECTATABLE
};
/**
@ -110,7 +115,8 @@ class AreaData : public QObject {
/**
* @brief The level of "authorisation" needed to be able to modify, add, and remove evidence in the area.
*/
enum class EvidenceMod{
enum class EvidenceMod
{
FFA,
MOD,
CM,
@ -144,7 +150,8 @@ class AreaData : public QObject {
/**
* @brief The five "states" the testimony recording system can have in an area.
*/
enum TestimonyRecording{
enum TestimonyRecording
{
STOPPED,
RECORDING,
UPDATE,
@ -190,17 +197,19 @@ class AreaData : public QObject {
* @brief Determines how the testimony progressed after advancement was called in a direction
* (Either to next or previous statement).
*/
enum class TestimonyProgress {
OK, //!< The expected statement was selected.
LOOPED, //!< The "next" statement would have been beyond the testimony's limits, so the first one was selected.
enum class TestimonyProgress
{
OK, //!< The expected statement was selected.
LOOPED, //!< The "next" statement would have been beyond the testimony's limits, so the first one was selected.
STAYED_AT_FIRST, //!< The "previous" statement would have been before the first, so the selection stayed at the first.
};
/**
* @brief Determines a side. Self-explanatory.
*/
enum class Side {
DEFENCE, //!< Self-explanatory.
enum class Side
{
DEFENCE, //!< Self-explanatory.
PROSECUTOR, //!< Self-explanatory.
};
@ -411,7 +420,7 @@ class AreaData : public QObject {
*
* @param f_evi_r The evidence to append.
*/
void appendEvidence(const Evidence& f_evi_r);
void appendEvidence(const Evidence &f_evi_r);
/**
* @brief Deletes a piece of evidence from the list of evidence.
@ -426,7 +435,7 @@ class AreaData : public QObject {
* @param f_eviId The ID of the evidence to replace.
* @param f_newEvi_r The new piece of evidence that will replace the aforementioned one.
*/
void replaceEvidence(int f_eviId, const Evidence& f_newEvi_r);
void replaceEvidence(int f_eviId, const Evidence &f_newEvi_r);
/**
* @brief Returns the status of the area.
@ -444,7 +453,7 @@ class AreaData : public QObject {
*
* @see #map_statuses
*/
bool changeStatus(const QString& f_newStatus_r);
bool changeStatus(const QString &f_newStatus_r);
/**
* @brief Returns a copy of the list of invited clients.
@ -546,7 +555,7 @@ class AreaData : public QObject {
*
* @see #m_document
*/
void changeDoc(const QString& f_newDoc_r);
void changeDoc(const QString &f_newDoc_r);
/**
* @brief Returns the message of the area.
@ -569,7 +578,12 @@ class AreaData : public QObject {
*
* @param f_newMessage_r The new message.
*/
void changeAreaMessage(const QString& f_newMessage_r);
void changeAreaMessage(const QString &f_newMessage_r);
/**
* @brief Clear the area message in the area.
*/
void clearAreaMessage();
/**
* @brief Returns the value of the Confidence bar for the defence's side.
@ -632,7 +646,7 @@ class AreaData : public QObject {
*
* @see #m_musicPlayedBy
*/
void setMusicPlayedBy(const QString& f_music_player);
void setMusicPlayedBy(const QString &f_music_player);
/**
* @brief Changes the music being played in the area.
@ -640,7 +654,7 @@ class AreaData : public QObject {
* @param f_source_r The showname of the client who initiated the music change.
* @param f_newSong_r The name of the new song that is going to be played in the area.
*/
void changeMusic(const QString& f_source_r, const QString& f_newSong_r);
void changeMusic(const QString &f_source_r, const QString &f_newSong_r);
/**
* @brief Returns the evidence mod in the area.
@ -666,7 +680,7 @@ class AreaData : public QObject {
*
* @return True if the notecard didn't replace a previous one, false if it did.
*/
bool addNotecard(const QString& f_owner_r, const QString& f_notecard_r);
bool addNotecard(const QString &f_owner_r, const QString &f_notecard_r);
/**
* @brief Returns the list of notecards recorded in the area.
@ -708,7 +722,7 @@ class AreaData : public QObject {
*
* @note Unlike most other getters, this one returns a reference, as it is expected to be used frequently.
*/
const QVector<QStringList>& testimony() const;
const QVector<QStringList> &testimony() const;
/**
* @brief Returns the index of the currently examined statement in the testimony.
@ -722,7 +736,7 @@ class AreaData : public QObject {
*
* @param f_newStatement_r The IC message packet to append to the testimony vector.
*/
void recordStatement(const QStringList& f_newStatement_r);
void recordStatement(const QStringList &f_newStatement_r);
/**
* @brief Adds a statement into the testimony to a given position.
@ -730,7 +744,7 @@ class AreaData : public QObject {
* @param f_position The index to insert the statement to.
* @param f_newStatement_r The IC message packet to insert.
*/
void addStatement(int f_position, const QStringList& f_newStatement_r);
void addStatement(int f_position, const QStringList &f_newStatement_r);
/**
* @brief Replaces an already existing statement in the testimony in a given position with a new one.
@ -738,7 +752,7 @@ class AreaData : public QObject {
* @param f_position The index of the statement to replace.
* @param f_newStatement_r The IC message packet to insert in the old one's stead.
*/
void replaceStatement(int f_position, const QStringList& f_newStatement_r);
void replaceStatement(int f_position, const QStringList &f_newStatement_r);
/**
* @brief Removes a statement from the testimony at a given position, and moves the statement index one backward.
@ -780,21 +794,21 @@ class AreaData : public QObject {
*
* @param f_newLog_r The new line to append to the judgelog.
*/
void appendJudgelog(const QString& f_newLog_r);
void appendJudgelog(const QString &f_newLog_r);
/**
* @brief Returns the last IC message sent in the area.
*
* @return See short description.
*/
const QStringList& lastICMessage() const;
const QStringList &lastICMessage() const;
/**
* @brief Updates the last IC message sent in the area.
*
* @param f_lastMessage_r The new last IC message.
*/
void updateLastICMessage(const QStringList& f_lastMessage_r);
void updateLastICMessage(const QStringList &f_lastMessage_r);
/**
* @brief Returns whether ~~non-interrupting~~ immediate messages are forced in the area.
@ -856,7 +870,7 @@ class AreaData : public QObject {
*/
QVector<int> joinedIDs() const;
public slots:
public slots:
/**
* @brief Plays a random song from the jukebox. Plays the same if only one is left.
@ -891,11 +905,11 @@ public slots:
*/
void userJoinedArea(int f_area_index, int f_user_id);
private:
private:
/**
* @brief The list of timers available in the area.
*/
QList<QTimer*> m_timers;
QList<QTimer *> m_timers;
/**
* @brief The user-facing and internal name of the area.
@ -910,7 +924,7 @@ private:
/**
* @brief Pointer to the global music manager.
*/
MusicManager* m_music_manager;
MusicManager *m_music_manager;
/**
* @brief A list of the character IDs of all characters taken.
@ -1036,7 +1050,7 @@ private:
/**
* @brief A pointer to a Logger, used to send requests to log data.
*/
Logger* m_logger;
Logger *m_logger;
/**
* @brief The evidence mod of the area.
@ -1061,15 +1075,14 @@ private:
*/
TestimonyRecording m_testimonyRecording;
QVector<QStringList> m_testimony; //!< Vector of all statements saved. Index 0 is always the title of the testimony.
int m_statement; //!< Keeps track of the currently played statement.
int m_statement; //!< Keeps track of the currently played statement.
/**
* @brief The judgelog of an area.
*
* @details This list contains up to 10 recorded packets of the most recent judge actions (WT/CE or penalty updates) in an area.
*/
* @brief The judgelog of an area.
*
* @details This list contains up to 10 recorded packets of the most recent judge actions (WT/CE or penalty updates) in an area.
*/
QStringList m_judgelog;
/**
@ -1077,7 +1090,6 @@ private:
*/
QStringList m_lastICMessage;
/**
* @brief Whether or not to force immediate text processing in this area.
*/
@ -1118,7 +1130,7 @@ private:
* @details While this may be considered bad design, I do not care.
* It triggers a direct broadcast of the MC packet in the area.
*/
QTimer* m_jukebox_timer;
QTimer *m_jukebox_timer;
/**
* @brief Wether or not the jukebox is enabled in this area.

View File

@ -20,29 +20,29 @@
#define CONFIG_VERSION 1
#include "data_types.h"
#include <QDebug>
#include <QDir>
#include <QElapsedTimer>
#include <QFile>
#include <QFileInfo>
#include <QHostAddress>
#include <QMetaEnum>
#include <QSettings>
#include <QUrl>
#include <QMetaEnum>
#include <QElapsedTimer>
#include <QHostAddress>
//JSON loading requirements
// JSON loading requirements
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
typedef QMap<QString,QPair<QString,int>> MusicList;
#include "include/data_types.h"
#include "include/typedefs.h"
/**
* @brief The config file handler class.
*/
class ConfigManager {
class ConfigManager
{
public:
/**
@ -99,7 +99,7 @@ class ConfigManager {
*
* @return See short description.
*/
static QSettings* areaData();
static QSettings *areaData();
/**
* @brief Returns a sanitized QStringList of the areas.
@ -289,7 +289,7 @@ class ConfigManager {
* @return See short description.
*/
static bool discordBanWebhookEnabled();
/**
* @brief Returns the Discord Ban Webhook URL.
*
@ -309,7 +309,7 @@ class ConfigManager {
/**
* @brief Returns the Discord Uptime Webhook URL.
*
*
* @return See short description.
*/
static QString discordUptimeWebhookUrl();
@ -451,7 +451,8 @@ class ConfigManager {
* @brief A struct that contains the help information for a command.
* It's split in the syntax and the explanation text.
*/
struct help {
struct help
{
QString usage;
QString text;
};
@ -482,8 +483,7 @@ class ConfigManager {
*/
static void reloadSettings();
private:
private:
/**
* @brief Checks if a file exists and is valid.
*
@ -491,7 +491,7 @@ private:
*
* @return True if the file exists and is valid, false otherwise.
*/
static bool fileExists(const QFileInfo& file);
static bool fileExists(const QFileInfo &file);
/**
* @brief Checks if a directory exists and is valid.
@ -500,63 +500,64 @@ private:
*
* @return True if the directory exists and is valid, false otherwise.
*/
static bool dirExists(const QFileInfo& dir);
static bool dirExists(const QFileInfo &dir);
/**
* @brief A struct for storing QStringLists loaded from command configuration files.
*/
struct CommandSettings {
struct CommandSettings
{
QStringList magic_8ball; //!< Contains answers for /8ball, found in config/text/8ball.txt
QStringList praises; //!< Contains command praises, found in config/text/praises.txt
QStringList reprimands; //!< Contains command reprimands, found in config/text/reprimands.txt
QStringList gimps; //!< Contains phrases for /gimp, found in config/text/gimp.txt
QStringList cdns; // !< Contains domains for custom song validation, found in config/text/cdns.txt
QStringList praises; //!< Contains command praises, found in config/text/praises.txt
QStringList reprimands; //!< Contains command reprimands, found in config/text/reprimands.txt
QStringList gimps; //!< Contains phrases for /gimp, found in config/text/gimp.txt
QStringList cdns; // !< Contains domains for custom song validation, found in config/text/cdns.txt
};
/**
* @brief Contains the settings required for various commands.
*/
static CommandSettings* m_commands;
static CommandSettings *m_commands;
/**
* @brief Stores all server configuration values.
*/
static QSettings* m_settings;
static QSettings *m_settings;
/**
* @brief Stores all discord webhook configuration values.
*/
static QSettings* m_discord;
static QSettings *m_discord;
/**
* @brief Stores all of the area valus.
*/
static QSettings* m_areas;
static QSettings *m_areas;
/**
* @brief Stores all adjustable logstrings.
*/
static QSettings* m_logtext;
static QSettings *m_logtext;
/**
* @brief Pointer to QElapsedTimer to track the uptime of the server.
*/
static QElapsedTimer* m_uptimeTimer;
static QElapsedTimer *m_uptimeTimer;
/**
* @brief Contains the musiclist with time durations.
*/
static MusicList* m_musicList;
static MusicList *m_musicList;
/**
* @brief Contains an ordered list for the musiclist.
*/
static QStringList* m_ordered_list;
static QStringList *m_ordered_list;
/**
* @brief QHash containing the help information for all commands registered to the server.
*/
static QHash<QString,help>* m_commands_help;
static QHash<QString, help> *m_commands_help;
/**
* @brief Returns a stringlist with the contents of a .txt file from config/text/.
@ -566,6 +567,4 @@ private:
static QStringList loadConfigFile(const QString filename);
};
#endif // CONFIG_MANAGER_H

View File

@ -19,6 +19,7 @@
#define DATA_TYPES_H
#include <QDebug>
/**
* @brief A class for handling several custom data types.
*/
@ -26,20 +27,22 @@ class DataTypes
{
Q_GADGET
public:
public:
/**
* @brief Custom type for authorization types.
*/
enum class AuthType {
SIMPLE,
ADVANCED
};
enum class AuthType
{
SIMPLE,
ADVANCED
};
Q_ENUM(AuthType);
/**
* @brief Custom type for logging types.
*/
enum class LogType {
enum class LogType
{
MODCALL,
FULL,
FULLAREA
@ -47,13 +50,15 @@ public:
Q_ENUM(LogType)
};
template<typename T>
T toDataType(const QString& f_string){
template <typename T>
T toDataType(const QString &f_string)
{
return QVariant(f_string).value<T>();
}
template<typename T>
QString fromDataType(const T& f_t){
template <typename T>
QString fromDataType(const T &f_t)
{
return QVariant::fromValue(f_t).toString();
}

View File

@ -21,13 +21,13 @@
#define DB_VERSION 1
#include <QDateTime>
#include <QFileInfo>
#include <QHostAddress>
#include <QMessageAuthenticationCode>
#include <QSqlDatabase>
#include <QSqlDriver>
#include <QSqlError>
#include <QSqlQuery>
#include <QFileInfo>
/**
* @brief A class used to handle database interaction.
@ -39,9 +39,11 @@
* differently than the average user.
* This comes in two forms, when the user's client is banned, and when the user is a moderator.
*/
class DBManager : public QObject {
class DBManager : public QObject
{
Q_OBJECT
public:
public:
/**
* @brief Constructor for the DBManager class.
*
@ -51,8 +53,8 @@ public:
DBManager();
/**
* @brief Destructor for the DBManager class. Closes the underlying database.
*/
* @brief Destructor for the DBManager class. Closes the underlying database.
*/
~DBManager();
/**
@ -95,15 +97,16 @@ public:
/**
* @brief Details about a ban.
*/
struct BanInfo {
QString ipid; //!< The banned user's IPID.
QHostAddress ip; //!< The banned user's IP.
QString hdid; //!< The banned user's hardware ID.
struct BanInfo
{
QString ipid; //!< The banned user's IPID.
QHostAddress ip; //!< The banned user's IP.
QString hdid; //!< The banned user's hardware ID.
unsigned long time; //!< The time the ban was registered.
QString reason; //!< The reason given for the ban by the moderator who registered it.
QString reason; //!< The reason given for the ban by the moderator who registered it.
long long duration; //!< The duration of the ban, in seconds.
int id; //!< The unique ID of the ban.
QString moderator; //!< The moderator who issued the ban.
int id; //!< The unique ID of the ban.
QString moderator; //!< The moderator who issued the ban.
};
/**
@ -250,7 +253,7 @@ public:
*/
bool updatePassword(QString username, QString password);
private:
private:
/**
* @brief The name of the database connection driver.
*/

View File

@ -18,17 +18,19 @@
#ifndef DISCORD_H
#define DISCORD_H
#include <QtNetwork>
#include <QCoreApplication>
#include "config_manager.h"
#include <QtNetwork>
class ConfigManager;
/**
* @brief A class for handling all Discord webhook requests.
*/
class Discord : public QObject {
class Discord : public QObject
{
Q_OBJECT
public:
public:
/**
* @brief Constructor for the Discord object
*
@ -37,13 +39,13 @@ public:
* @param f_webhook_sendfile Whether or not to send a file containing area logs with the webhook POST request.
* @param parent Qt-based parent, passed along to inherited constructor from QObject.
*/
Discord(QObject* parent = nullptr);
Discord(QObject *parent = nullptr);
/**
* @brief Deconstructor for the Discord class.
*
* @details Marks the nam to be deleted later.
*/
* @brief Deconstructor for the Discord class.
*
* @details Marks the nam to be deleted later.
*/
~Discord();
/**
@ -56,8 +58,7 @@ public:
*/
void stopUptimeTimer();
public slots:
public slots:
/**
* @brief Handles a modcall webhook request.
*
@ -66,7 +67,7 @@ public slots:
* @param f_reason The reason for the modcall.
* @param f_buffer The area's log buffer.
*/
void onModcallWebhookRequested(const QString& f_name, const QString& f_area, const QString& f_reason, const QQueue<QString>& f_buffer);
void onModcallWebhookRequested(const QString &f_name, const QString &f_area, const QString &f_reason, const QQueue<QString> &f_buffer);
/**
* @brief Handles a ban webhook request.
@ -76,18 +77,18 @@ public slots:
* @param f_duration The date the ban expires.
* @param f_reason The reason of the ban.
*/
void onBanWebhookRequested(const QString& f_ipid, const QString& f_moderator, const QString& f_duration, const QString& f_reason, const int& f_banID);
void onBanWebhookRequested(const QString &f_ipid, const QString &f_moderator, const QString &f_duration, const QString &f_reason, const int &f_banID);
/**
* @brief Handles a uptime webhook request.
*/
void onUptimeWebhookRequested();
private:
private:
/**
* @brief The QNetworkAccessManager for webhooks.
*/
QNetworkAccessManager* m_nam;
QNetworkAccessManager *m_nam;
/**
* @brief The QNetworkRequest for webhooks.
@ -97,7 +98,7 @@ private:
/**
* @brief Timer to post a message that the server is still alive.
*/
QTimer* m_uptimePostTimer;
QTimer *m_uptimePostTimer;
/**
* @brief Constructs a new JSON document for modcalls.
@ -108,7 +109,7 @@ private:
*
* @return A JSON document for the modcall.
*/
QJsonDocument constructModcallJson(const QString& f_name, const QString& f_area, const QString& f_reason) const;
QJsonDocument constructModcallJson(const QString &f_name, const QString &f_area, const QString &f_reason) const;
/**
* @brief Constructs a new QHttpMultiPart document for log files.
@ -117,29 +118,29 @@ private:
*
* @return A QHttpMultiPart containing the log file.
*/
QHttpMultiPart* constructLogMultipart(const QQueue<QString>& f_buffer) const;
QHttpMultiPart *constructLogMultipart(const QQueue<QString> &f_buffer) const;
private slots:
private slots:
/**
* @brief Handles a network reply from a webhook POST request.
*
* @param f_reply Pointer to the QNetworkReply created by the webhook POST request.
*/
void onReplyFinished(QNetworkReply* f_reply);
void onReplyFinished(QNetworkReply *f_reply);
/**
* @brief Sends a webhook POST request with the given JSON document.
*
* @param f_json The JSON document to send.
*/
void postJsonWebhook(const QJsonDocument& f_json);
void postJsonWebhook(const QJsonDocument &f_json);
/**
* @brief Sends a webhook POST request with the given QHttpMultiPart.
*
* @param f_multipart The QHttpMultiPart to send.
*/
void postMultipartWebhook(QHttpMultiPart& f_multipart);
void postMultipartWebhook(QHttpMultiPart &f_multipart);
/**
* @brief Constructs a new JSON document for bans.
@ -151,15 +152,14 @@ private slots:
*
* @return A JSON document for the ban.
*/
QJsonDocument constructBanJson(const QString& f_ipid, const QString& f_moderator, const QString& f_duration, const QString& f_reason, const int& f_banID);
QJsonDocument constructBanJson(const QString &f_ipid, const QString &f_moderator, const QString &f_duration, const QString &f_reason, const int &f_banID);
/**
* @brief Constructs a new JSON document for the server alive message.
* @param f_timeExpired formatted uptime as a string.
*
* @return A JSON document for the alive notification.
*/
QJsonDocument constructUptimeJson(const QString& f_timeExpired);
QJsonDocument constructUptimeJson(const QString &f_timeExpired);
};
#endif // DISCORD_H

View File

@ -18,13 +18,13 @@
#ifndef U_LOGGER_H
#define U_LOGGER_H
#include <QObject>
#include <QMap>
#include <QQueue>
#include <QDateTime>
#include "include/config_manager.h"
#include "include/logger/writer_full.h"
#include "include/logger/writer_modcall.h"
#include <QDateTime>
#include <QMap>
#include <QObject>
#include <QQueue>
/**
* @brief The Universal Logger class to provide a common place to handle, store and write logs to file.
@ -32,12 +32,13 @@
class ULogger : public QObject
{
Q_OBJECT
public:
public:
/**
* @brief Constructor for the universal logger. Determines which writer is initially created.
* @param Pointer to the Server.
*/
ULogger(QObject* parent = nullptr);
ULogger(QObject *parent = nullptr);
/**
* @brief Deconstructor of the universal logger. Deletes its writer before deconstruction.
@ -50,65 +51,64 @@ public:
*/
QQueue<QString> buffer(const QString &f_areaName);
public slots:
public slots:
/**
* @brief Adds an IC log entry to the area buffer and writes it to the respective log format.
*/
void logIC(const QString& f_char_name, const QString& f_ooc_name, const QString& f_ipid,
const QString& f_area_name, const QString &f_message);
void logIC(const QString &f_char_name, const QString &f_ooc_name, const QString &f_ipid,
const QString &f_area_name, const QString &f_message);
/**
* @brief Adds an OOC log entry to the area buffer and writes it to the respective log format.
*/
void logOOC(const QString& f_char_Name, const QString& f_ooc_name, const QString& f_ipid,
const QString& f_area_name, const QString& f_message);
void logOOC(const QString &f_char_Name, const QString &f_ooc_name, const QString &f_ipid,
const QString &f_area_name, const QString &f_message);
/**
* @brief Adds an login attempt to the area buffer and writes it to the respective log format.
*/
void logLogin(const QString& f_char_name, const QString& f_ooc_name, const QString& f_moderator_name,
const QString& f_ipid, const QString &f_area_name, const bool& f_success);
void logLogin(const QString &f_char_name, const QString &f_ooc_name, const QString &f_moderator_name,
const QString &f_ipid, const QString &f_area_name, const bool &f_success);
/**
* @brief Adds a command usage to the area buffer and writes it to the respective log format.
*/
void logCMD(const QString& f_char_name, const QString &f_ipid, const QString& f_ooc_name, const QString& f_command,
const QStringList& f_args, const QString& f_area_name);
void logCMD(const QString &f_char_name, const QString &f_ipid, const QString &f_ooc_name, const QString &f_command,
const QStringList &f_args, const QString &f_area_name);
/**
* @brief Adds a player kick to the area buffer and writes it to the respective log format.
*/
void logKick(const QString& f_moderator, const QString& f_target_ipid);
void logKick(const QString &f_moderator, const QString &f_target_ipid);
/**
* @brief Adds a player ban to the area buffer and writes it to the respective log format.
*/
void logBan(const QString& f_moderator, const QString& f_target_ipid, const QString &f_duration);
void logBan(const QString &f_moderator, const QString &f_target_ipid, const QString &f_duration);
/**
* @brief Adds a modcall event to the area buffer, also triggers modcall writing.
*/
void logModcall(const QString& f_char_name, const QString &f_ipid, const QString& f_ooc_name, const QString& f_area_name);
void logModcall(const QString &f_char_name, const QString &f_ipid, const QString &f_ooc_name, const QString &f_area_name);
/**
* @brief Logs any connection attempt to the server, wether sucessful or not.
*/
void logConnectionAttempt(const QString& f_ip_address, const QString& f_ipid, const QString& f_hwid);
void logConnectionAttempt(const QString &f_ip_address, const QString &f_ipid, const QString &f_hwid);
/**
* @brief Loads template strings for the logger.
*/
void loadLogtext();
private:
private:
/**
* @brief Updates the area buffer with a new entry, moving old ones if the buffer exceesed the maximum size.
* @param Name of the area which buffer is modified.
* @param Formatted QString to be added into the buffer.
*/
void updateAreaBuffer(const QString& f_areaName, const QString& f_log_entry);
void updateAreaBuffer(const QString &f_areaName, const QString &f_log_entry);
/**
* @brief QMap of all available area buffers.
@ -120,12 +120,12 @@ private:
/**
* @brief Pointer to modcall writer. Handles QQueue delogging into area specific file.
*/
WriterModcall* writerModcall;
WriterModcall *writerModcall;
/**
* @brief Pointer to full writer. Handles single messages in one file.
*/
WriterFull* writerFull;
WriterFull *writerFull;
/**
* @brief Table that contains template strings for text-based logger format.
@ -133,19 +133,18 @@ private:
* This has the problem of lacking defaults that work for all when the file is missing.
* This QMap contains all default values and overwrites them on logger construction.
*/
QHash<QString,QString>m_logtext {
{"ic", "[%1][%5][IC][%2(%3)][%4]%6"},
{"ooc", "[%1][%5][OOC][%2(%3)][%4]%6"},
{"login", "[%1][LOGIN][%2][%3][%4(%5)]"},
{"cmdlogin", "[%1][%2][LOGIN][%5][%3(%4)]"},
QHash<QString, QString> m_logtext{
{"ic", "[%1][%5][IC][%2(%3)][%4]%6"},
{"ooc", "[%1][%5][OOC][%2(%3)][%4]%6"},
{"login", "[%1][LOGIN][%2][%3][%4(%5)]"},
{"cmdlogin", "[%1][%2][LOGIN][%5][%3(%4)]"},
{"cmdrootpass", "[%1][%2][ROOTPASS][%5][%3(%4)]"},
{"cmdadduser", "[%1][%2][USERADD][%6][%3(%4)]%5"},
{"cmd", "[%1][%2][CMD][%7][%3(%4)]/%5 %6"},
{"kick", "[%1][%2][KICK][%3]"},
{"ban", "[%1][%2][BAN][%3][%4]"},
{"modcall", "[%1][%2][MODCALL][%5][%3(%4)]"},
{"connect", "[%1][CONNECT][%2][%3][%4]"}
};
{"cmdadduser", "[%1][%2][USERADD][%6][%3(%4)]%5"},
{"cmd", "[%1][%2][CMD][%7][%3(%4)]/%5 %6"},
{"kick", "[%1][%2][KICK][%3]"},
{"ban", "[%1][%2][BAN][%3][%4]"},
{"modcall", "[%1][%2][MODCALL][%5][%3(%4)]"},
{"connect", "[%1][CONNECT][%2][%3][%4]"}};
};
#endif //U_LOGGER_H
#endif // U_LOGGER_H

View File

@ -17,10 +17,10 @@
//////////////////////////////////////////////////////////////////////////////////////
#ifndef WRITER_FULL_H
#define WRITER_FULL_H
#include <QObject>
#include <QFile>
#include <QDir>
#include <QDateTime>
#include <QDir>
#include <QFile>
#include <QObject>
#include <QTextStream>
/**
@ -29,13 +29,15 @@
class WriterFull : public QObject
{
Q_OBJECT
public:
public:
/**
* @brief Constructor for full logwriter
*
* @param QObject pointer to the parent object.
*/
WriterFull(QObject* parent = nullptr);;
WriterFull(QObject *parent = nullptr);
;
/**
* @brief Deconstructor for full logwriter.
@ -57,7 +59,7 @@ public:
*/
void flush(const QString f_entry, const QString f_area_name);
private:
private:
/**
* @brief Filename of the logfile used. This will always be the time the server starts up.
*/
@ -69,4 +71,4 @@ private:
QDir l_dir;
};
#endif //WRITER_FULL_H
#endif // WRITER_FULL_H

View File

@ -17,13 +17,12 @@
//////////////////////////////////////////////////////////////////////////////////////
#ifndef WRITER_MODCALL_H
#define WRITER_MODCALL_H
#include <QObject>
#include <QFile>
#include <QDir>
#include <QDateTime>
#include <QTextStream>
#include <QDir>
#include <QFile>
#include <QObject>
#include <QQueue>
#include <QTextStream>
/**
* @brief A class to handle file interaction when writing the modcall buffer.
@ -31,13 +30,15 @@
class WriterModcall : public QObject
{
Q_OBJECT
public:
public:
/**
* @brief Constructor for modcall logwriter
*
* @param QObject pointer to the parent object.
*/
WriterModcall(QObject* parent = nullptr);;
WriterModcall(QObject *parent = nullptr);
;
/**
* @brief Deconstructor for modcall logwriter.
@ -53,7 +54,7 @@ public:
*/
void flush(const QString f_area_name, QQueue<QString> f_buffer);
private:
private:
/**
* @brief Filename of the logfile used.
*/
@ -65,4 +66,4 @@ private:
QDir l_dir;
};
#endif //WRITER_MODCALL_H
#endif // WRITER_MODCALL_H

View File

@ -18,26 +18,27 @@
#ifndef MUSIC_MANAGER_H
#define MUSIC_MANAGER_H
#include <QObject>
#include <QMap>
#include <QHash>
#include <QMap>
#include <QObject>
#include <QPair>
#include <include/config_manager.h>
#include <include/aopacket.h>
#include "include/aopacket.h"
#include "include/typedefs.h"
class ConfigManager;
class MusicManager : public QObject
{
Q_OBJECT
public:
public:
/**
* @brief Constructor for the server-wide musiclist manager.
*
* @param Copy of the server musiclist generated by ConfigManager::musiclist();
*/
MusicManager(QObject* parent = nullptr, QStringList f_root_ordered = {}, QStringList f_cdns = {"cdn.discord.com"},
QMap<QString, QPair<QString, int> > f_root_list = ConfigManager::musiclist());
MusicManager(QStringList f_root_ordered, QStringList f_cdns, QMap<QString, QPair<QString, int>> f_root_list, QObject *parent = nullptr);
/**
* @brief Destructor for the server-wide musiclist manager.
@ -146,7 +147,7 @@ public:
*/
bool isCustom(int f_area_id, QString f_song_name);
public slots:
public slots:
/**
* @brief Updates the root musiclist and CDN list.
@ -158,7 +159,7 @@ public slots:
*/
void userJoinedArea(int f_area_index, int f_user_id);
signals:
signals:
/**
* @brief Sends the FM packet with the musiclist of the area when a client enters.
@ -178,12 +179,11 @@ signals:
*/
void sendAreaFMPacket(AOPacket f_packet, int f_area_index);
private:
private:
/**
* @brief Contains all custom lists of all areas in the server.
*/
QHash<int,MusicList>* m_custom_lists;
QHash<int, MusicList> *m_custom_lists;
/**
* @brief Server musiclist shared among all areas.
@ -198,12 +198,12 @@ private:
/**
* @brief Contains all custom songs ordered in a per-area buffer.
*/
QMap<int,QStringList> m_customs_ordered;
QMap<int, QStringList> m_customs_ordered;
/**
* @brief Wether the global musiclist is prepend and validation when adding custom music.
*/
QHash<int,bool> m_global_enabled;
QHash<int, bool> m_global_enabled;
/**
* @brief Contains all server approved content sources.

View File

@ -18,35 +18,34 @@
#ifndef SERVER_H
#define SERVER_H
#include "include/aoclient.h"
#include "include/aopacket.h"
#include "include/area_data.h"
#include "include/ws_proxy.h"
#include "include/db_manager.h"
#include "include/discord.h"
#include "include/config_manager.h"
#include "include/advertiser.h"
#include "include/logger/u_logger.h"
#include "include/music_manager.h"
#include <QCoreApplication>
#include <QDebug>
#include <QFile>
#include <QMap>
#include <QSettings>
#include <QStack>
#include <QString>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTimer>
#include "include/aopacket.h"
class Advertiser;
class AOClient;
class DBManager;
class AreaData;
class ConfigManager;
class DBManager;
class Discord;
class MusicManager;
class ULogger;
class WSProxy;
/**
* @brief The class that represents the actual server as it is.
*/
class Server : public QObject {
class Server : public QObject
{
Q_OBJECT
public:
@ -57,13 +56,13 @@ class Server : public QObject {
* @param p_ws_port The WebSocket port to listen for connections on.
* @param parent Qt-based parent, passed along to inherited constructor from QObject.
*/
Server(int p_port, int p_ws_port, QObject* parent = nullptr);
Server(int p_port, int p_ws_port, QObject *parent = nullptr);
/**
* @brief Destructor for the Server class.
*
* @details Marks every Client, the WSProxy, the underlying #server, and the database manager to be deleted later.
*/
* @brief Destructor for the Server class.
*
* @details Marks every Client, the WSProxy, the underlying #server, and the database manager to be deleted later.
*/
~Server();
/**
@ -79,13 +78,21 @@ class Server : public QObject {
/**
* @brief Enum to specifc different targets to send altered packets to a specific usergroup.
*/
enum class TARGET_TYPE {
enum class TARGET_TYPE
{
AUTHENTICATED,
MODCHAT,
ADVERT
};
Q_ENUM(TARGET_TYPE)
/**
* @brief Returns a list of all clients currently in the server.
*
* @return A list of all clients currently in the server.
*/
QVector<AOClient *> getClients();
/**
* @brief Gets a pointer to a client by IPID.
*
@ -95,7 +102,7 @@ class Server : public QObject {
*
* @see Server::getClientsByIpid() to get all clients ran by the same user.
*/
AOClient* getClient(QString ipid);
AOClient *getClient(QString ipid);
/**
* @brief Gets a list of pointers to all clients with the given IPID.
@ -104,8 +111,8 @@ class Server : public QObject {
*
* @return A list of clients whose IPID match. List may be empty.
*/
QList<AOClient*> getClientsByIpid(QString ipid);
QList<AOClient *> getClientsByIpid(QString ipid);
/**
* @brief Gets a pointer to a client by user ID.
*
@ -113,7 +120,37 @@ class Server : public QObject {
*
* @return A pointer to the client if found, a nullpointer if not.
*/
AOClient* getClientByID(int id);
AOClient *getClientByID(int id);
/**
* @brief Returns the overall player count in the server.
*
* @return The overall player count in the server.
*/
int getPlayerCount();
/**
* @brief Returns a list of the available characters on the server to use.
*
* @return A list of the available characters on the server to use.
*/
QStringList getCharacters();
/**
* @brief Returns the count of available characters on the server to use.
*
* @return The count of available characters on the server to use.
*/
int getCharacterCount();
/**
* @brief Get the available character by index.
*
* @param f_chr_id The index of the character.
*
* @return The character if it exist, otherwise an empty stirng.
*/
QString getCharacterById(int f_chr_id);
/**
* @brief Updates which characters are taken in the given area, and sends out an update packet to
@ -121,7 +158,7 @@ class Server : public QObject {
*
* @param area The area in which to update the list of characters.
*/
void updateCharsTaken(AreaData* area);
void updateCharsTaken(AreaData *area);
/**
* @brief Sends a packet to all clients in a given area.
@ -185,20 +222,229 @@ class Server : public QObject {
**/
bool isIPBanned(QHostAddress f_remote_IP);
/**
* @brief Returns the list of areas in the server.
*
* @return A list of areas.
*/
QVector<AreaData *> getAreas();
/**
* @brief Returns the number of areas in the server.
*/
int getAreaCount();
/**
* @brief Returns a pointer to the area associated with the index.
*
* @param f_area_id The index of the area.
*
* @return A pointer to the area or null.
*/
AreaData *getAreaById(int f_area_id);
/**
* @brief Getter for an area specific buffer from the logger.
*/
QQueue<QString> getAreaBuffer(const QString& f_areaName);
QQueue<QString> getAreaBuffer(const QString &f_areaName);
/**
* @brief The names of the areas on the server.
*
* @return A list of names.
*/
QStringList getAreaNames();
/**
* @brief Returns the name of the area associated with the index.
*
* @param f_area_id The index of the area.
*
* @return The name of the area or empty.
*/
QString getAreaName(int f_area_id);
/**
* @brief Returns the available songs on the server.
*
* @return A list of songs.
*/
QStringList getMusicList();
/**
* @brief Returns the available backgrounds on the server.
*
* @return A list of backgrounds.
*/
QStringList getBackgrounds();
/**
* @brief Returns a pointer to a database manager.
*
* @return A pointer to database manager.
*/
DBManager *getDatabaseManager();
/**
* @brief The server-wide global timer.
*/
QTimer *timer;
QStringList getCursedCharsTaken(AOClient *client, QStringList chars_taken);
/**
* @brief Returns whatever a game message may be broadcasted or not.
*
* @return True if expired; false otherwise.
*/
bool isMessageAllowed();
/**
* @brief Starts a global timer that determines whatever a game message may be broadcasted or not.
*
* @param f_duration The duration of the message floodguard timer.
*/
void startMessageFloodguard(int f_duration);
/**
* @brief Attempts to parse a IPv6 mapped IPv4 to an IPv4.
*/
QHostAddress parseToIPv4(QHostAddress f_remote_ip);
public slots:
/**
* @brief Convenience class to call a reload of available configuraiton elements.
*/
void reloadSettings();
/**
* @brief Handles a new connection.
*
* @details The function creates an AOClient to represent the user, assigns a user ID to them, and
* checks if the client is banned.
*/
void clientConnected();
/**
* @brief Method to construct and reconstruct Discord Webhook Integration.
*
* @details Constructs or rebuilds Discord Object during server startup and configuration reload.
*/
void handleDiscordIntegration();
/**
* @brief Marks a userID as free and ads it back to the available client id queue.
*/
void markIDFree(const int &f_user_id);
signals:
/**
* @brief Sends the server name and description, emitted by /reload.
*
* @param p_name The server name.
* @param p_desc The server description.
*/
void reloadRequest(QString p_name, QString p_desc);
/**
* @brief This signal is emitted whenever the current player count has changed.
*
* @param f_current_player The player count at the time the signal was emitted.
*/
void playerCountUpdated(int f_current_players);
/**
* @brief Triggers a partial update of the modern advertiser as some information, such as ports
* can't be updated while the server is running.
*/
void updateHTTPConfiguration();
/**
* @brief Sends a modcall webhook request, emitted by AOClient::pktModcall.
*
* @param f_name The character or OOC name of the client who sent the modcall.
* @param f_area The name of the area the modcall was sent from.
* @param f_reason The reason the client specified for the modcall.
* @param f_buffer The area's log buffer.
*/
void modcallWebhookRequest(const QString &f_name, const QString &f_area, const QString &f_reason, const QQueue<QString> &f_buffer);
/**
* @brief Sends a ban webhook request, emitted by AOClient::cmdBan
* @param f_ipid The IPID of the banned client.
* @param f_moderator The moderator who issued the ban.
* @param f_duration The duration of the ban in a human readable format.
* @param f_reason The reason for the ban.
* @param f_banID The ID of the issued ban.
*/
void banWebhookRequest(const QString &f_ipid, const QString &f_moderator, const QString &f_duration, const QString &f_reason, const int &f_banID);
/**
* @brief Signal connected to universal logger. Logs a client connection attempt.
* @param f_ip_address The IP Address of the incoming connection.
* @param f_ipid The IPID of the incoming connection.
* @param f_hdid The HDID of the incoming connection.
*/
void logConnectionAttempt(const QString &f_ip_address, const QString &f_ipid, const QString &f_hwid);
private:
/**
* @brief The proxy used for WebSocket connections.
*
* @see WSProxy and WSClient for an explanation as to why this is a thing.
*/
WSProxy *proxy;
/**
* @brief Listens for incoming TCP connections.
*/
QTcpServer *server;
/**
* @brief Handles Discord webhooks.
*/
Discord *discord;
/**
* @brief Handles HTTP server advertising.
*/
Advertiser *ms3_Advertiser;
/**
* @brief Advertises the server in a regular intervall.
*/
QTimer *AdvertiserTimer;
/**
* @brief Handles the universal log framework.
*/
ULogger *logger;
/**
* @brief Handles all musiclists.
*/
MusicManager *music_manager;
/**
* @brief The port through which the server will accept TCP connections.
*/
int port;
/**
* @brief The port through which the server will accept WebSocket connections.
*/
int ws_port;
/**
* @brief The collection of all currently connected clients.
*/
QVector<AOClient*> m_clients;
QVector<AOClient *> m_clients;
/**
* @brief Collection of all clients with their userID as key.
*/
QHash<int,AOClient*> m_clients_ids;
QHash<int, AOClient *> m_clients_ids;
/**
* @brief Stack of all available IDs for clients. When this is empty the server
@ -219,7 +465,7 @@ class Server : public QObject {
/**
* @brief The areas on the server.
*/
QVector<AreaData*> m_areas;
QVector<AreaData *> m_areas;
/**
* @brief The names of the areas on the server.
@ -247,169 +493,43 @@ class Server : public QObject {
*/
QStringList m_ipban_list;
/**
* @brief The database manager on the server, used to store users' bans and authorisation details.
*/
DBManager* db_manager;
/**
* @brief The server-wide global timer.
*/
QTimer* timer;
QStringList getCursedCharsTaken(AOClient* client, QStringList chars_taken);
/**
* @brief Timer until the next IC message can be sent.
*/
QTimer next_message_timer;
/**
* @brief Attempts to parse a IPv6 mapped IPv4 to an IPv4.
*/
QHostAddress parseToIPv4(QHostAddress f_remote_ip);
QTimer *m_message_floodguard_timer;
/**
* @brief If false, IC messages will be rejected.
*/
bool can_send_ic_messages = true;
public slots:
bool m_can_send_ic_messages = true;
/**
* @brief Convenience class to call a reload of available configuraiton elements.
* @brief The database manager on the server, used to store users' bans and authorisation details.
*/
void reloadSettings();
DBManager *db_manager;
/**
* @brief Handles a new connection.
*
* @details The function creates an AOClient to represent the user, assigns a user ID to them, and
* checks if the client is banned.
*/
void clientConnected();
/**
* @brief Sets #can_send_messages to true.
*
* @details Called whenever #next_message_timer reaches 0.
*/
void allowMessage();
/**
* @brief Method to construct and reconstruct Discord Webhook Integration.
*
* @details Constructs or rebuilds Discord Object during server startup and configuration reload.
*/
void handleDiscordIntegration();
/**
* @brief Marks a userID as free and ads it back to the available client id queue.
*/
void markIDFree(const int& f_user_id);
signals:
/**
* @brief Sends the server name and description, emitted by /reload.
*
* @param p_name The server name.
* @param p_desc The server description.
*/
void reloadRequest(QString p_name, QString p_desc);
/**
* @brief Updates the playercount in the modern advertiser.
*/
void updatePlayerCount(int f_current_players);
/**
* @brief Triggers a partial update of the modern advertiser as some information, such as ports
* can't be updated while the server is running.
*/
void updateHTTPConfiguration();
/**
* @brief Sends a modcall webhook request, emitted by AOClient::pktModcall.
*
* @param f_name The character or OOC name of the client who sent the modcall.
* @param f_area The name of the area the modcall was sent from.
* @param f_reason The reason the client specified for the modcall.
* @param f_buffer The area's log buffer.
*/
void modcallWebhookRequest(const QString& f_name, const QString& f_area, const QString& f_reason, const QQueue<QString>& f_buffer);
/**
* @brief Sends a ban webhook request, emitted by AOClient::cmdBan
* @param f_ipid The IPID of the banned client.
* @param f_moderator The moderator who issued the ban.
* @param f_duration The duration of the ban in a human readable format.
* @param f_reason The reason for the ban.
* @param f_banID The ID of the issued ban.
*/
void banWebhookRequest(const QString& f_ipid, const QString& f_moderator, const QString& f_duration, const QString& f_reason, const int& f_banID);
/**
* @brief Signal connected to universal logger. Logs a client connection attempt.
* @param f_ip_address The IP Address of the incoming connection.
* @param f_ipid The IPID of the incoming connection.
* @param f_hdid The HDID of the incoming connection.
*/
void logConnectionAttempt(const QString& f_ip_address, const QString& f_ipid, const QString& f_hwid);
private:
/**
* @brief Connects new AOClient to logger and disconnect handling.
**/
void hookupAOClient(AOClient* client);
void hookupAOClient(AOClient *client);
private slots:
/**
* @brief Increase the current player count by one.
*/
void increasePlayerCount();
/**
* @brief The proxy used for WebSocket connections.
* @brief Decrease the current player count based on the client id provided.
*
* @see WSProxy and WSClient for an explanation as to why this is a thing.
* @param f_client_id The client id of the client to check.
*/
WSProxy* proxy;
void decreasePlayerCount();
/**
* @brief Listens for incoming TCP connections.
* @brief Allow game messages to be broadcasted.
*/
QTcpServer* server;
/**
* @brief Handles Discord webhooks.
*/
Discord* discord;
/**
* @brief Handles HTTP server advertising.
*/
Advertiser* ms3_Advertiser;
/**
* @brief Advertises the server in a regular intervall.
*/
QTimer* AdvertiserTimer;
/**
* @brief Handles the universal log framework.
*/
ULogger* logger;
/**
* @brief Handles all musiclists.
*/
MusicManager* music_manager;
/**
* @brief The port through which the server will accept TCP connections.
*/
int port;
/**
* @brief The port through which the server will accept WebSocket connections.
*/
int ws_port;
void allowMessage();
};
#endif // SERVER_H

7
core/include/typedefs.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#include <QMap>
#include <QPair>
#include <QString>
typedef QMap<QString, QPair<QString, int>> MusicList;

View File

@ -19,9 +19,9 @@
#define WS_CLIENT_H
#include <QObject>
#include <QtWebSockets/QtWebSockets>
#include <QTcpSocket>
#include <QString>
#include <QTcpSocket>
#include <QtWebSockets/QtWebSockets>
/**
* @brief Represents a WebSocket client (generally WebAO) connected to the server.
@ -31,9 +31,11 @@
*
* This class is a very thin layer -- see WSProxy for the actual mechanics of this WebSocket-to-TCP proxy solution.
*/
class WSClient : public QObject {
class WSClient : public QObject
{
Q_OBJECT
public:
public:
/**
* @brief Creates an instance of the WSClient class.
*
@ -44,15 +46,15 @@ public:
* @pre This class will not connect up the ports to each other in any way. Unless some setup is done, this class
* by default will never be prompted to read and/or write from/to either of the sockets.
*/
WSClient(QTcpSocket* p_tcp_socket, QWebSocket* p_web_socket, QObject* parent = nullptr);
WSClient(QTcpSocket *p_tcp_socket, QWebSocket *p_web_socket, QObject *parent = nullptr);
/**
* @brief Destructor for the WSClient class.
*
* @details Marks the TCP and WebSocket for later deletion.
*/
* @brief Destructor for the WSClient class.
*
* @details Marks the TCP and WebSocket for later deletion.
*/
~WSClient();
public slots:
public slots:
/**
* @brief A slot that can be signalled when #tcp_socket has data ready for reading.
* Will read all data in the socket.
@ -92,17 +94,16 @@ public slots:
*/
void onTcpConnect();
private:
private:
/**
* @brief The local TCP socket used as a proxy to connect with the server.
*/
QTcpSocket* tcp_socket;
QTcpSocket *tcp_socket;
/**
* @brief The WebSocket representing an incoming connection.
*/
QWebSocket* web_socket;
QWebSocket *web_socket;
/**
* @brief Stores partial packets in case they don't all come through the TCP socket at once

View File

@ -18,19 +18,21 @@
#ifndef WS_PROXY_H
#define WS_PROXY_H
#include "include/ws_client.h"
#include <QHostAddress>
#include <QMap>
#include <QTcpSocket>
#include <QtWebSockets/QtWebSockets>
#include <QHostAddress>
class WSClient;
/**
* @brief Handles WebSocket connections by redirecting data sent through them through a local TCP connection
* for common handling.
*/
class WSProxy : public QObject {
class WSProxy : public QObject
{
Q_OBJECT
public:
/**
* @brief Creates a WSProxy instance.
@ -40,13 +42,13 @@ class WSProxy : public QObject {
* @param p_ws_port The WebSocket port. Should the same that is opened for WebSockets connections.
* @param parent Qt-based parent, passed along to inherited constructor from QObject.
*/
WSProxy(int p_local_port, int p_ws_port, QObject* parent);
WSProxy(int p_local_port, int p_ws_port, QObject *parent);
/**
* @brief Destructor for the WSProxy class.
*
* @details Marks the WebSocket server that is used to handle the proxy process to be deleted later.
*/
* @brief Destructor for the WSProxy class.
*
* @details Marks the WebSocket server that is used to handle the proxy process to be deleted later.
*/
~WSProxy();
/**
@ -54,7 +56,7 @@ class WSProxy : public QObject {
*/
void start();
public slots:
public slots:
/**
* @brief Sets up the proxy process to the newly connected WebSocket.
*
@ -66,12 +68,12 @@ public slots:
/**
* @brief The WebSocket server listening to incoming WebSocket connections.
*/
QWebSocketServer* server;
QWebSocketServer *server;
/**
* @brief Every client connected through WebSocket.
*/
QVector<WSClient*> clients;
QVector<WSClient *> clients;
/**
* @brief The TCP port that the WebSocket connections will be redirected through.

View File

@ -17,13 +17,14 @@
//////////////////////////////////////////////////////////////////////////////////////
#include "include/advertiser.h"
#include "include/config_manager.h"
Advertiser::Advertiser()
{
m_manager = new QNetworkAccessManager();
connect(m_manager, &QNetworkAccessManager::finished,
this, &Advertiser::msRequestFinished);
m_name = ConfigManager::serverName();
m_hostname = ConfigManager::advertiserHostname();
m_description = ConfigManager::serverDescription();
@ -61,7 +62,7 @@ void Advertiser::msAdvertiseServer()
l_json["name"] = m_name;
if (!m_description.isEmpty()) {
l_json["description"] = m_description;
l_json["description"] = m_description;
}
m_manager->post(request, QJsonDocument(l_json).toJson());
@ -73,7 +74,6 @@ void Advertiser::msAdvertiseServer()
if (m_debug)
qWarning().noquote() << "Unable to advertise. Masterserver URL '" + m_masterserver.toString() + "' is not valid.";
return;
}
void Advertiser::msRequestFinished(QNetworkReply *f_reply)
@ -110,5 +110,3 @@ void Advertiser::updateAdvertiserSettings()
m_masterserver = ConfigManager::advertiserIP();
m_debug = ConfigManager::advertiserDebug();
}

View File

@ -17,6 +17,12 @@
//////////////////////////////////////////////////////////////////////////////////////
#include "include/aoclient.h"
#include "include/aopacket.h"
#include "include/area_data.h"
#include "include/config_manager.h"
#include "include/db_manager.h"
#include "include/server.h"
void AOClient::clientData()
{
if (last_read + m_socket->bytesAvailable() > 30720) { // Client can send a max of 30KB to the server over two sequential reads
@ -53,19 +59,18 @@ void AOClient::clientDisconnected()
qDebug() << remote_ip.toString() << "disconnected";
#endif
if (m_joined) {
server->m_player_count--;
emit server->updatePlayerCount(server->m_player_count);
server->m_areas[m_current_area]->clientLeftArea(server->getCharID(m_current_char), m_id);
server->getAreaById(m_current_area)->clientLeftArea(server->getCharID(m_current_char), m_id);
arup(ARUPType::PLAYER_COUNT, true);
}
if (m_current_char != "") {
server->updateCharsTaken(server->m_areas[m_current_area]);
server->updateCharsTaken(server->getAreaById(m_current_area));
}
bool l_updateLocks = false;
for (AreaData* l_area : qAsConst(server->m_areas)) {
const QVector<AreaData *> l_areas = server->getAreas();
for (AreaData *l_area : l_areas) {
l_updateLocks = l_updateLocks || l_area->removeOwner(m_id);
}
@ -81,7 +86,7 @@ void AOClient::handlePacket(AOPacket packet)
#ifdef NET_DEBUG
qDebug() << "Received packet:" << packet.header << ":" << packet.contents << "args length:" << packet.contents.length();
#endif
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
PacketInfo l_info = packets.value(packet.header, {false, 0, &AOClient::pktDefault});
if (packet.contents.join("").size() > 16384) {
@ -112,65 +117,65 @@ void AOClient::handlePacket(AOPacket packet)
void AOClient::changeArea(int new_area)
{
if (m_current_area == new_area) {
sendServerMessage("You are already in area " + server->m_area_names[m_current_area]);
sendServerMessage("You are already in area " + server->getAreaName(m_current_area));
return;
}
if (server->m_areas[new_area]->lockStatus() == AreaData::LockStatus::LOCKED && !server->m_areas[new_area]->invited().contains(m_id) && !checkAuth(ACLFlags.value("BYPASS_LOCKS"))) {
sendServerMessage("Area " + server->m_area_names[new_area] + " is locked.");
if (server->getAreaById(new_area)->lockStatus() == AreaData::LockStatus::LOCKED && !server->getAreaById(new_area)->invited().contains(m_id) && !checkAuth(ACLFlags.value("BYPASS_LOCKS"))) {
sendServerMessage("Area " + server->getAreaName(new_area) + " is locked.");
return;
}
if (m_current_char != "") {
server->m_areas[m_current_area]->changeCharacter(server->getCharID(m_current_char), -1);
server->updateCharsTaken(server->m_areas[m_current_area]);
server->getAreaById(m_current_area)->changeCharacter(server->getCharID(m_current_char), -1);
server->updateCharsTaken(server->getAreaById(m_current_area));
}
server->m_areas[m_current_area]->clientLeftArea(m_char_id, m_id);
server->getAreaById(m_current_area)->clientLeftArea(m_char_id, m_id);
bool l_character_taken = false;
if (server->m_areas[new_area]->charactersTaken().contains(server->getCharID(m_current_char))) {
if (server->getAreaById(new_area)->charactersTaken().contains(server->getCharID(m_current_char))) {
m_current_char = "";
m_char_id = -1;
l_character_taken = true;
}
server->m_areas[new_area]->clientJoinedArea(m_char_id, m_id);
server->getAreaById(new_area)->clientJoinedArea(m_char_id, m_id);
m_current_area = new_area;
arup(ARUPType::PLAYER_COUNT, true);
sendEvidenceList(server->m_areas[new_area]);
sendPacket("HP", {"1", QString::number(server->m_areas[new_area]->defHP())});
sendPacket("HP", {"2", QString::number(server->m_areas[new_area]->proHP())});
sendPacket("BN", {server->m_areas[new_area]->background()});
sendEvidenceList(server->getAreaById(new_area));
sendPacket("HP", {"1", QString::number(server->getAreaById(new_area)->defHP())});
sendPacket("HP", {"2", QString::number(server->getAreaById(new_area)->proHP())});
sendPacket("BN", {server->getAreaById(new_area)->background()});
if (l_character_taken) {
sendPacket("DONE");
}
const QList<QTimer*> l_timers = server->m_areas[m_current_area]->timers();
for (QTimer* l_timer : l_timers) {
int l_timer_id = server->m_areas[m_current_area]->timers().indexOf(l_timer) + 1;
const QList<QTimer *> l_timers = server->getAreaById(m_current_area)->timers();
for (QTimer *l_timer : l_timers) {
int l_timer_id = server->getAreaById(m_current_area)->timers().indexOf(l_timer) + 1;
if (l_timer->isActive()) {
sendPacket("TI", {QString::number(l_timer_id), "2"});
sendPacket("TI", {QString::number(l_timer_id), "0", QString::number(QTime(0,0).msecsTo(QTime(0,0).addMSecs(l_timer->remainingTime())))});
sendPacket("TI", {QString::number(l_timer_id), "0", QString::number(QTime(0, 0).msecsTo(QTime(0, 0).addMSecs(l_timer->remainingTime())))});
}
else {
sendPacket("TI", {QString::number(l_timer_id), "3"});
}
}
sendServerMessage("You moved to area " + server->m_area_names[m_current_area]);
if (server->m_areas[m_current_area]->sendAreaMessageOnJoin())
sendServerMessage(server->m_areas[m_current_area]->areaMessage());
sendServerMessage("You moved to area " + server->getAreaName(m_current_area));
if (server->getAreaById(m_current_area)->sendAreaMessageOnJoin())
sendServerMessage(server->getAreaById(m_current_area)->areaMessage());
if (server->m_areas[m_current_area]->lockStatus() == AreaData::LockStatus::SPECTATABLE)
sendServerMessage("Area " + server->m_area_names[m_current_area] + " is spectate-only; to chat IC you will need to be invited by the CM.");
if (server->getAreaById(m_current_area)->lockStatus() == AreaData::LockStatus::SPECTATABLE)
sendServerMessage("Area " + server->getAreaName(m_current_area) + " is spectate-only; to chat IC you will need to be invited by the CM.");
}
bool AOClient::changeCharacter(int char_id)
{
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
if(char_id >= server->m_characters.length())
if (char_id >= server->getCharacterCount())
return false;
if (m_is_charcursed && !m_charcurse_list.contains(char_id)) {
return false;
}
bool l_successfulChange = l_area->changeCharacter(server->getCharID(m_current_char), char_id);
if (char_id < 0) {
@ -178,7 +183,7 @@ bool AOClient::changeCharacter(int char_id)
}
if (l_successfulChange == true) {
QString l_char_selected = server->m_characters[char_id];
QString l_char_selected = server->getCharacterById(char_id);
m_current_char = l_char_selected;
m_pos = "";
server->updateCharsTaken(l_area);
@ -217,39 +222,45 @@ void AOClient::arup(ARUPType type, bool broadcast)
{
QStringList l_arup_data;
l_arup_data.append(QString::number(type));
for (AreaData* l_area : qAsConst(server->m_areas)) {
switch(type) {
case ARUPType::PLAYER_COUNT: {
l_arup_data.append(QString::number(l_area->playerCount()));
break;
}
case ARUPType::STATUS: {
QString l_area_status = QVariant::fromValue(l_area->status()).toString().replace("_", "-"); // LOOKING_FOR_PLAYERS to LOOKING-FOR-PLAYERS
l_arup_data.append(l_area_status);
break;
}
case ARUPType::CM: {
if (l_area->owners().isEmpty())
l_arup_data.append("FREE");
else {
QStringList l_area_owners;
const QList<int> l_owner_ids = l_area->owners();
for (int l_owner_id : l_owner_ids) {
AOClient* l_owner = server->getClientByID(l_owner_id);
l_area_owners.append("[" + QString::number(l_owner->m_id) + "] " + l_owner->m_current_char);
}
l_arup_data.append(l_area_owners.join(", "));
const QVector<AreaData *> l_areas = server->getAreas();
for (AreaData *l_area : l_areas) {
switch (type) {
case ARUPType::PLAYER_COUNT:
{
l_arup_data.append(QString::number(l_area->playerCount()));
break;
}
case ARUPType::STATUS:
{
QString l_area_status = QVariant::fromValue(l_area->status()).toString().replace("_", "-"); // LOOKING_FOR_PLAYERS to LOOKING-FOR-PLAYERS
l_arup_data.append(l_area_status);
break;
}
case ARUPType::CM:
{
if (l_area->owners().isEmpty())
l_arup_data.append("FREE");
else {
QStringList l_area_owners;
const QList<int> l_owner_ids = l_area->owners();
for (int l_owner_id : l_owner_ids) {
AOClient *l_owner = server->getClientByID(l_owner_id);
l_area_owners.append("[" + QString::number(l_owner->m_id) + "] " + l_owner->m_current_char);
}
break;
}
case ARUPType::LOCKED: {
QString l_lock_status = QVariant::fromValue(l_area->lockStatus()).toString();
l_arup_data.append(l_lock_status);
break;
}
default: {
return;
l_arup_data.append(l_area_owners.join(", "));
}
break;
}
case ARUPType::LOCKED:
{
QString l_lock_status = QVariant::fromValue(l_area->lockStatus()).toString();
l_arup_data.append(l_lock_status);
break;
}
default:
{
return;
}
}
}
if (broadcast)
@ -258,7 +269,8 @@ void AOClient::arup(ARUPType type, bool broadcast)
sendPacket("ARUP", l_arup_data);
}
void AOClient::fullArup() {
void AOClient::fullArup()
{
arup(ARUPType::PLAYER_COUNT, false);
arup(ARUPType::STATUS, false);
arup(ARUPType::CM, false);
@ -271,8 +283,8 @@ void AOClient::sendPacket(AOPacket packet)
qDebug() << "Sent packet:" << packet.header << ":" << packet.contents;
#endif
packet.contents.replaceInStrings("#", "<num>")
.replaceInStrings("%", "<percent>")
.replaceInStrings("$", "<dollar>");
.replaceInStrings("%", "<percent>")
.replaceInStrings("$", "<dollar>");
if (packet.header != "LE")
packet.contents.replaceInStrings("&", "<and>");
m_socket->write(packet.toUtf8());
@ -326,7 +338,7 @@ bool AOClient::checkAuth(unsigned long long acl_mask)
#endif
if (acl_mask != ACLFlags.value("NONE")) {
if (acl_mask == ACLFlags.value("CM")) {
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
if (l_area->owners().contains(m_id))
return true;
}
@ -338,7 +350,7 @@ bool AOClient::checkAuth(unsigned long long acl_mask)
return m_authenticated;
break;
case DataTypes::AuthType::ADVANCED:
unsigned long long l_user_acl = server->db_manager->getACL(m_moderator_name);
unsigned long long l_user_acl = server->getDatabaseManager()->getACL(m_moderator_name);
return (l_user_acl & acl_mask) != 0;
break;
}
@ -346,7 +358,6 @@ bool AOClient::checkAuth(unsigned long long acl_mask)
return true;
}
QString AOClient::getIpid() const
{
return m_ipid;
@ -357,7 +368,12 @@ QString AOClient::getHwid() const
return m_hwid;
}
Server* AOClient::getServer() { return server; }
bool AOClient::hasJoined() const
{
return m_joined;
}
Server *AOClient::getServer() { return server; }
void AOClient::onAfkTimeout()
{
@ -366,26 +382,26 @@ void AOClient::onAfkTimeout()
m_is_afk = true;
}
AOClient::AOClient(Server *p_server, QTcpSocket *p_socket, QObject *parent, int user_id, MusicManager *p_manager)
: QObject(parent),
m_id(user_id),
m_remote_ip(p_socket->peerAddress()),
m_password(""),
m_joined(false),
m_current_area(0),
m_current_char(""),
m_socket(p_socket),
server(p_server),
is_partial(false),
m_last_wtce_time(0),
m_music_manager(p_manager)
AOClient::AOClient(Server *p_server, QTcpSocket *p_socket, QObject *parent, int user_id, MusicManager *p_manager) :
QObject(parent),
m_id(user_id),
m_remote_ip(p_socket->peerAddress()),
m_password(""),
m_joined(false),
m_current_area(0),
m_current_char(""),
m_socket(p_socket),
server(p_server),
is_partial(false),
m_last_wtce_time(0),
m_music_manager(p_manager)
{
m_afk_timer = new QTimer;
m_afk_timer->setSingleShot(true);
connect(m_afk_timer, &QTimer::timeout,
this, &AOClient::onAfkTimeout);
connect(m_afk_timer, &QTimer::timeout, this, &AOClient::onAfkTimeout);
}
AOClient::~AOClient() {
AOClient::~AOClient()
{
m_socket->deleteLater();
}

View File

@ -18,9 +18,12 @@
#include <algorithm>
#include "include/aopacket.h"
#include "include/area_data.h"
#include "include/config_manager.h"
#include "include/music_manager.h"
AreaData::AreaData(QString p_name, int p_index, MusicManager* p_music_manager = nullptr) :
AreaData::AreaData(QString p_name, int p_index, MusicManager *p_music_manager = nullptr) :
m_index(p_index),
m_music_manager(p_music_manager),
m_playerCount(0),
@ -38,7 +41,7 @@ AreaData::AreaData(QString p_name, int p_index, MusicManager* p_music_manager =
QStringList name_split = p_name.split(":");
name_split.removeFirst();
m_name = name_split.join(":");
QSettings* areas_ini = ConfigManager::areaData();
QSettings *areas_ini = ConfigManager::areaData();
areas_ini->setIniCodec("UTF-8");
areas_ini->beginGroup(p_name);
m_background = areas_ini->value("background", "gs4").toString();
@ -46,20 +49,22 @@ AreaData::AreaData(QString p_name, int p_index, MusicManager* p_music_manager =
m_iniswapAllowed = areas_ini->value("iniswap_allowed", "true").toBool();
m_bgLocked = areas_ini->value("bg_locked", "false").toBool();
m_eviMod = QVariant(areas_ini->value("evidence_mod", "FFA").toString().toUpper()).value<EvidenceMod>();
m_blankpostingAllowed = areas_ini->value("blankposting_allowed","true").toBool();
m_blankpostingAllowed = areas_ini->value("blankposting_allowed", "true").toBool();
m_area_message = areas_ini->value("area_message").toString();
m_send_area_message = areas_ini->value("send_area_message_on_join", false).toBool();
m_forceImmediate = areas_ini->value("force_immediate", "false").toBool();
m_toggleMusic = areas_ini->value("toggle_music", "true").toBool();
m_shownameAllowed = areas_ini->value("shownames_allowed", "true").toBool();
m_ignoreBgList = areas_ini->value("ignore_bglist", "false").toBool();
m_jukebox = areas_ini->value("jukebox_enabled", "false").toBool();
areas_ini->endGroup();
QTimer* timer1 = new QTimer();
QTimer *timer1 = new QTimer();
m_timers.append(timer1);
QTimer* timer2 = new QTimer();
QTimer *timer2 = new QTimer();
m_timers.append(timer2);
QTimer* timer3 = new QTimer();
QTimer *timer3 = new QTimer();
m_timers.append(timer3);
QTimer* timer4 = new QTimer();
QTimer *timer4 = new QTimer();
m_timers.append(timer4);
m_jukebox_timer = new QTimer();
connect(m_jukebox_timer, &QTimer::timeout,
@ -67,13 +72,13 @@ AreaData::AreaData(QString p_name, int p_index, MusicManager* p_music_manager =
}
const QMap<QString, AreaData::Status> AreaData::map_statuses = {
{"idle", AreaData::Status::IDLE },
{"rp", AreaData::Status::RP },
{"casing", AreaData::Status::CASING },
{"lfp", AreaData::Status::LOOKING_FOR_PLAYERS },
{"looking-for-players", AreaData::Status::LOOKING_FOR_PLAYERS },
{"recess", AreaData::Status::RECESS },
{"gaming", AreaData::Status::GAMING },
{"idle", AreaData::Status::IDLE},
{"rp", AreaData::Status::RP},
{"casing", AreaData::Status::CASING},
{"lfp", AreaData::Status::LOOKING_FOR_PLAYERS},
{"looking-for-players", AreaData::Status::LOOKING_FOR_PLAYERS},
{"recess", AreaData::Status::RECESS},
{"gaming", AreaData::Status::GAMING},
};
void AreaData::clientLeftArea(int f_charId, int f_userId)
@ -95,9 +100,9 @@ void AreaData::clientJoinedArea(int f_charId, int f_userId)
}
m_joined_ids.append(f_userId);
emit userJoinedArea(m_index, f_userId);
//The name will never be shown as we are using a spectator ID. Still nice for people who network sniff.
//We auto-loop this so you'll never sit in silence unless wanted.
emit sendAreaPacketClient(AOPacket("MC",{m_currentMusic, QString::number(-1), ConfigManager::serverName(), QString::number(1)}), f_userId);
// The name will never be shown as we are using a spectator ID. Still nice for people who network sniff.
// We auto-loop this so you'll never sit in silence unless wanted.
emit sendAreaPacketClient(AOPacket("MC", {m_currentMusic, QString::number(-1), ConfigManager::serverName(), QString::number(1)}), f_userId);
}
QList<int> AreaData::owners() const
@ -238,7 +243,7 @@ QList<AreaData::Evidence> AreaData::evidence() const
void AreaData::swapEvidence(int f_eviId1, int f_eviId2)
{
#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
//swapItemsAt does not exist in Qt older than 5.13
// swapItemsAt does not exist in Qt older than 5.13
m_evidence.swap(f_eviId1, f_eviId2);
#else
m_evidence.swapItemsAt(f_eviId1, f_eviId2);
@ -323,7 +328,7 @@ void AreaData::toggleImmediate()
m_forceImmediate = !m_forceImmediate;
}
const QStringList& AreaData::lastICMessage() const
const QStringList &AreaData::lastICMessage() const
{
return m_lastICMessage;
}
@ -391,7 +396,7 @@ QPair<QStringList, AreaData::TestimonyProgress> AreaData::jumpToStatement(int f_
}
}
const QVector<QStringList>& AreaData::testimony() const
const QVector<QStringList> &AreaData::testimony() const
{
return m_testimony;
}
@ -438,7 +443,7 @@ QString AreaData::musicPlayerBy() const
return m_musicPlayedBy;
}
void AreaData::setMusicPlayedBy(const QString& f_music_player)
void AreaData::setMusicPlayedBy(const QString &f_music_player)
{
m_musicPlayedBy = f_music_player;
}
@ -468,7 +473,8 @@ void AreaData::changeHP(AreaData::Side f_side, int f_newHP)
{
if (f_side == Side::DEFENCE) {
m_defHP = std::min(std::max(0, f_newHP), 10);
} else if(f_side == Side::PROSECUTOR) {
}
else if (f_side == Side::PROSECUTOR) {
m_proHP = std::min(std::max(0, f_newHP), 10);
}
}
@ -490,7 +496,7 @@ void AreaData::changeDoc(const QString &f_newDoc_r)
QString AreaData::areaMessage() const
{
return m_area_message;
return m_area_message.isEmpty() ? "No area message set." : m_area_message;
}
bool AreaData::sendAreaMessageOnJoin() const
@ -498,12 +504,14 @@ bool AreaData::sendAreaMessageOnJoin() const
return m_send_area_message;
}
void AreaData::changeAreaMessage(const QString& f_newMessage_r)
void AreaData::changeAreaMessage(const QString &f_newMessage_r)
{
if(f_newMessage_r.isEmpty())
m_area_message = "No area message set.";
else
m_area_message = f_newMessage_r;
m_area_message = f_newMessage_r;
}
void AreaData::clearAreaMessage()
{
changeAreaMessage(QString{});
}
bool AreaData::bgLocked() const
@ -567,24 +575,24 @@ void AreaData::toggleJukebox()
QString AreaData::addJukeboxSong(QString f_song)
{
if(!m_jukebox_queue.contains(f_song)) {
//Retrieve song information.
QPair<QString,float> l_song = m_music_manager->songInformation(f_song, index());
if (!m_jukebox_queue.contains(f_song)) {
// Retrieve song information.
QPair<QString, float> l_song = m_music_manager->songInformation(f_song, index());
if (l_song.second > 0) {
if (m_jukebox_queue.size() == 0) {
if (l_song.second > 0) {
if (m_jukebox_queue.size() == 0) {
emit sendAreaPacket(AOPacket("MC",{l_song.first,QString::number(-1)}), index());
m_jukebox_timer->start(l_song.second * 1000);
setCurrentMusic(f_song);
setMusicPlayedBy("Jukebox");
}
m_jukebox_queue.append(f_song);
return "Song added to Jukebox.";
}
else {
return "Unable to add song. Duration shorter than 1.";
emit sendAreaPacket(AOPacket("MC", {l_song.first, QString::number(-1)}), index());
m_jukebox_timer->start(l_song.second * 1000);
setCurrentMusic(f_song);
setMusicPlayedBy("Jukebox");
}
m_jukebox_queue.append(f_song);
return "Song added to Jukebox.";
}
else {
return "Unable to add song. Duration shorter than 1.";
}
}
return "Unable to add song. Song already in Jukebox.";
}
@ -597,18 +605,18 @@ QVector<int> AreaData::joinedIDs() const
void AreaData::switchJukeboxSong()
{
QString l_song_name;
if(m_jukebox_queue.size() == 1) {
if (m_jukebox_queue.size() == 1) {
l_song_name = m_jukebox_queue[0];
QPair<QString,float> l_song = m_music_manager->songInformation(l_song_name, index());
emit sendAreaPacket(AOPacket("MC",{l_song.first,"-1"}), m_index);
QPair<QString, float> l_song = m_music_manager->songInformation(l_song_name, index());
emit sendAreaPacket(AOPacket("MC", {l_song.first, "-1"}), m_index);
m_jukebox_timer->start(l_song.second * 1000);
}
else {
int l_random_index = QRandomGenerator::system()->bounded(m_jukebox_queue.size() -1);
int l_random_index = QRandomGenerator::system()->bounded(m_jukebox_queue.size() - 1);
l_song_name = m_jukebox_queue[l_random_index];
QPair<QString,float> l_song = m_music_manager->songInformation(l_song_name, index());
emit sendAreaPacket(AOPacket("MC",{l_song.first,"-1"}), m_index);
QPair<QString, float> l_song = m_music_manager->songInformation(l_song_name, index());
emit sendAreaPacket(AOPacket("MC", {l_song.first, "-1"}), m_index);
m_jukebox_timer->start(l_song.second * 1000);
m_jukebox_queue.remove(l_random_index);

View File

@ -17,14 +17,18 @@
//////////////////////////////////////////////////////////////////////////////////////
#include "include/aoclient.h"
#include "include/aopacket.h"
#include "include/area_data.h"
#include "include/config_manager.h"
#include "include/server.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 l_sender_name = m_ooc_name;
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
if (l_area->isProtected()) {
sendServerMessage("This area is protected, you may not become CM.");
return;
@ -39,7 +43,7 @@ void AOClient::cmdCM(int argc, QStringList argv)
}
else if (argc == 1) { // we are CM, and we want to make ID argv[0] also CM
bool ok;
AOClient* l_owner_candidate = server->getClientByID(argv[0].toInt(&ok));
AOClient *l_owner_candidate = server->getClientByID(argv[0].toInt(&ok));
if (!ok) {
sendServerMessage("That doesn't look like a valid ID.");
return;
@ -63,7 +67,7 @@ void AOClient::cmdCM(int argc, QStringList argv)
void AOClient::cmdUnCM(int argc, QStringList argv)
{
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
int l_uid;
if (l_area->owners().isEmpty()) {
@ -85,7 +89,7 @@ void AOClient::cmdUnCM(int argc, QStringList argv)
sendServerMessage("That user is not CMed.");
return;
}
AOClient* l_target = server->getClientByID(l_uid);
AOClient *l_target = server->getClientByID(l_uid);
if (l_target == nullptr) {
sendServerMessage("No client with that ID found.");
return;
@ -108,7 +112,7 @@ void AOClient::cmdInvite(int argc, QStringList argv)
{
Q_UNUSED(argc);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
bool ok;
int l_invited_id = argv[0].toInt(&ok);
if (!ok) {
@ -116,7 +120,7 @@ void AOClient::cmdInvite(int argc, QStringList argv)
return;
}
AOClient* target_client = server->getClientByID(l_invited_id);
AOClient *target_client = server->getClientByID(l_invited_id);
if (target_client == nullptr) {
sendServerMessage("No client with that ID found.");
return;
@ -133,7 +137,7 @@ void AOClient::cmdUnInvite(int argc, QStringList argv)
{
Q_UNUSED(argc);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
bool ok;
int l_uninvited_id = argv[0].toInt(&ok);
if (!ok) {
@ -141,7 +145,7 @@ void AOClient::cmdUnInvite(int argc, QStringList argv)
return;
}
AOClient* target_client = server->getClientByID(l_uninvited_id);
AOClient *target_client = server->getClientByID(l_uninvited_id);
if (target_client == nullptr) {
sendServerMessage("No client with that ID found.");
return;
@ -163,16 +167,17 @@ void AOClient::cmdLock(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
AreaData* area = server->m_areas[m_current_area];
AreaData *area = server->getAreaById(m_current_area);
if (area->lockStatus() == AreaData::LockStatus::LOCKED) {
sendServerMessage("This area is already locked.");
return;
}
sendServerMessageArea("This area is now locked.");
area->lock();
for (AOClient* client : qAsConst(server->m_clients)) { // qAsConst here avoids detaching the container
if (client->m_current_area == m_current_area && client->m_joined) {
area->invite(client->m_id);
const QVector<AOClient *> l_clients = server->getClients();
for (AOClient *l_client : l_clients) {
if (l_client->m_current_area == m_current_area && l_client->hasJoined()) {
area->invite(l_client->m_id);
}
}
arup(ARUPType::LOCKED, true);
@ -183,16 +188,17 @@ void AOClient::cmdSpectatable(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
if (l_area->lockStatus() == AreaData::LockStatus::SPECTATABLE) {
sendServerMessage("This area is already in spectate mode.");
return;
}
sendServerMessageArea("This area is now spectatable.");
l_area->spectatable();
for (AOClient* client : qAsConst(server->m_clients)) {
if (client->m_current_area == m_current_area && client->m_joined) {
l_area->invite(client->m_id);
const QVector<AOClient *> l_clients = server->getClients();
for (AOClient *l_client : l_clients) {
if (l_client->m_current_area == m_current_area && l_client->hasJoined()) {
l_area->invite(l_client->m_id);
}
}
arup(ARUPType::LOCKED, true);
@ -203,7 +209,7 @@ void AOClient::cmdUnLock(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
if (l_area->lockStatus() == AreaData::LockStatus::FREE) {
sendServerMessage("This area is not locked.");
return;
@ -219,9 +225,9 @@ void AOClient::cmdGetAreas(int argc, QStringList argv)
Q_UNUSED(argv);
QStringList l_entries;
l_entries.append("\n== Currently Online: " + QString::number(server->m_player_count)+ " ==");
for (int i = 0; i < server->m_area_names.length(); i++) {
if (server->m_areas.value(i)->playerCount() > 0) {
l_entries.append("\n== Currently Online: " + QString::number(server->getPlayerCount()) + " ==");
for (int i = 0; i < server->getAreaCount(); i++) {
if (server->getAreaById(i)->playerCount() > 0) {
QStringList l_cur_area_lines = buildAreaList(i);
l_entries.append(l_cur_area_lines);
}
@ -244,7 +250,7 @@ void AOClient::cmdArea(int argc, QStringList argv)
bool ok;
int l_new_area = argv[0].toInt(&ok);
if (!ok || l_new_area >= server->m_areas.size() || l_new_area < 0) {
if (!ok || l_new_area >= server->getAreaCount() || l_new_area < 0) {
sendServerMessage("That does not look like a valid area ID.");
return;
}
@ -255,7 +261,7 @@ void AOClient::cmdAreaKick(int argc, QStringList argv)
{
Q_UNUSED(argc);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
bool ok;
int l_idx = argv[0].toInt(&ok);
@ -263,11 +269,11 @@ void AOClient::cmdAreaKick(int argc, QStringList argv)
sendServerMessage("That does not look like a valid ID.");
return;
}
if (server->m_areas[m_current_area]->owners().contains(l_idx)) {
if (server->getAreaById(m_current_area)->owners().contains(l_idx)) {
sendServerMessage("You cannot kick another CM!");
return;
}
AOClient* l_client_to_kick = server->getClientByID(l_idx);
AOClient *l_client_to_kick = server->getClientByID(l_idx);
if (l_client_to_kick == nullptr) {
sendServerMessage("No client with that ID found.");
return;
@ -287,9 +293,9 @@ void AOClient::cmdSetBackground(int argc, QStringList argv)
Q_UNUSED(argc);
QString f_background = argv.join(" ");
AreaData* area = server->m_areas[m_current_area];
AreaData *area = server->getAreaById(m_current_area);
if (m_authenticated || !area->bgLocked()) {
if (server->m_backgrounds.contains(f_background, Qt::CaseInsensitive) || area->ignoreBgList() == true) {
if (server->getBackgrounds().contains(f_background, Qt::CaseInsensitive) || area->ignoreBgList() == true) {
area->setBackground(f_background);
server->broadcast(AOPacket("BN", {f_background}), m_current_area);
sendServerMessageArea(m_current_char + " changed the background to " + f_background);
@ -308,7 +314,7 @@ void AOClient::cmdBgLock(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
if (l_area->bgLocked() == false) {
l_area->toggleBgLock();
@ -322,7 +328,7 @@ void AOClient::cmdBgUnlock(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
if (l_area->bgLocked() == true) {
l_area->toggleBgLock();
@ -335,13 +341,14 @@ void AOClient::cmdStatus(int argc, QStringList argv)
{
Q_UNUSED(argc);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
QString l_arg = argv[0].toLower();
if (l_area->changeStatus(l_arg)) {
arup(ARUPType::STATUS, true);
server->broadcast(AOPacket("CT", {ConfigManager::serverName(), m_current_char + " changed status to " + l_arg.toUpper(), "1"}), m_current_area);
} else {
}
else {
const QStringList keys = AreaData::map_statuses.keys();
sendServerMessage("That does not look like a valid status. Valid statuses are " + keys.join(", "));
}
@ -352,18 +359,18 @@ void AOClient::cmdJudgeLog(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
if (l_area->judgelog().isEmpty()) {
sendServerMessage("There have been no judge actions in this area.");
return;
}
QString l_message = l_area->judgelog().join("\n");
//Judgelog contains an IPID, so we shouldn't send that unless the caller has appropriate permissions
// 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(l_message);
sendServerMessage(l_message);
}
else {
QString filteredmessage = l_message.remove(QRegularExpression("[(].*[)]")); //Filter out anything between two parentheses. This should only ever be the IPID
QString filteredmessage = l_message.remove(QRegularExpression("[(].*[)]")); // Filter out anything between two parentheses. This should only ever be the IPID
sendServerMessage(filteredmessage);
}
}
@ -373,7 +380,7 @@ void AOClient::cmdIgnoreBgList(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
l_area->toggleIgnoreBgList();
QString l_state = l_area->ignoreBgList() ? "ignored." : "enforced.";
sendServerMessage("BG list in this area is now " + l_state);
@ -381,7 +388,7 @@ void AOClient::cmdIgnoreBgList(int argc, QStringList argv)
void AOClient::cmdAreaMessage(int argc, QStringList argv)
{
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
if (argc == 0) {
sendServerMessage(l_area->areaMessage());
return;
@ -398,10 +405,10 @@ void AOClient::cmdToggleAreaMessageOnJoin(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
l_area->toggleAreaMessageJoin();
QString l_state = l_area->sendAreaMessageOnJoin() ? "enabled." : "disabled.";
sendServerMessage("Sending message on area join is now " +l_state);
sendServerMessage("Sending message on area join is now " + l_state);
}
void AOClient::cmdClearAreaMessage(int argc, QStringList argv)
@ -409,8 +416,8 @@ void AOClient::cmdClearAreaMessage(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
AreaData* l_area = server->m_areas[m_current_area];
l_area->changeAreaMessage(QString{});
if (l_area->sendAreaMessageOnJoin()) //Turn off the automatic sending.
cmdToggleAreaMessageOnJoin(0,QStringList{}); //Dummy values.
AreaData *l_area = server->getAreaById(m_current_area);
l_area->clearAreaMessage();
if (l_area->sendAreaMessageOnJoin()) // Turn off the automatic sending.
cmdToggleAreaMessageOnJoin(0, QStringList{}); // Dummy values.
}

View File

@ -17,6 +17,10 @@
//////////////////////////////////////////////////////////////////////////////////////
#include "include/aoclient.h"
#include "include/config_manager.h"
#include "include/db_manager.h"
#include "include/server.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!
@ -86,7 +90,7 @@ void AOClient::cmdSetRootPass(int argc, QStringList argv)
#endif
QString l_salt = QStringLiteral("%1").arg(l_salt_number, 16, 16, QLatin1Char('0'));
server->db_manager->createUser("root", l_salt, argv[0], ACLFlags.value("SUPER"));
server->getDatabaseManager()->createUser("root", l_salt, argv[0], ACLFlags.value("SUPER"));
}
void AOClient::cmdAddUser(int argc, QStringList argv)
@ -107,7 +111,7 @@ void AOClient::cmdAddUser(int argc, QStringList argv)
#endif
QString l_salt = QStringLiteral("%1").arg(l_salt_number, 16, 16, QLatin1Char('0'));
if (server->db_manager->createUser(argv[0], l_salt, argv[1], ACLFlags.value("NONE")))
if (server->getDatabaseManager()->createUser(argv[0], l_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?");
@ -117,7 +121,7 @@ void AOClient::cmdRemoveUser(int argc, QStringList argv)
{
Q_UNUSED(argc);
if (server->db_manager->deleteUser(argv[0]))
if (server->getDatabaseManager()->deleteUser(argv[0]))
sendServerMessage("Successfully removed user " + argv[0] + ".");
else
sendServerMessage("Unable to remove user " + argv[0] + ".\nDoes it exist?");
@ -125,19 +129,21 @@ void AOClient::cmdRemoveUser(int argc, QStringList argv)
void AOClient::cmdListPerms(int argc, QStringList argv)
{
unsigned long long l_user_acl = server->db_manager->getACL(m_moderator_name);
unsigned long long l_user_acl = server->getDatabaseManager()->getACL(m_moderator_name);
QStringList l_message;
const QStringList l_keys = ACLFlags.keys();
if (argc == 0) {
// Just print out all permissions available to the user.
l_message.append("You have been given the following permissions:");
for (const QString &l_perm : l_keys) {
if (l_perm == "NONE"); // don't need to list this one
if (l_perm == "NONE")
; // don't need to list this one
else if (l_perm == "SUPER") {
if (l_user_acl == ACLFlags.value("SUPER")) // This has to be checked separately, because SUPER & anything will always be truthy
l_message.append("SUPER (Be careful! This grants the user all permissions.)");
}
else if ((ACLFlags.value(l_perm) & l_user_acl) == 0); // user doesn't have this permission, don't print it
else if ((ACLFlags.value(l_perm) & l_user_acl) == 0)
; // user doesn't have this permission, don't print it
else
l_message.append(l_perm);
}
@ -149,7 +155,7 @@ void AOClient::cmdListPerms(int argc, QStringList argv)
}
l_message.append("User " + argv[0] + " has the following permissions:");
unsigned long long l_acl = server->db_manager->getACL(argv[0]);
unsigned long long l_acl = server->getDatabaseManager()->getACL(argv[0]);
if (l_acl == 0) {
sendServerMessage("This user either doesn't exist, or has no permissions set.");
return;
@ -168,7 +174,7 @@ void AOClient::cmdAddPerms(int argc, QStringList argv)
{
Q_UNUSED(argc);
unsigned long long l_user_acl = server->db_manager->getACL(m_moderator_name);
unsigned long long l_user_acl = server->getDatabaseManager()->getACL(m_moderator_name);
argv[1] = argv[1].toUpper();
const QStringList l_keys = ACLFlags.keys();
@ -191,7 +197,7 @@ void AOClient::cmdAddPerms(int argc, QStringList argv)
unsigned long long l_newperm = ACLFlags.value(argv[1]);
if ((l_newperm & l_user_acl) != 0) {
if (server->db_manager->updateACL(argv[0], l_newperm, true))
if (server->getDatabaseManager()->updateACL(argv[0], l_newperm, true))
sendServerMessage("Successfully added permission " + argv[1] + " to user " + argv[0]);
else
sendServerMessage(argv[0] + " wasn't found!");
@ -205,7 +211,7 @@ void AOClient::cmdRemovePerms(int argc, QStringList argv)
{
Q_UNUSED(argc);
unsigned long long l_user_acl = server->db_manager->getACL(m_moderator_name);
unsigned long long l_user_acl = server->getDatabaseManager()->getACL(m_moderator_name);
argv[1] = argv[1].toUpper();
const QStringList l_keys = ACLFlags.keys();
@ -234,7 +240,7 @@ void AOClient::cmdRemovePerms(int argc, QStringList argv)
unsigned long long l_newperm = ACLFlags.value(argv[1]);
if ((l_newperm & l_user_acl) != 0) {
if (server->db_manager->updateACL(argv[0], l_newperm, false))
if (server->getDatabaseManager()->updateACL(argv[0], l_newperm, false))
sendServerMessage("Successfully removed permission " + argv[1] + " from user " + argv[0]);
else
sendServerMessage(argv[0] + " wasn't found!");
@ -249,7 +255,7 @@ void AOClient::cmdListUsers(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
QStringList l_users = server->db_manager->getUsers();
QStringList l_users = server->getDatabaseManager()->getUsers();
sendServerMessage("All users:\n" + l_users.join("\n"));
}
@ -291,7 +297,7 @@ void AOClient::cmdChangePassword(int argc, QStringList argv)
return;
}
if (server->db_manager->updatePassword(l_username, l_password)) {
if (server->getDatabaseManager()->updatePassword(l_username, l_password)) {
sendServerMessage("Successfully changed password.");
}
else {

View File

@ -17,13 +17,18 @@
//////////////////////////////////////////////////////////////////////////////////////
#include "include/aoclient.h"
#include "include/aopacket.h"
#include "include/area_data.h"
#include "include/config_manager.h"
#include "include/server.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 l_sender_name = m_ooc_name;
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
if (argc == 0) {
sendServerMessage("Document: " + l_area->document());
}
@ -39,7 +44,7 @@ void AOClient::cmdClearDoc(int argc, QStringList argv)
Q_UNUSED(argv);
QString l_sender_name = m_ooc_name;
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
l_area->changeDoc("No document.");
sendServerMessageArea(l_sender_name + " cleared the document.");
}
@ -48,7 +53,7 @@ void AOClient::cmdEvidenceMod(int argc, QStringList argv)
{
Q_UNUSED(argc);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
argv[0] = argv[0].toLower();
if (argv[0] == "cm")
l_area->setEviMod(AreaData::EvidenceMod::CM);
@ -72,8 +77,8 @@ void AOClient::cmdEvidence_Swap(int argc, QStringList argv)
{
Q_UNUSED(argc);
AreaData* l_area = server->m_areas[m_current_area];
int l_ev_size = l_area->evidence().size() -1;
AreaData *l_area = server->getAreaById(m_current_area);
int l_ev_size = l_area->evidence().size() - 1;
if (l_ev_size < 0) {
sendServerMessage("No evidence in area.");
@ -106,7 +111,7 @@ void AOClient::cmdTestify(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
if (l_area->testimonyRecording() == AreaData::TestimonyRecording::RECORDING) {
sendServerMessage("Testimony recording is already in progress. Please stop it before starting a new one.");
}
@ -122,11 +127,10 @@ void AOClient::cmdExamine(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
AreaData* l_area = server->m_areas[m_current_area];
if (l_area->testimony().size() -1 > 0)
{
AreaData *l_area = server->getAreaById(m_current_area);
if (l_area->testimony().size() - 1 > 0) {
l_area->restartTestimony();
server->broadcast(AOPacket("RT",{"testimony2"}), m_current_area);
server->broadcast(AOPacket("RT", {"testimony2"}), m_current_area);
server->broadcast(AOPacket("MS", {l_area->testimony()[0]}), m_current_area);
return;
}
@ -141,20 +145,19 @@ void AOClient::cmdTestimony(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
AreaData* l_area = server->m_areas[m_current_area];
if (l_area->testimony().size() -1 < 1) {
sendServerMessage("Unable to display empty testimony.");
return;
}
AreaData *l_area = server->getAreaById(m_current_area);
if (l_area->testimony().size() - 1 < 1) {
sendServerMessage("Unable to display empty testimony.");
return;
}
QString l_ooc_message;
for (int i = 1; i <= l_area->testimony().size() -1; i++)
{
QStringList l_packet = l_area->testimony().at(i);
QString l_ic_message = l_packet[4];
l_ooc_message.append( "[" + QString::number(i) + "]" + l_ic_message + "\n");
}
sendServerMessage(l_ooc_message);
QString l_ooc_message;
for (int i = 1; i <= l_area->testimony().size() - 1; i++) {
QStringList l_packet = l_area->testimony().at(i);
QString l_ic_message = l_packet[4];
l_ooc_message.append("[" + QString::number(i) + "]" + l_ic_message + "\n");
}
sendServerMessage(l_ooc_message);
}
void AOClient::cmdDeleteStatement(int argc, QStringList argv)
@ -162,7 +165,7 @@ void AOClient::cmdDeleteStatement(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
int l_c_statement = l_area->statement();
if (l_area->testimony().size() - 1 == 0) {
sendServerMessage("Unable to delete statement. No statements saved in this area.");
@ -178,7 +181,7 @@ void AOClient::cmdUpdateStatement(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
server->m_areas[m_current_area]->setTestimonyRecording(AreaData::TestimonyRecording::UPDATE);
server->getAreaById(m_current_area)->setTestimonyRecording(AreaData::TestimonyRecording::UPDATE);
sendServerMessage("The next IC-Message will replace the last displayed replay message.");
}
@ -187,9 +190,9 @@ void AOClient::cmdPauseTestimony(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
l_area->setTestimonyRecording(AreaData::TestimonyRecording::STOPPED);
server->broadcast(AOPacket("RT",{"testimony1", "1"}), m_current_area);
server->broadcast(AOPacket("RT", {"testimony1", "1"}), m_current_area);
sendServerMessage("Testimony has been stopped.");
}
@ -198,8 +201,8 @@ void AOClient::cmdAddStatement(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
if (server->m_areas[m_current_area]->statement() < ConfigManager::maxStatements()) {
server->m_areas[m_current_area]->setTestimonyRecording(AreaData::TestimonyRecording::ADD);
if (server->getAreaById(m_current_area)->statement() < ConfigManager::maxStatements()) {
server->getAreaById(m_current_area)->setTestimonyRecording(AreaData::TestimonyRecording::ADD);
sendServerMessage("The next IC-Message will be inserted into the testimony.");
}
else
@ -218,18 +221,18 @@ void AOClient::cmdSaveTestimony(int argc, QStringList argv)
l_permission_found = true;
if (l_permission_found) {
AreaData* l_area = server->m_areas[m_current_area];
if (l_area->testimony().size() -1 <= 0) {
AreaData *l_area = server->getAreaById(m_current_area);
if (l_area->testimony().size() - 1 <= 0) {
sendServerMessage("Can't save an empty testimony.");
return;
}
QDir l_dir_testimony("storage/testimony");
if (!l_dir_testimony.exists()) {
l_dir_testimony.mkpath(".");
}
if (!l_dir_testimony.exists()) {
l_dir_testimony.mkpath(".");
}
QString l_testimony_name = argv[0].trimmed().toLower().replace("..",""); // :)
QString l_testimony_name = argv[0].trimmed().toLower().replace("..", ""); // :)
QFile l_file("storage/testimony/" + l_testimony_name + ".txt");
if (l_file.exists()) {
sendServerMessage("Unable to save testimony. Testimony name already exists.");
@ -238,9 +241,8 @@ void AOClient::cmdSaveTestimony(int argc, QStringList argv)
QTextStream l_out(&l_file);
l_out.setCodec("UTF-8");
if(l_file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
for (int i = 0; i <= l_area->testimony().size() -1; i++)
{
if (l_file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
for (int i = 0; i <= l_area->testimony().size() - 1; i++) {
l_out << l_area->testimony().at(i).join("#") << "\n";
}
sendServerMessage("Testimony saved. To load it use /loadtestimony " + l_testimony_name);
@ -257,14 +259,14 @@ void AOClient::cmdLoadTestimony(int argc, QStringList argv)
{
Q_UNUSED(argc);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
QDir l_dir_testimony("storage/testimony");
if (!l_dir_testimony.exists()) {
sendServerMessage("Unable to load testimonies. Testimony storage not found.");
return;
}
QString l_testimony_name = argv[0].trimmed().toLower().replace("..",""); // :)
QString l_testimony_name = argv[0].trimmed().toLower().replace("..", ""); // :)
QFile l_file("storage/testimony/" + l_testimony_name + ".txt");
if (!l_file.exists()) {
sendServerMessage("Unable to load testimony. Testimony name not found.");

View File

@ -17,6 +17,11 @@
//////////////////////////////////////////////////////////////////////////////////////
#include "include/aoclient.h"
#include "include/aopacket.h"
#include "include/area_data.h"
#include "include/config_manager.h"
#include "include/server.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!
@ -32,33 +37,34 @@ void AOClient::cmdDefault(int argc, QStringList argv)
QStringList AOClient::buildAreaList(int area_idx)
{
QStringList entries;
QString area_name = server->m_area_names[area_idx];
AreaData* area = server->m_areas[area_idx];
QString area_name = server->getAreaName(area_idx);
AreaData *area = server->getAreaById(area_idx);
entries.append("=== " + area_name + " ===");
switch (area->lockStatus()) {
case AreaData::LockStatus::LOCKED:
entries.append("[LOCKED]");
break;
case AreaData::LockStatus::SPECTATABLE:
entries.append("[SPECTATABLE]");
break;
case AreaData::LockStatus::FREE:
default:
break;
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->playerCount()) + " users][" + QVariant::fromValue(area->status()).toString().replace("_", "-") + "]");
for (AOClient* client : qAsConst(server->m_clients)) {
if (client->m_current_area == area_idx && client->m_joined) {
QString char_entry = "[" + QString::number(client->m_id) + "] " + client->m_current_char;
if (client->m_current_char == "")
const QVector<AOClient *> l_clients = server->getClients();
for (AOClient *l_client : l_clients) {
if (l_client->m_current_area == area_idx && l_client->hasJoined()) {
QString char_entry = "[" + QString::number(l_client->m_id) + "] " + l_client->m_current_char;
if (l_client->m_current_char == "")
char_entry += "Spectator";
if (client->m_showname != "")
char_entry += " (" + client->m_showname + ")";
if (area->owners().contains(client->m_id))
if (l_client->m_showname != "")
char_entry += " (" + l_client->m_showname + ")";
if (area->owners().contains(l_client->m_id))
char_entry.insert(0, "[CM] ");
if (m_authenticated)
char_entry += " (" + client->getIpid() + "): " + client->m_ooc_name;
if (client->m_is_afk)
char_entry += " (" + l_client->getIpid() + "): " + l_client->m_ooc_name;
if (l_client->m_is_afk)
char_entry += " [AFK]";
entries.append(char_entry);
}
@ -100,8 +106,8 @@ void AOClient::diceThrower(int argc, QStringList argv, bool p_roll)
QString AOClient::getAreaTimer(int area_idx, int timer_idx)
{
AreaData* l_area = server->m_areas[area_idx];
QTimer* l_timer;
AreaData *l_area = server->getAreaById(area_idx);
QTimer *l_timer;
QString l_timer_name = (timer_idx == 0) ? "Global timer" : "Timer " + QString::number(timer_idx);
if (timer_idx == 0)
@ -112,7 +118,7 @@ QString AOClient::getAreaTimer(int area_idx, int timer_idx)
return "Invalid timer ID.";
if (l_timer->isActive()) {
QTime l_current_time = QTime(0,0).addMSecs(l_timer->remainingTime());
QTime l_current_time = QTime(0, 0).addMSecs(l_timer->remainingTime());
return l_timer_name + " is at " + l_current_time.toString("hh:mm:ss.zzz");
}
@ -168,10 +174,10 @@ QString AOClient::getReprimand(bool f_positive)
{
if (f_positive) {
return ConfigManager::praiseList().at(genRand(0, ConfigManager::praiseList().size() - 1));
}
}
else {
return ConfigManager::reprimandsList().at(genRand(0, ConfigManager::reprimandsList().size() - 1));
}
}
}
bool AOClient::checkPasswordRequirements(QString f_username, QString f_password)

View File

@ -17,6 +17,10 @@
//////////////////////////////////////////////////////////////////////////////////////
#include "include/aoclient.h"
#include "include/aopacket.h"
#include "include/area_data.h"
#include "include/server.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!
@ -25,7 +29,7 @@ void AOClient::cmdPos(int argc, QStringList argv)
Q_UNUSED(argc);
changePosition(argv[0]);
updateEvidenceList(server->m_areas[m_current_area]);
updateEvidenceList(server->getAreaById(m_current_area));
}
void AOClient::cmdForcePos(int argc, QStringList argv)
@ -33,7 +37,7 @@ void AOClient::cmdForcePos(int argc, QStringList argv)
Q_UNUSED(argc);
bool ok;
QList<AOClient*> l_targets;
QList<AOClient *> l_targets;
int l_target_id = argv[1].toInt(&ok);
int l_forced_clients = 0;
if (!ok && argv[1] != "*") {
@ -41,7 +45,7 @@ void AOClient::cmdForcePos(int argc, QStringList argv)
return;
}
else if (ok) {
AOClient* l_target_client = server->getClientByID(l_target_id);
AOClient *l_target_client = server->getClientByID(l_target_id);
if (l_target_client != nullptr)
l_targets.append(l_target_client);
else {
@ -51,12 +55,13 @@ void AOClient::cmdForcePos(int argc, QStringList argv)
}
else if (argv[1] == "*") { // force all clients in the area
for (AOClient* client : qAsConst(server->m_clients)) {
if (client->m_current_area == m_current_area)
l_targets.append(client);
const QVector<AOClient *> l_clients = server->getClients();
for (AOClient *l_client : l_clients) {
if (l_client->m_current_area == m_current_area)
l_targets.append(l_client);
}
}
for (AOClient* l_target : l_targets) {
for (AOClient *l_target : l_targets) {
l_target->sendServerMessage("Position forcibly changed by CM.");
l_target->changePosition(argv[0]);
l_forced_clients++;
@ -69,7 +74,7 @@ void AOClient::cmdG(int argc, QStringList argv)
Q_UNUSED(argc);
QString l_sender_name = m_ooc_name;
QString l_sender_area = server->m_area_names.value(m_current_area);
QString l_sender_area = server->getAreaName(m_current_area);
QString l_sender_message = argv.join(" ");
//Slightly better readability
AOPacket l_mod_packet = AOPacket("CT", {"[G][" + m_ipid + "][" + l_sender_area + "]" + l_sender_name, l_sender_message});
@ -82,9 +87,9 @@ void AOClient::cmdNeed(int argc, QStringList argv)
{
Q_UNUSED(argc);
QString l_sender_area = server->m_area_names.value(m_current_area);
QString l_sender_area = server->getAreaName(m_current_area);
QString l_sender_message = argv.join(" ");
server->broadcast(AOPacket("CT",{"=== Advert ===\n[" + l_sender_area + "] needs " + l_sender_message+ "."}),Server::TARGET_TYPE::ADVERT);
server->broadcast(AOPacket("CT", {"=== Advert ===\n[" + l_sender_area + "] needs " + l_sender_message + "."}), Server::TARGET_TYPE::ADVERT);
}
void AOClient::cmdSwitch(int argc, QStringList argv)
@ -109,11 +114,11 @@ void AOClient::cmdRandomChar(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
int l_selected_char_id;
bool l_taken = true;
while (l_taken) {
l_selected_char_id = genRand(0, server->m_characters.size() - 1);
l_selected_char_id = genRand(0, server->getCharacterCount() - 1);
if (!l_area->charactersTaken().contains(l_selected_char_id)) {
l_taken = false;
}
@ -143,7 +148,7 @@ void AOClient::cmdPM(int argc, QStringList argv)
sendServerMessage("That does not look like a valid ID.");
return;
}
AOClient* l_target_client = server->getClientByID(l_target_id);
AOClient *l_target_client = server->getClientByID(l_target_id);
if (l_target_client == nullptr) {
sendServerMessage("No client with that ID found.");
return;
@ -154,7 +159,7 @@ void AOClient::cmdPM(int argc, QStringList argv)
}
QString l_message = argv.join(" "); //...which means it will not end up as part of the message
l_target_client->sendServerMessage("Message from " + m_ooc_name + " (" + QString::number(m_id) + "): " + l_message);
sendServerMessage("PM sent to " + QString::number(l_target_id) +". Message: " + l_message);
sendServerMessage("PM sent to " + QString::number(l_target_id) + ". Message: " + l_message);
}
void AOClient::cmdAnnounce(int argc, QStringList argv)
@ -178,9 +183,9 @@ void AOClient::cmdGM(int argc, QStringList argv)
Q_UNUSED(argc);
QString l_sender_name = m_ooc_name;
QString l_sender_area = server->m_area_names.value(m_current_area);
QString l_sender_area = server->getAreaName(m_current_area);
QString l_sender_message = argv.join(" ");
server->broadcast(AOPacket("CT", {"[G][" + l_sender_area + "]" + "["+ l_sender_name+"][M]", l_sender_message}),Server::TARGET_TYPE::MODCHAT);
server->broadcast(AOPacket("CT", {"[G][" + l_sender_area + "]" + "[" + l_sender_name + "][M]", l_sender_message}), Server::TARGET_TYPE::MODCHAT);
}
void AOClient::cmdLM(int argc, QStringList argv)
@ -189,7 +194,7 @@ void AOClient::cmdLM(int argc, QStringList argv)
QString l_sender_name = m_ooc_name;
QString l_sender_message = argv.join(" ");
server->broadcast(AOPacket("CT", {"["+ l_sender_name +"][M]", l_sender_message}), m_current_area);
server->broadcast(AOPacket("CT", {"[" + l_sender_name + "][M]", l_sender_message}), m_current_area);
}
void AOClient::cmdGimp(int argc, QStringList argv)
@ -203,7 +208,7 @@ void AOClient::cmdGimp(int argc, QStringList argv)
return;
}
AOClient* l_target = server->getClientByID(l_uid);
AOClient *l_target = server->getClientByID(l_uid);
if (l_target == nullptr) {
sendServerMessage("No client with that ID found.");
@ -230,7 +235,7 @@ void AOClient::cmdUnGimp(int argc, QStringList argv)
return;
}
AOClient* l_target = server->getClientByID(l_uid);
AOClient *l_target = server->getClientByID(l_uid);
if (l_target == nullptr) {
sendServerMessage("No client with that ID found.");
@ -257,7 +262,7 @@ void AOClient::cmdDisemvowel(int argc, QStringList argv)
return;
}
AOClient* l_target = server->getClientByID(l_uid);
AOClient *l_target = server->getClientByID(l_uid);
if (l_target == nullptr) {
sendServerMessage("No client with that ID found.");
@ -284,7 +289,7 @@ void AOClient::cmdUnDisemvowel(int argc, QStringList argv)
return;
}
AOClient* l_target = server->getClientByID(l_uid);
AOClient *l_target = server->getClientByID(l_uid);
if (l_target == nullptr) {
sendServerMessage("No client with that ID found.");
@ -311,7 +316,7 @@ void AOClient::cmdShake(int argc, QStringList argv)
return;
}
AOClient* l_target = server->getClientByID(l_uid);
AOClient *l_target = server->getClientByID(l_uid);
if (l_target == nullptr) {
sendServerMessage("No client with that ID found.");
@ -338,7 +343,7 @@ void AOClient::cmdUnShake(int argc, QStringList argv)
return;
}
AOClient* l_target = server->getClientByID(l_uid);
AOClient *l_target = server->getClientByID(l_uid);
if (l_target == nullptr) {
sendServerMessage("No client with that ID found.");
@ -392,7 +397,7 @@ void AOClient::cmdCharCurse(int argc, QStringList argv)
return;
}
AOClient* l_target = server->getClientByID(l_uid);
AOClient *l_target = server->getClientByID(l_uid);
if (l_target == nullptr) {
sendServerMessage("No client with that ID found.");
@ -424,14 +429,14 @@ void AOClient::cmdCharCurse(int argc, QStringList argv)
l_target->m_is_charcursed = true;
//Kick back to char select screen
// Kick back to char select screen
if (!l_target->m_charcurse_list.contains(server->getCharID(l_target->m_current_char))) {
l_target->changeCharacter(-1);
server->updateCharsTaken(server->m_areas.value(m_current_area));
server->updateCharsTaken(server->getAreaById(m_current_area));
l_target->sendPacket("DONE");
}
else {
server->updateCharsTaken(server->m_areas.value(m_current_area));
server->updateCharsTaken(server->getAreaById(m_current_area));
}
l_target->sendServerMessage("You have been charcursed!");
@ -449,7 +454,7 @@ void AOClient::cmdUnCharCurse(int argc, QStringList argv)
return;
}
AOClient* l_target = server->getClientByID(l_uid);
AOClient *l_target = server->getClientByID(l_uid);
if (l_target == nullptr) {
sendServerMessage("No client with that ID found.");
@ -462,7 +467,7 @@ void AOClient::cmdUnCharCurse(int argc, QStringList argv)
}
l_target->m_is_charcursed = false;
l_target->m_charcurse_list.clear();
server->updateCharsTaken(server->m_areas.value(m_current_area));
server->updateCharsTaken(server->getAreaById(m_current_area));
sendServerMessage("Uncharcursed player.");
l_target->sendServerMessage("You were uncharcursed.");
}
@ -486,7 +491,7 @@ void AOClient::cmdCharSelect(int argc, QStringList argv)
return;
}
AOClient* l_target = server->getClientByID(l_target_id);
AOClient *l_target = server->getClientByID(l_target_id);
if (l_target == nullptr) {
sendServerMessage("Unable to locate client with ID " + QString::number(l_target_id) + ".");
@ -496,7 +501,6 @@ void AOClient::cmdCharSelect(int argc, QStringList argv)
l_target->changeCharacter(-1);
l_target->sendPacket("DONE");
sendServerMessage("Client has been forced into character select!");
}
}
@ -511,7 +515,7 @@ void AOClient::cmdA(int argc, QStringList argv)
return;
}
AreaData* l_area = server->m_areas[l_area_id];
AreaData *l_area = server->getAreaById(l_area_id);
if (!l_area->owners().contains(m_id)) {
sendServerMessage("You are not CM in that area.");
return;
@ -527,12 +531,12 @@ void AOClient::cmdS(int argc, QStringList argv)
{
Q_UNUSED(argc);
int l_all_areas = server->m_areas.size() - 1;
int l_all_areas = server->getAreaCount() - 1;
QString l_sender_name = m_ooc_name;
QString l_ooc_message = argv.join(" ");
for (int i = 0; i <= l_all_areas; i++) {
if (server->m_areas[i]->owners().contains(m_id))
if (server->getAreaById(i)->owners().contains(m_id))
server->broadcast(AOPacket("CT", {"[CM]" + l_sender_name, l_ooc_message}), i);
}
}

View File

@ -17,6 +17,11 @@
//////////////////////////////////////////////////////////////////////////////////////
#include "include/aoclient.h"
#include "include/area_data.h"
#include "include/config_manager.h"
#include "include/db_manager.h"
#include "include/server.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!
@ -57,12 +62,12 @@ void AOClient::cmdBan(int argc, QStringList argv)
break;
}
const QList<AOClient*> l_targets = server->getClientsByIpid(l_ban.ipid);
for (AOClient* client : l_targets) {
const QList<AOClient *> l_targets = server->getClientsByIpid(l_ban.ipid);
for (AOClient *l_client : l_targets) {
if (!l_ban_logged) {
l_ban.ip = client->m_remote_ip;
l_ban.hdid = client->m_hwid;
server->db_manager->addBan(l_ban);
l_ban.ip = l_client->m_remote_ip;
l_ban.hdid = l_client->m_hwid;
server->getDatabaseManager()->addBan(l_ban);
sendServerMessage("Banned user with ipid " + l_ban.ipid + " for reason: " + l_ban.reason);
l_ban_logged = true;
}
@ -73,12 +78,12 @@ void AOClient::cmdBan(int argc, QStringList argv)
else {
l_ban_duration = "The heat death of the universe.";
}
int l_ban_id = server->db_manager->getBanID(l_ban.ip);
client->sendPacket("KB", {l_ban.reason + "\nID: " + QString::number(l_ban_id) + "\nUntil: " + l_ban_duration});
client->m_socket->close();
int l_ban_id = server->getDatabaseManager()->getBanID(l_ban.ip);
l_client->sendPacket("KB", {l_ban.reason + "\nID: " + QString::number(l_ban_id) + "\nUntil: " + l_ban_duration});
l_client->m_socket->close();
l_kick_counter++;
emit logBan(l_ban.moderator,l_ban.ipid,l_ban_duration,l_ban.reason);
emit logBan(l_ban.moderator, l_ban.ipid, l_ban_duration, l_ban.reason);
if (ConfigManager::discordBanWebhookEnabled())
emit server->banWebhookRequest(l_ban.ipid, l_ban.moderator, l_ban_duration, l_ban.reason, l_ban_id);
}
@ -88,7 +93,7 @@ void AOClient::cmdBan(int argc, QStringList argv)
// We're banning someone not connected.
if (!l_ban_logged) {
server->db_manager->addBan(l_ban);
server->getDatabaseManager()->addBan(l_ban);
sendServerMessage("Banned " + l_ban.ipid + " for reason: " + l_ban.reason);
}
}
@ -105,15 +110,15 @@ void AOClient::cmdKick(int argc, QStringList argv)
}
}
const QList<AOClient*> l_targets = server->getClientsByIpid(l_target_ipid);
for (AOClient* client : l_targets) {
client->sendPacket("KK", {l_reason});
client->m_socket->close();
const QList<AOClient *> l_targets = server->getClientsByIpid(l_target_ipid);
for (AOClient *l_client : l_targets) {
l_client->sendPacket("KK", {l_reason});
l_client->m_socket->close();
l_kick_counter++;
}
if (l_kick_counter > 0) {
if (ConfigManager::authType() == DataTypes::AuthType::ADVANCED){
if (ConfigManager::authType() == DataTypes::AuthType::ADVANCED) {
emit logKick(m_moderator_name, l_target_ipid, l_reason);
}
else {
@ -132,7 +137,8 @@ void AOClient::cmdMods(int argc, QStringList argv)
QStringList l_entries;
int l_online_count = 0;
for (AOClient* l_client : qAsConst(server->m_clients)) {
const QVector<AOClient *> l_clients = server->getClients();
for (AOClient *l_client : l_clients) {
if (l_client->m_authenticated) {
l_entries << "---";
if (ConfigManager::authType() != DataTypes::AuthType::SIMPLE)
@ -157,7 +163,7 @@ void AOClient::cmdCommands(int argc, QStringList argv)
QStringList l_entries;
l_entries << "Allowed commands:";
QMap<QString, CommandInfo>::const_iterator i;
for (i = commands.constBegin(); i!= commands.constEnd(); ++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
l_entries << "/" + i.key();
@ -168,7 +174,7 @@ void AOClient::cmdCommands(int argc, QStringList argv)
void AOClient::cmdHelp(int argc, QStringList argv)
{
if(argc > 1) {
if (argc > 1) {
sendServerMessage("Too many arguments. Please only use the command name.");
return;
}
@ -178,7 +184,7 @@ void AOClient::cmdHelp(int argc, QStringList argv)
if (l_command_info.usage.isEmpty() || l_command_info.text.isEmpty()) // my picoseconds :(
sendServerMessage("Unable to find the command " + l_command_name + ".");
else
sendServerMessage("==Help==\n" +l_command_info.usage + "\n" + l_command_info.text);
sendServerMessage("==Help==\n" + l_command_info.usage + "\n" + l_command_info.text);
}
void AOClient::cmdMOTD(int argc, QStringList argv)
@ -206,7 +212,7 @@ void AOClient::cmdBans(int argc, QStringList argv)
QStringList l_recent_bans;
l_recent_bans << "Last 5 bans:";
l_recent_bans << "-----";
const QList<DBManager::BanInfo> l_bans_list = server->db_manager->getRecentBans();
const QList<DBManager::BanInfo> l_bans_list = server->getDatabaseManager()->getRecentBans();
for (const DBManager::BanInfo &l_ban : l_bans_list) {
QString l_banned_until;
if (l_ban.duration == -2)
@ -235,7 +241,7 @@ void AOClient::cmdUnBan(int argc, QStringList argv)
sendServerMessage("Invalid ban ID.");
return;
}
else if (server->db_manager->invalidateBan(l_target_ban))
else if (server->getDatabaseManager()->invalidateBan(l_target_ban))
sendServerMessage("Successfully invalidated ban " + argv[0] + ".");
else
sendServerMessage("Couldn't invalidate ban " + argv[0] + ", are you sure it exists?");
@ -260,7 +266,7 @@ void AOClient::cmdMute(int argc, QStringList argv)
return;
}
AOClient* target = server->getClientByID(l_uid);
AOClient *target = server->getClientByID(l_uid);
if (target == nullptr) {
sendServerMessage("No client with that ID found.");
@ -287,7 +293,7 @@ void AOClient::cmdUnMute(int argc, QStringList argv)
return;
}
AOClient* l_target = server->getClientByID(l_uid);
AOClient *l_target = server->getClientByID(l_uid);
if (l_target == nullptr) {
sendServerMessage("No client with that ID found.");
@ -314,7 +320,7 @@ void AOClient::cmdOocMute(int argc, QStringList argv)
return;
}
AOClient* l_target = server->getClientByID(l_uid);
AOClient *l_target = server->getClientByID(l_uid);
if (l_target == nullptr) {
sendServerMessage("No client with that ID found.");
@ -341,7 +347,7 @@ void AOClient::cmdOocUnMute(int argc, QStringList argv)
return;
}
AOClient* l_target = server->getClientByID(l_uid);
AOClient *l_target = server->getClientByID(l_uid);
if (l_target == nullptr) {
sendServerMessage("No client with that ID found.");
@ -368,7 +374,7 @@ void AOClient::cmdBlockWtce(int argc, QStringList argv)
return;
}
AOClient* l_target = server->getClientByID(l_uid);
AOClient *l_target = server->getClientByID(l_uid);
if (l_target == nullptr) {
sendServerMessage("No client with that ID found.");
@ -395,7 +401,7 @@ void AOClient::cmdUnBlockWtce(int argc, QStringList argv)
return;
}
AOClient* l_target = server->getClientByID(l_uid);
AOClient *l_target = server->getClientByID(l_uid);
if (l_target == nullptr) {
sendServerMessage("No client with that ID found.");
@ -417,7 +423,7 @@ void AOClient::cmdAllowBlankposting(int argc, QStringList argv)
Q_UNUSED(argv);
QString l_sender_name = m_ooc_name;
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
l_area->toggleBlankposting();
if (l_area->blankpostingAllowed() == false) {
sendServerMessageArea(l_sender_name + " has set blankposting in the area to forbidden.");
@ -435,7 +441,7 @@ void AOClient::cmdBanInfo(int argc, QStringList argv)
QString l_lookup_type;
if (argc == 1) {
l_lookup_type = "banid";
l_lookup_type = "banid";
}
else if (argc == 2) {
l_lookup_type = argv[1];
@ -449,7 +455,7 @@ void AOClient::cmdBanInfo(int argc, QStringList argv)
return;
}
QString l_id = argv[0];
const QList<DBManager::BanInfo> l_bans = server->db_manager->getBanInfo(l_lookup_type, l_id);
const QList<DBManager::BanInfo> l_bans = server->getDatabaseManager()->getBanInfo(l_lookup_type, l_id);
for (const DBManager::BanInfo &l_ban : l_bans) {
QString l_banned_until;
if (l_ban.duration == -2)
@ -473,7 +479,7 @@ void AOClient::cmdReload(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
//Todo: Make this a signal when splitting AOClient and Server.
// Todo: Make this a signal when splitting AOClient and Server.
server->reloadSettings();
sendServerMessage("Reloaded configurations");
}
@ -483,7 +489,7 @@ void AOClient::cmdForceImmediate(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
l_area->toggleImmediate();
QString l_state = l_area->forceImmediate() ? "on." : "off.";
sendServerMessage("Forced immediate text processing in this area is now " + l_state);
@ -494,7 +500,7 @@ void AOClient::cmdAllowIniswap(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
l_area->toggleIniswap();
QString state = l_area->iniswapAllowed() ? "allowed." : "disallowed.";
sendServerMessage("Iniswapping in this area is now " + state);
@ -504,7 +510,7 @@ void AOClient::cmdPermitSaving(int argc, QStringList argv)
{
Q_UNUSED(argc);
AOClient* l_client = server->getClientByID(argv[0].toInt());
AOClient *l_client = server->getClientByID(argv[0].toInt());
if (l_client == nullptr) {
sendServerMessage("Invalid ID.");
return;
@ -530,7 +536,7 @@ void AOClient::cmdKickUid(int argc, QStringList argv)
return;
}
AOClient* l_target = server->getClientByID(l_uid);
AOClient *l_target = server->getClientByID(l_uid);
if (l_target == nullptr) {
sendServerMessage("No client with that ID found.");
return;
@ -560,7 +566,6 @@ void AOClient::cmdUpdateBan(int argc, QStringList argv)
return;
}
l_updated_info = QVariant(l_duration_seconds);
}
else if (argv[1] == "reason") {
QString l_args_str = argv[2];
@ -574,7 +579,7 @@ void AOClient::cmdUpdateBan(int argc, QStringList argv)
sendServerMessage("Invalid update type.");
return;
}
if (!server->db_manager->updateBan(l_ban_id, argv[1], l_updated_info)) {
if (!server->getDatabaseManager()->updateBan(l_ban_id, argv[1], l_updated_info)) {
sendServerMessage("There was an error updating the ban. Please confirm the ban ID is valid.");
return;
}
@ -599,8 +604,8 @@ void AOClient::cmdClearCM(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
AreaData* l_area = server->m_areas.value(m_current_area);
foreach (int l_client_id,l_area->owners()) {
AreaData *l_area = server->getAreaById(m_current_area);
foreach (int l_client_id, l_area->owners()) {
l_area->removeOwner(l_client_id);
}
arup(ARUPType::CM, true);

View File

@ -16,6 +16,12 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. //
//////////////////////////////////////////////////////////////////////////////////////
#include "include/aoclient.h"
#include "include/aopacket.h"
#include "include/area_data.h"
#include "include/music_manager.h"
#include "include/server.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!
@ -27,7 +33,7 @@ void AOClient::cmdPlay(int argc, QStringList argv)
sendServerMessage("You are blocked from changing the music.");
return;
}
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
QString l_song = argv.join(" ");
if (m_showname.isEmpty()) {
l_area->changeMusic(m_current_char, l_song);
@ -44,7 +50,7 @@ void AOClient::cmdCurrentMusic(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
if (!l_area->currentMusic().isEmpty() && !l_area->currentMusic().contains("~stop.mp3")) // dummy track for stopping music
sendServerMessage("The current song is " + l_area->currentMusic() + " played by " + l_area->musicPlayerBy());
else
@ -62,7 +68,7 @@ void AOClient::cmdBlockDj(int argc, QStringList argv)
return;
}
AOClient* l_target = server->getClientByID(l_uid);
AOClient *l_target = server->getClientByID(l_uid);
if (l_target == nullptr) {
sendServerMessage("No client with that ID found.");
@ -89,7 +95,7 @@ void AOClient::cmdUnBlockDj(int argc, QStringList argv)
return;
}
AOClient* l_target = server->getClientByID(l_uid);
AOClient *l_target = server->getClientByID(l_uid);
if (l_target == nullptr) {
sendServerMessage("No client with that ID found.");
@ -110,7 +116,7 @@ void AOClient::cmdToggleMusic(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
l_area->toggleMusic();
QString l_state = l_area->isMusicAllowed() ? "allowed." : "disallowed.";
sendServerMessage("Music in this area is now " + l_state);
@ -122,7 +128,7 @@ void AOClient::cmdToggleJukebox(int argc, QStringList argv)
Q_UNUSED(argv);
if (checkAuth(ACLFlags.value("CM")) | checkAuth(ACLFlags.value("Jukebox"))) {
AreaData* l_area = server->m_areas.value(m_current_area);
AreaData *l_area = server->getAreaById(m_current_area);
l_area->toggleJukebox();
QString l_state = l_area->isjukeboxEnabled() ? "enabled." : "disabled.";
sendServerMessageArea("The jukebox in this area has been " + l_state);
@ -136,11 +142,11 @@ void AOClient::cmdAddSong(int argc, QStringList argv)
{
Q_UNUSED(argc);
//This needs some explanation.
//Akashi has no concept of argument count,so any space is interpreted as a new element
//in the QStringList. This works fine until someone enters something with a space.
//Since we can't preencode those elements, we join all as a string and use a delimiter
//that does not exist in file and URL paths. I decided on the ol' reliable ','.
// This needs some explanation.
// Akashi has no concept of argument count,so any space is interpreted as a new element
// in the QStringList. This works fine until someone enters something with a space.
// Since we can't preencode those elements, we join all as a string and use a delimiter
// that does not exist in file and URL paths. I decided on the ol' reliable ','.
QString l_argv_string = argv.join(" ");
QStringList l_argv = l_argv_string.split(",");

View File

@ -17,6 +17,11 @@
//////////////////////////////////////////////////////////////////////////////////////
#include "include/aoclient.h"
#include "include/aopacket.h"
#include "include/area_data.h"
#include "include/config_manager.h"
#include "include/server.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!
@ -26,8 +31,8 @@ void AOClient::cmdFlip(int argc, QStringList argv)
Q_UNUSED(argv);
QString l_sender_name = m_ooc_name;
QStringList l_faces = {"heads","tails"};
QString l_face = l_faces[AOClient::genRand(0,1)];
QStringList l_faces = {"heads", "tails"};
QString l_face = l_faces[AOClient::genRand(0, 1)];
sendServerMessageArea(l_sender_name + " flipped a coin and got " + l_face + ".");
}
@ -43,7 +48,7 @@ void AOClient::cmdRollP(int argc, QStringList argv)
void AOClient::cmdTimer(int argc, QStringList argv)
{
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
// Called without arguments
// Shows a brief of all timers
@ -77,7 +82,7 @@ void AOClient::cmdTimer(int argc, QStringList argv)
// Select the proper timer
// Check against permissions if global timer is selected
QTimer* l_requested_timer;
QTimer *l_requested_timer;
if (l_timer_id == 0) {
if (!checkAuth(ACLFlags.value("GLOBAL_TIMER"))) {
sendServerMessage("You are not authorized to alter the global timer.");
@ -96,10 +101,10 @@ void AOClient::cmdTimer(int argc, QStringList argv)
// argument is a valid time
QTime l_requested_time = QTime::fromString(argv[1], "hh:mm:ss");
if (l_requested_time.isValid()) {
l_requested_timer->setInterval(QTime(0,0).msecsTo(l_requested_time));
l_requested_timer->setInterval(QTime(0, 0).msecsTo(l_requested_time));
l_requested_timer->start();
sendServerMessage("Set timer " + QString::number(l_timer_id) + " to " + argv[1] + ".");
AOPacket l_update_timer("TI", {QString::number(l_timer_id), "0", QString::number(QTime(0,0).msecsTo(l_requested_time))});
AOPacket l_update_timer("TI", {QString::number(l_timer_id), "0", QString::number(QTime(0, 0).msecsTo(l_requested_time))});
l_is_global ? server->broadcast(l_show_timer) : server->broadcast(l_show_timer, m_current_area); // Show the timer
l_is_global ? server->broadcast(l_update_timer) : server->broadcast(l_update_timer, m_current_area);
return;
@ -109,7 +114,7 @@ void AOClient::cmdTimer(int argc, QStringList argv)
if (argv[1] == "start") {
l_requested_timer->start();
sendServerMessage("Started timer " + QString::number(l_timer_id) + ".");
AOPacket l_update_timer("TI", {QString::number(l_timer_id), "0", QString::number(QTime(0,0).msecsTo(QTime(0,0).addMSecs(l_requested_timer->remainingTime())))});
AOPacket l_update_timer("TI", {QString::number(l_timer_id), "0", QString::number(QTime(0, 0).msecsTo(QTime(0, 0).addMSecs(l_requested_timer->remainingTime())))});
l_is_global ? server->broadcast(l_show_timer) : server->broadcast(l_show_timer, m_current_area);
l_is_global ? server->broadcast(l_update_timer) : server->broadcast(l_update_timer, m_current_area);
}
@ -117,7 +122,7 @@ void AOClient::cmdTimer(int argc, QStringList argv)
l_requested_timer->setInterval(l_requested_timer->remainingTime());
l_requested_timer->stop();
sendServerMessage("Stopped timer " + QString::number(l_timer_id) + ".");
AOPacket l_update_timer("TI", {QString::number(l_timer_id), "1", QString::number(QTime(0,0).msecsTo(QTime(0,0).addMSecs(l_requested_timer->interval())))});
AOPacket l_update_timer("TI", {QString::number(l_timer_id), "1", QString::number(QTime(0, 0).msecsTo(QTime(0, 0).addMSecs(l_requested_timer->interval())))});
l_is_global ? server->broadcast(l_update_timer) : server->broadcast(l_update_timer, m_current_area);
}
else if (argv[1] == "hide" || argv[1] == "unset") {
@ -134,7 +139,7 @@ void AOClient::cmdNoteCard(int argc, QStringList argv)
{
Q_UNUSED(argc);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
QString l_notecard = argv.join(" ");
l_area->addNotecard(m_current_char, l_notecard);
sendServerMessageArea(m_current_char + " wrote a note card.");
@ -145,7 +150,7 @@ void AOClient::cmdNoteCardClear(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
if (!l_area->addNotecard(m_current_char, QString())) {
sendServerMessageArea(m_current_char + " erased their note card.");
}
@ -156,7 +161,7 @@ void AOClient::cmdNoteCardReveal(int argc, QStringList argv)
Q_UNUSED(argc);
Q_UNUSED(argv);
AreaData* l_area = server->m_areas[m_current_area];
AreaData *l_area = server->getAreaById(m_current_area);
const QStringList l_notecards = l_area->getNotecards();
if (l_notecards.isEmpty()) {
@ -177,14 +182,14 @@ void AOClient::cmd8Ball(int argc, QStringList argv)
if (ConfigManager::magic8BallAnswers().isEmpty()) {
qWarning() << "8ball.txt is empty!";
sendServerMessage("8ball.txt is empty.");
}
}
else {
QString l_response = ConfigManager::magic8BallAnswers().at((genRand(1, ConfigManager::magic8BallAnswers().size() - 1)));
QString l_sender_name = m_ooc_name;
QString l_sender_message = argv.join(" ");
sendServerMessageArea(l_sender_name + " asked the magic 8-ball, \"" + l_sender_message + "\" and the answer is: " + l_response);
}
}
}
void AOClient::cmdSubTheme(int argc, QStringList argv)
@ -192,7 +197,8 @@ void AOClient::cmdSubTheme(int argc, QStringList argv)
Q_UNUSED(argc);
QString l_subtheme = argv.join(" ");
for (AOClient* l_client : qAsConst(server->m_clients)) {
const QVector<AOClient *> l_clients = server->getClients();
for (AOClient *l_client : l_clients) {
if (l_client->m_current_area == m_current_area)
l_client->sendPacket("ST", {l_subtheme, "1"});
}

View File

@ -19,15 +19,15 @@
#include <include/config_manager.h>
QSettings* ConfigManager::m_settings = new QSettings("config/config.ini", QSettings::IniFormat);
QSettings* ConfigManager::m_discord = new QSettings("config/discord.ini", QSettings::IniFormat);
QSettings* ConfigManager::m_areas = new QSettings("config/areas.ini", QSettings::IniFormat);
QSettings* ConfigManager::m_logtext = new QSettings("config/text/logtext.ini", QSettings::IniFormat);
ConfigManager::CommandSettings* ConfigManager::m_commands = new CommandSettings();
QElapsedTimer* ConfigManager::m_uptimeTimer = new QElapsedTimer;
MusicList* ConfigManager::m_musicList = new MusicList;
QHash<QString,ConfigManager::help>* ConfigManager::m_commands_help = new QHash<QString,ConfigManager::help>;
QStringList* ConfigManager::m_ordered_list = new QStringList;
QSettings *ConfigManager::m_settings = new QSettings("config/config.ini", QSettings::IniFormat);
QSettings *ConfigManager::m_discord = new QSettings("config/discord.ini", QSettings::IniFormat);
QSettings *ConfigManager::m_areas = new QSettings("config/areas.ini", QSettings::IniFormat);
QSettings *ConfigManager::m_logtext = new QSettings("config/text/logtext.ini", QSettings::IniFormat);
ConfigManager::CommandSettings *ConfigManager::m_commands = new CommandSettings();
QElapsedTimer *ConfigManager::m_uptimeTimer = new QElapsedTimer;
MusicList *ConfigManager::m_musicList = new MusicList;
QHash<QString, ConfigManager::help> *ConfigManager::m_commands_help = new QHash<QString, ConfigManager::help>;
QStringList *ConfigManager::m_ordered_list = new QStringList;
bool ConfigManager::verifyServerConfig()
{
@ -35,15 +35,15 @@ bool ConfigManager::verifyServerConfig()
QStringList l_directories{"config/", "config/text/"};
for (const QString &l_directory : l_directories) {
if (!dirExists(QFileInfo(l_directory))) {
qCritical() << l_directory + " does not exist!";
return false;
qCritical() << l_directory + " does not exist!";
return false;
}
}
// Verify config files
QStringList l_config_files{"config/config.ini", "config/areas.ini", "config/backgrounds.txt", "config/characters.txt", "config/music.json",
"config/discord.ini", "config/text/8ball.txt", "config/text/gimp.txt", "config/text/praise.txt",
"config/text/reprimands.txt","config/text/commandhelp.json","config/text/cdns.txt"};
"config/text/reprimands.txt", "config/text/commandhelp.json", "config/text/cdns.txt"};
for (const QString &l_file : l_config_files) {
if (!fileExists(QFileInfo(l_file))) {
qCritical() << l_file + " does not exist!";
@ -94,6 +94,8 @@ bool ConfigManager::verifyServerConfig()
m_commands->reprimands = (loadConfigFile("reprimands"));
m_commands->gimps = (loadConfigFile("gimp"));
m_commands->cdns = (loadConfigFile("cdns"));
if (m_commands->cdns.isEmpty())
m_commands->cdns = QStringList{"cdn.discord.com"};
m_uptimeTimer->start();
@ -102,7 +104,7 @@ bool ConfigManager::verifyServerConfig()
QString ConfigManager::bindIP()
{
return m_settings->value("Options/bind_ip","all").toString();
return m_settings->value("Options/bind_ip", "all").toString();
}
QStringList ConfigManager::charlist()
@ -138,22 +140,22 @@ MusicList ConfigManager::musiclist()
QJsonParseError l_error;
QJsonDocument l_music_list_json = QJsonDocument::fromJson(l_music_json.readAll(), &l_error);
if (!(l_error.error == QJsonParseError::NoError)) { //Non-Terminating error.
if (!(l_error.error == QJsonParseError::NoError)) { // Non-Terminating error.
qWarning() << "Unable to load musiclist. The following error was encounted : " + l_error.errorString();
return QMap<QString,QPair<QString,int>>{}; //Server can still run without music.
return QMap<QString, QPair<QString, int>>{}; // Server can still run without music.
}
// Akashi expects the musiclist to be contained in a JSON array, even if its only a single category.
QJsonArray l_Json_root_array = l_music_list_json.array();
QJsonObject l_child_obj;
QJsonArray l_child_array;
for (int i = 0; i <= l_Json_root_array.size() -1; i++){ //Iterate trough entire JSON file to assemble musiclist
for (int i = 0; i <= l_Json_root_array.size() - 1; i++) { // Iterate trough entire JSON file to assemble musiclist
l_child_obj = l_Json_root_array.at(i).toObject();
//Technically not a requirement, but neat for organisation.
// Technically not a requirement, but neat for organisation.
QString l_category_name = l_child_obj["category"].toString();
if (!l_category_name.isEmpty()) {
m_musicList->insert(l_category_name,{l_category_name,0});
m_musicList->insert(l_category_name, {l_category_name, 0});
m_ordered_list->append(l_category_name);
}
else {
@ -161,7 +163,7 @@ MusicList ConfigManager::musiclist()
}
l_child_array = l_child_obj["songs"].toArray();
for (int i = 0; i <= l_child_array.size() -1; i++){ // Inner for loop because a category can contain multiple songs.
for (int i = 0; i <= l_child_array.size() - 1; i++) { // Inner for loop because a category can contain multiple songs.
QJsonObject l_song_obj = l_child_array.at(i).toObject();
QString l_song_name = l_song_obj["name"].toString();
QString l_real_name = l_song_obj["realname"].toString();
@ -169,8 +171,8 @@ MusicList ConfigManager::musiclist()
l_real_name = l_song_name;
}
int l_song_duration = l_song_obj["length"].toVariant().toInt();
m_musicList->insert(l_song_name,{l_real_name,l_song_duration});
m_ordered_list->append(l_song_name);
m_musicList->insert(l_song_name, {l_real_name, l_song_duration});
m_ordered_list->append(l_song_name);
}
}
l_music_json.close();
@ -190,7 +192,7 @@ void ConfigManager::loadCommandHelp()
QJsonParseError l_error;
QJsonDocument l_help_list_json = QJsonDocument::fromJson(l_help_json.readAll(), &l_error);
if (!(l_error.error == QJsonParseError::NoError)) { //Non-Terminating error.
if (!(l_error.error == QJsonParseError::NoError)) { // Non-Terminating error.
qWarning() << "Unable to load help information. The following error occurred: " + l_error.errorString();
}
@ -198,7 +200,7 @@ void ConfigManager::loadCommandHelp()
QJsonArray l_Json_root_array = l_help_list_json.array();
QJsonObject l_child_obj;
for (int i = 0; i <= l_Json_root_array.size() -1; i++){
for (int i = 0; i <= l_Json_root_array.size() - 1; i++) {
l_child_obj = l_Json_root_array.at(i).toObject();
QString l_name = l_child_obj["name"].toString();
QString l_usage = l_child_obj["usage"].toString();
@ -209,12 +211,12 @@ void ConfigManager::loadCommandHelp()
l_help_information.usage = l_usage;
l_help_information.text = l_text;
m_commands_help->insert(l_name,l_help_information);
m_commands_help->insert(l_name, l_help_information);
}
}
}
QSettings* ConfigManager::areaData()
QSettings *ConfigManager::areaData()
{
return m_areas;
}
@ -222,7 +224,7 @@ QSettings* ConfigManager::areaData()
QStringList ConfigManager::sanitizedAreaNames()
{
QStringList l_area_names = m_areas->childGroups(); // invisibly does a lexicographical sort, because Qt is great like that
std::sort(l_area_names.begin(), l_area_names.end(), [] (const QString &a, const QString &b) {return a.split(":")[0].toInt() < b.split(":")[0].toInt();});
std::sort(l_area_names.begin(), l_area_names.end(), [](const QString &a, const QString &b) { return a.split(":")[0].toInt() < b.split(":")[0].toInt(); });
QStringList l_sanitized_area_names;
for (const QString &areaName : qAsConst(l_area_names)) {
QStringList l_nameSplit = areaName.split(":");
@ -452,13 +454,13 @@ QString ConfigManager::discordBanWebhookUrl()
bool ConfigManager::discordUptimeEnabled()
{
return m_discord->value("Discord/webhook_uptime_enabled","false").toBool();
return m_discord->value("Discord/webhook_uptime_enabled", "false").toBool();
}
int ConfigManager::discordUptimeTime()
{
bool ok;
int l_aliveTime = m_discord->value("Discord/webhook_uptime_time","60").toInt(&ok);
int l_aliveTime = m_discord->value("Discord/webhook_uptime_time", "60").toInt(&ok);
if (!ok) {
qWarning("alive_time is not an int");
l_aliveTime = 60;
@ -532,7 +534,7 @@ bool ConfigManager::passwordCanContainUsername()
QString ConfigManager::LogText(QString f_logtype)
{
return m_logtext->value("LogConfiguration/" + f_logtype,"").toString();
return m_logtext->value("LogConfiguration/" + f_logtype, "").toString();
}
int ConfigManager::afkTimeout()
@ -578,23 +580,23 @@ QStringList ConfigManager::cdnList()
bool ConfigManager::advertiseServer()
{
return m_settings->value("Advertiser/advertise","true").toBool();
return m_settings->value("Advertiser/advertise", "true").toBool();
}
bool ConfigManager::advertiserDebug()
{
return m_settings->value("Advertiser/debug","true").toBool();
return m_settings->value("Advertiser/debug", "true").toBool();
}
QUrl ConfigManager::advertiserIP()
{
qDebug() << m_settings->value("Advertiser/ms_ip","").toUrl();
return m_settings->value("Advertiser/ms_ip","").toUrl();
qDebug() << m_settings->value("Advertiser/ms_ip", "").toUrl();
return m_settings->value("Advertiser/ms_ip", "").toUrl();
}
QString ConfigManager::advertiserHostname()
{
return m_settings->value("Advertiser/hostname","").toString();
return m_settings->value("Advertiser/hostname", "").toString();
}
qint64 ConfigManager::uptime()

View File

@ -26,8 +26,8 @@ DBManager::DBManager() :
qWarning().noquote() << tr("Database Info: Database not found. Attempting to create new database.");
}
else {
//We should only check if a file is readable/writeable when it actually exists.
if(!db_info.isReadable() || !db_info.isWritable())
// We should only check if a file is readable/writeable when it actually exists.
if (!db_info.isReadable() || !db_info.isWritable())
qCritical() << tr("Database Error: Missing permissions. Check if \"%1\" is writable.").arg(db_filename);
}
@ -59,9 +59,11 @@ QPair<bool, QString> DBManager::isIPBanned(QString ipid)
long long current_time = QDateTime::currentDateTime().toSecsSinceEpoch();
if (ban_time + duration > current_time)
return {true, reason};
else return {false, nullptr};
else
return {false, nullptr};
}
else return {false, nullptr};
else
return {false, nullptr};
}
QPair<bool, QString> DBManager::isHDIDBanned(QString hdid)
@ -79,9 +81,11 @@ QPair<bool, QString> DBManager::isHDIDBanned(QString hdid)
long long current_time = QDateTime::currentDateTime().toSecsSinceEpoch();
if (ban_time + duration > current_time)
return {true, reason};
else return {false, nullptr};
else
return {false, nullptr};
}
else return {false, nullptr};
else
return {false, nullptr};
}
int DBManager::getBanID(QString hdid)
@ -98,7 +102,6 @@ int DBManager::getBanID(QString hdid)
}
}
int DBManager::getBanID(QHostAddress ip)
{
QSqlQuery query;
@ -199,7 +202,7 @@ bool DBManager::createUser(QString username, QString salt, QString password, uns
bool DBManager::deleteUser(QString username)
{
if (username == "root") {
//To prevent lockout scenarios where an admin may accidentally delete root.
// To prevent lockout scenarios where an admin may accidentally delete root.
return false;
}
@ -209,9 +212,9 @@ bool DBManager::deleteUser(QString username)
username_exists.addBindValue(username);
username_exists.exec();
username_exists.first();
//If EXISTS can't find a record, it returns 0.
// If EXISTS can't find a record, it returns 0.
if (username_exists.value(0).toInt() == 0)
//We were unable to locate an entry with this name.
// We were unable to locate an entry with this name.
return false;
}
{
@ -405,7 +408,7 @@ void DBManager::updateDB(int current_version)
QSqlQuery("ALTER TABLE bans ADD COLUMN MODERATOR TEXT");
Q_FALLTHROUGH();
case 1:
QSqlQuery ("PRAGMA user_version = " + QString::number(DB_VERSION));
QSqlQuery("PRAGMA user_version = " + QString::number(DB_VERSION));
break;
}
}

View File

@ -17,7 +17,9 @@
//////////////////////////////////////////////////////////////////////////////////////
#include "include/discord.h"
Discord::Discord(QObject* parent) :
#include "include/config_manager.h"
Discord::Discord(QObject *parent) :
QObject(parent)
{
m_nam = new QNetworkAccessManager();
@ -26,7 +28,7 @@ Discord::Discord(QObject* parent) :
m_uptimePostTimer = new QTimer;
connect(m_uptimePostTimer, &QTimer::timeout,
this, &Discord::onUptimeWebhookRequested);
this, &Discord::onUptimeWebhookRequested);
}
void Discord::onModcallWebhookRequested(const QString &f_name, const QString &f_area, const QString &f_reason, const QQueue<QString> &f_buffer)
@ -44,7 +46,7 @@ void Discord::onModcallWebhookRequested(const QString &f_name, const QString &f_
void Discord::onBanWebhookRequested(const QString &f_ipid, const QString &f_moderator, const QString &f_duration, const QString &f_reason, const int &f_banID)
{
m_request.setUrl(QUrl(ConfigManager::discordBanWebhookUrl()));
QJsonDocument l_json = constructBanJson(f_ipid,f_moderator, f_duration, f_reason, f_banID);
QJsonDocument l_json = constructBanJson(f_ipid, f_moderator, f_duration, f_reason, f_banID);
postJsonWebhook(l_json);
}
@ -65,18 +67,16 @@ QJsonDocument Discord::constructModcallJson(const QString &f_name, const QString
{
QJsonObject l_json;
QJsonArray l_array;
QJsonObject l_object {
QJsonObject l_object{
{"color", ConfigManager::discordWebhookColor()},
{"title", f_name + " filed a modcall in " + f_area},
{"description", f_reason}
};
{"description", f_reason}};
l_array.append(l_object);
if (!ConfigManager::discordModcallWebhookContent().isEmpty())
l_json["content"] = ConfigManager::discordModcallWebhookContent();
l_json["content"] = ConfigManager::discordModcallWebhookContent();
l_json["embeds"] = l_array;
return QJsonDocument(l_json);
}
@ -84,35 +84,33 @@ QJsonDocument Discord::constructBanJson(const QString &f_ipid, const QString &f_
{
QJsonObject l_json;
QJsonArray l_array;
QJsonObject l_object {
QJsonObject l_object{
{"color", ConfigManager::discordWebhookColor()},
{"title", "Ban issued by " + f_moderator},
{"description", "Client IPID : " + f_ipid + "\nBan ID: " + QString::number(f_banID) + "\nBan reason : " + f_reason +"\nBanned until : " +f_duration}
};
{"description", "Client IPID : " + f_ipid + "\nBan ID: " + QString::number(f_banID) + "\nBan reason : " + f_reason + "\nBanned until : " + f_duration}};
l_array.append(l_object);
l_json["embeds"] = l_array;
return QJsonDocument(l_json);
}
QJsonDocument Discord::constructUptimeJson(const QString& f_timeExpired)
QJsonDocument Discord::constructUptimeJson(const QString &f_timeExpired)
{
QJsonObject l_json;
QJsonArray l_array;
QJsonObject l_object {
QJsonObject l_object{
{"color", ConfigManager::discordWebhookColor()},
{"title", "Your server is online!"},
{"description", "Your server has been online for " + f_timeExpired}
};
{"description", "Your server has been online for " + f_timeExpired}};
l_array.append(l_object);
l_json["embeds"] = l_array;
return QJsonDocument(l_json);
}
QHttpMultiPart* Discord::constructLogMultipart(const QQueue<QString> &f_buffer) const
QHttpMultiPart *Discord::constructLogMultipart(const QQueue<QString> &f_buffer) const
{
QHttpMultiPart* l_multipart = new QHttpMultiPart();
QHttpMultiPart *l_multipart = new QHttpMultiPart();
QHttpPart l_file;
l_file.setRawHeader(QByteArray("Content-Disposition"), QByteArray("form-data; name=\"file\"; filename=\"log.txt\""));
l_file.setRawHeader(QByteArray("Content-Type"), QByteArray("plain/text"));
@ -143,7 +141,7 @@ void Discord::postMultipartWebhook(QHttpMultiPart &f_multipart)
return;
}
m_request.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data; boundary=" + f_multipart.boundary());
QNetworkReply* l_reply = m_nam->post(m_request, &f_multipart);
QNetworkReply *l_reply = m_nam->post(m_request, &f_multipart);
f_multipart.setParent(l_reply);
}

View File

@ -17,17 +17,17 @@
//////////////////////////////////////////////////////////////////////////////////////
#include "include/logger/u_logger.h"
ULogger::ULogger(QObject* parent) :
ULogger::ULogger(QObject *parent) :
QObject(parent)
{
switch (ConfigManager::loggingType()) {
case DataTypes::LogType::MODCALL :
writerModcall = new WriterModcall;
break;
case DataTypes::LogType::FULL :
case DataTypes::LogType::FULLAREA :
writerFull = new WriterFull;
break;
case DataTypes::LogType::MODCALL:
writerModcall = new WriterModcall;
break;
case DataTypes::LogType::FULL:
case DataTypes::LogType::FULLAREA:
writerFull = new WriterFull;
break;
}
loadLogtext();
}
@ -35,45 +35,45 @@ ULogger::ULogger(QObject* parent) :
ULogger::~ULogger()
{
switch (ConfigManager::loggingType()) {
case DataTypes::LogType::MODCALL :
writerModcall->deleteLater();
break;
case DataTypes::LogType::FULL :
case DataTypes::LogType::FULLAREA :
writerFull->deleteLater();
break;
case DataTypes::LogType::MODCALL:
writerModcall->deleteLater();
break;
case DataTypes::LogType::FULL:
case DataTypes::LogType::FULLAREA:
writerFull->deleteLater();
break;
}
}
void ULogger::logIC(const QString& f_char_name, const QString& f_ooc_name, const QString& f_ipid,
const QString& f_area_name, const QString& f_message)
void ULogger::logIC(const QString &f_char_name, const QString &f_ooc_name, const QString &f_ipid,
const QString &f_area_name, const QString &f_message)
{
QString l_time = QDateTime::currentDateTime().toString("ddd MMMM d yyyy | hh:mm:ss");
QString l_logEntry = QString(m_logtext.value("ic") + "\n").arg(l_time, f_char_name, f_ooc_name, f_ipid, f_area_name, f_message);
updateAreaBuffer(f_area_name,l_logEntry);
updateAreaBuffer(f_area_name, l_logEntry);
}
void ULogger::logOOC(const QString& f_char_name, const QString& f_ooc_name, const QString& f_ipid,
const QString& f_area_name, const QString& f_message)
void ULogger::logOOC(const QString &f_char_name, const QString &f_ooc_name, const QString &f_ipid,
const QString &f_area_name, const QString &f_message)
{
QString l_time = QDateTime::currentDateTime().toString("ddd MMMM d yyyy | hh:mm:ss");
QString l_logEntry = QString(m_logtext.value("ooc") + "\n")
.arg(l_time, f_char_name, f_ooc_name, f_ipid, f_area_name, f_message);
updateAreaBuffer(f_area_name,l_logEntry);
.arg(l_time, f_char_name, f_ooc_name, f_ipid, f_area_name, f_message);
updateAreaBuffer(f_area_name, l_logEntry);
}
void ULogger::logLogin(const QString& f_char_name, const QString& f_ooc_name, const QString& f_moderator_name,
const QString& f_ipid, const QString& f_area_name, const bool &f_success)
void ULogger::logLogin(const QString &f_char_name, const QString &f_ooc_name, const QString &f_moderator_name,
const QString &f_ipid, const QString &f_area_name, const bool &f_success)
{
QString l_time = QDateTime::currentDateTime().toString("ddd MMMM d yyyy | hh:mm:ss");
QString l_success = f_success ? "SUCCESS][" + f_moderator_name : "FAILED][" + f_moderator_name;
QString l_logEntry = QString(m_logtext.value("login") + "\n")
.arg(l_time, l_success, f_ipid, f_char_name, f_ooc_name);
.arg(l_time, l_success, f_ipid, f_char_name, f_ooc_name);
updateAreaBuffer(f_area_name, l_logEntry);
}
void ULogger::logCMD(const QString& f_char_name,const QString& f_ipid, const QString& f_ooc_name, const QString& f_command,
const QStringList& f_args, const QString& f_area_name)
void ULogger::logCMD(const QString &f_char_name, const QString &f_ipid, const QString &f_ooc_name, const QString &f_command,
const QStringList &f_args, const QString &f_area_name)
{
QString l_time = QDateTime::currentDateTime().toString("ddd MMMM d yyyy | hh:mm:ss");
QString l_logEntry;
@ -81,44 +81,44 @@ void ULogger::logCMD(const QString& f_char_name,const QString& f_ipid, const QSt
// These must be filtered out
if (f_command == "login") {
l_logEntry = QString(m_logtext.value("cmdlogin") + "\n")
.arg(l_time, f_area_name, f_char_name, f_ooc_name, f_ipid);
.arg(l_time, f_area_name, f_char_name, f_ooc_name, f_ipid);
}
else if (f_command == "rootpass") {
l_logEntry = QString(m_logtext.value("cmdrootpass") + "\n")
.arg(l_time, f_area_name, f_char_name, f_ooc_name, f_ipid);
.arg(l_time, f_area_name, f_char_name, f_ooc_name, f_ipid);
}
else if (f_command == "adduser" && !f_args.isEmpty()) {
l_logEntry = QString(m_logtext.value("adduser") + "\n")
.arg(l_time, f_area_name, f_char_name, f_ooc_name, f_args.at(0), f_ipid);
l_logEntry = QString(m_logtext.value("adduser") + "\n")
.arg(l_time, f_area_name, f_char_name, f_ooc_name, f_args.at(0), f_ipid);
}
else {
l_logEntry = QString(m_logtext.value("cmd") + "\n")
.arg(l_time, f_area_name, f_char_name, f_ooc_name, f_command, f_args.join(" "), f_ipid);
.arg(l_time, f_area_name, f_char_name, f_ooc_name, f_command, f_args.join(" "), f_ipid);
}
updateAreaBuffer(f_area_name,l_logEntry);
updateAreaBuffer(f_area_name, l_logEntry);
}
void ULogger::logKick(const QString& f_moderator, const QString& f_target_ipid)
void ULogger::logKick(const QString &f_moderator, const QString &f_target_ipid)
{
QString l_time = QDateTime::currentDateTime().toString("ddd MMMM d yyyy | hh:mm:ss");
QString l_logEntry = QString(m_logtext.value("kick") + "\n")
.arg(l_time, f_moderator, f_target_ipid);
updateAreaBuffer("SERVER",l_logEntry);
.arg(l_time, f_moderator, f_target_ipid);
updateAreaBuffer("SERVER", l_logEntry);
}
void ULogger::logBan(const QString &f_moderator, const QString &f_target_ipid, const QString &f_duration)
{
QString l_time = QDateTime::currentDateTime().toString("ddd MMMM d yyyy | hh:mm:ss");
QString l_logEntry = QString(m_logtext.value("ban") + "\n")
.arg(l_time, f_moderator, f_target_ipid, f_duration);
updateAreaBuffer("SERVER",l_logEntry);
.arg(l_time, f_moderator, f_target_ipid, f_duration);
updateAreaBuffer("SERVER", l_logEntry);
}
void ULogger::logModcall(const QString &f_char_name, const QString &f_ipid, const QString &f_ooc_name, const QString &f_area_name)
{
QString l_time = QDateTime::currentDateTime().toString("ddd MMMM d yyyy | hh:mm:ss");
QString l_logEvent = QString(m_logtext.value("modcall") + "\n")
.arg(l_time, f_area_name, f_char_name, f_ooc_name, f_ipid);
.arg(l_time, f_area_name, f_char_name, f_ooc_name, f_ipid);
updateAreaBuffer(f_area_name, l_logEvent);
if (ConfigManager::loggingType() == DataTypes::LogType::MODCALL) {
@ -126,18 +126,18 @@ void ULogger::logModcall(const QString &f_char_name, const QString &f_ipid, cons
}
}
void ULogger::logConnectionAttempt(const QString& f_ip_address, const QString& f_ipid, const QString& f_hwid)
void ULogger::logConnectionAttempt(const QString &f_ip_address, const QString &f_ipid, const QString &f_hwid)
{
QString l_time = QDateTime::currentDateTime().toString("ddd MMMM d yyyy | hh:mm:ss");
QString l_logEntry = QString(m_logtext.value("connect") + "\n")
.arg(l_time, f_ip_address, f_ipid, f_hwid);
updateAreaBuffer("SERVER",l_logEntry);
.arg(l_time, f_ip_address, f_ipid, f_hwid);
updateAreaBuffer("SERVER", l_logEntry);
}
void ULogger::loadLogtext()
{
//All of this to prevent one single clazy warning from appearing.
for (auto iterator = m_logtext.keyBegin(), end = m_logtext.keyEnd(); iterator != end; ++iterator){
// All of this to prevent one single clazy warning from appearing.
for (auto iterator = m_logtext.keyBegin(), end = m_logtext.keyEnd(); iterator != end; ++iterator) {
QString l_tempstring = ConfigManager::LogText(iterator.operator*());
if (!l_tempstring.isEmpty()) {
m_logtext[iterator.operator*()] = l_tempstring;
@ -145,9 +145,9 @@ void ULogger::loadLogtext()
}
}
void ULogger::updateAreaBuffer(const QString& f_area_name, const QString& f_log_entry)
void ULogger::updateAreaBuffer(const QString &f_area_name, const QString &f_log_entry)
{
QQueue<QString>l_buffer = m_bufferMap.value(f_area_name);
QQueue<QString> l_buffer = m_bufferMap.value(f_area_name);
if (l_buffer.length() <= ConfigManager::logBuffer()) {
l_buffer.enqueue(f_log_entry);
@ -158,7 +158,7 @@ void ULogger::updateAreaBuffer(const QString& f_area_name, const QString& f_log_
}
m_bufferMap.insert(f_area_name, l_buffer);
if (ConfigManager::loggingType() == DataTypes::LogType::FULL){
if (ConfigManager::loggingType() == DataTypes::LogType::FULL) {
writerFull->flush(f_log_entry);
}
if (ConfigManager::loggingType() == DataTypes::LogType::FULLAREA) {
@ -166,7 +166,7 @@ void ULogger::updateAreaBuffer(const QString& f_area_name, const QString& f_log_
}
}
QQueue<QString> ULogger::buffer(const QString& f_area_name)
QQueue<QString> ULogger::buffer(const QString &f_area_name)
{
return m_bufferMap.value(f_area_name);
}

View File

@ -17,7 +17,7 @@
//////////////////////////////////////////////////////////////////////////////////////
#include "include/logger/writer_full.h"
WriterFull::WriterFull(QObject* parent) :
WriterFull::WriterFull(QObject *parent) :
QObject(parent)
{
l_dir.setPath("logs/");
@ -47,4 +47,3 @@ void WriterFull::flush(const QString f_entry, const QString f_area_name)
}
l_logfile.close();
};

View File

@ -17,7 +17,7 @@
//////////////////////////////////////////////////////////////////////////////////////
#include "include/logger/writer_modcall.h"
WriterModcall::WriterModcall(QObject* parent) :
WriterModcall::WriterModcall(QObject *parent) :
QObject(parent)
{
l_dir.setPath("logs/");
@ -43,5 +43,4 @@ void WriterModcall::flush(const QString f_area_name, QQueue<QString> f_buffer)
}
l_logfile.close();
};

View File

@ -1,11 +1,14 @@
#include "include/music_manager.h"
MusicManager::MusicManager(QObject *parent, QStringList f_root_ordered, QStringList f_cdns, QMap<QString, QPair<QString, int>> f_root_list) :
#include "include/aopacket.h"
#include "include/config_manager.h"
MusicManager::MusicManager(QStringList f_root_ordered, QStringList f_cdns, QMap<QString, QPair<QString, int>> f_root_list, QObject *parent) :
QObject(parent),
m_root_list(f_root_list),
m_root_ordered(f_root_ordered)
{
m_custom_lists = new QHash<int,QMap<QString,QPair<QString,int>>>;
m_custom_lists = new QHash<int, QMap<QString, QPair<QString, int>>>;
if (!f_cdns.isEmpty()) {
m_cdns = f_cdns;
}
@ -13,7 +16,6 @@ MusicManager::MusicManager(QObject *parent, QStringList f_root_ordered, QStringL
MusicManager::~MusicManager()
{
}
QStringList MusicManager::musiclist(int f_area_id)
@ -33,28 +35,27 @@ QStringList MusicManager::rootMusiclist()
bool MusicManager::registerArea(int f_area_id)
{
if(m_custom_lists->contains(f_area_id)) {
//This area is already registered. We can't add it.
if (m_custom_lists->contains(f_area_id)) {
// This area is already registered. We can't add it.
return false;
}
m_custom_lists->insert(f_area_id,{});
m_global_enabled.insert(f_area_id,true);
m_custom_lists->insert(f_area_id, {});
m_global_enabled.insert(f_area_id, true);
return true;
}
bool MusicManager::validateSong(QString f_song_name, QStringList f_approved_cdns)
{
QStringList l_extensions = {".opus", ".ogg", ".mp3", ".wav" };
QStringList l_extensions = {".opus", ".ogg", ".mp3", ".wav"};
bool l_cdn_approved = false;
//Check if URL formatted.
// Check if URL formatted.
if (f_song_name.contains("/")) {
//Only allow HTTPS/HTTP sources.
// Only allow HTTPS/HTTP sources.
if (f_song_name.startsWith("https://") || f_song_name.startsWith("http://")) {
for (const QString &l_cdn : qAsConst(f_approved_cdns)) {
//Iterate trough all available CDNs to find an approved match
if (f_song_name.startsWith("https://" + l_cdn + "/", Qt::CaseInsensitive)
|| f_song_name.startsWith("http://" + l_cdn + "/", Qt::CaseInsensitive)) {
// Iterate trough all available CDNs to find an approved match
if (f_song_name.startsWith("https://" + l_cdn + "/", Qt::CaseInsensitive) || f_song_name.startsWith("http://" + l_cdn + "/", Qt::CaseInsensitive)) {
l_cdn_approved = true;
break;
}
@ -68,9 +69,10 @@ bool MusicManager::validateSong(QString f_song_name, QStringList f_approved_cdns
}
}
bool l_suffix_found = false;;
bool l_suffix_found = false;
;
for (const QString &suffix : qAsConst(l_extensions)) {
if (f_song_name.endsWith(suffix)){
if (f_song_name.endsWith(suffix)) {
l_suffix_found = true;
break;
}
@ -85,7 +87,7 @@ bool MusicManager::validateSong(QString f_song_name, QStringList f_approved_cdns
bool MusicManager::addCustomSong(QString f_song_name, QString f_real_name, int f_duration, int f_area_id)
{
//Validate if simple name.
// Validate if simple name.
QString l_song_name = f_song_name;
if (f_song_name.split(".").size() == 1) {
l_song_name = l_song_name + ".opus";
@ -109,16 +111,16 @@ bool MusicManager::addCustomSong(QString f_song_name, QString f_real_name, int f
return false;
}
if (m_customs_ordered.value(f_area_id).contains(l_song_name)){
if (m_customs_ordered.value(f_area_id).contains(l_song_name)) {
return false;
}
// There should be a way to directly insert into the QMap. Too bad!
MusicList l_custom_list = m_custom_lists->value(f_area_id);
l_custom_list.insert(l_song_name,{l_real_name,f_duration});
m_custom_lists->insert(f_area_id,l_custom_list);
m_customs_ordered.insert(f_area_id,(QStringList {m_customs_ordered.value(f_area_id)} << l_song_name));
emit sendAreaFMPacket(AOPacket("FM",musiclist(f_area_id)), f_area_id);
l_custom_list.insert(l_song_name, {l_real_name, f_duration});
m_custom_lists->insert(f_area_id, l_custom_list);
m_customs_ordered.insert(f_area_id, (QStringList{m_customs_ordered.value(f_area_id)} << l_song_name));
emit sendAreaFMPacket(AOPacket("FM", musiclist(f_area_id)), f_area_id);
return true;
}
@ -142,28 +144,28 @@ bool MusicManager::addCustomCategory(QString f_category_name, int f_area_id)
return false;
}
QMap<QString,QPair<QString,int>> l_custom_list = m_custom_lists->value(f_area_id);
l_custom_list.insert(l_category_name,{l_category_name,0});
m_custom_lists->insert(f_area_id,l_custom_list);
m_customs_ordered.insert(f_area_id,(QStringList {m_customs_ordered.value(f_area_id)} << l_category_name));
emit sendAreaFMPacket(AOPacket("FM",musiclist(f_area_id)), f_area_id);
QMap<QString, QPair<QString, int>> l_custom_list = m_custom_lists->value(f_area_id);
l_custom_list.insert(l_category_name, {l_category_name, 0});
m_custom_lists->insert(f_area_id, l_custom_list);
m_customs_ordered.insert(f_area_id, (QStringList{m_customs_ordered.value(f_area_id)} << l_category_name));
emit sendAreaFMPacket(AOPacket("FM", musiclist(f_area_id)), f_area_id);
return true;
}
bool MusicManager::removeCategorySong(QString f_songcategory_name, int f_area_id)
{
if (!m_root_list.contains(f_songcategory_name)){
if (!m_root_list.contains(f_songcategory_name)) {
MusicList l_custom_list = m_custom_lists->value(f_area_id);
if (l_custom_list.contains(f_songcategory_name)) {
l_custom_list.remove(f_songcategory_name);
m_custom_lists->insert(f_area_id,l_custom_list);
m_custom_lists->insert(f_area_id, l_custom_list);
//Updating the list alias too.
// Updating the list alias too.
QStringList l_customs_ordered = m_customs_ordered.value(f_area_id);
l_customs_ordered.removeAll(f_songcategory_name);
m_customs_ordered.insert(f_area_id, l_customs_ordered);
emit sendAreaFMPacket(AOPacket("FM",musiclist(f_area_id)), f_area_id);
emit sendAreaFMPacket(AOPacket("FM", musiclist(f_area_id)), f_area_id);
return true;
} // Fallthrough
}
@ -176,7 +178,7 @@ bool MusicManager::toggleRootEnabled(int f_area_id)
if (m_global_enabled.value(f_area_id)) {
sanitiseCustomList(f_area_id);
}
emit sendAreaFMPacket(AOPacket("FM",musiclist(f_area_id)), f_area_id);
emit sendAreaFMPacket(AOPacket("FM", musiclist(f_area_id)), f_area_id);
return m_global_enabled.value(f_area_id);
}
@ -185,8 +187,8 @@ void MusicManager::sanitiseCustomList(int f_area_id)
MusicList l_sanitised_list;
QStringList l_sanitised_ordered = m_customs_ordered.value(f_area_id);
for (auto iterator = m_custom_lists->value(f_area_id).keyBegin(),
end = m_custom_lists->value(f_area_id).keyEnd(); iterator != end; ++iterator)
{
end = m_custom_lists->value(f_area_id).keyEnd();
iterator != end; ++iterator) {
QString l_key = iterator.operator*();
if (!m_root_list.contains(l_key)) {
l_sanitised_list.insert(l_key, m_custom_lists->value(f_area_id).value(l_key));
@ -194,7 +196,6 @@ void MusicManager::sanitiseCustomList(int f_area_id)
else {
l_sanitised_ordered.removeAll(l_key);
}
}
m_custom_lists->insert(f_area_id, l_sanitised_list);
m_customs_ordered.insert(f_area_id, l_sanitised_ordered);
@ -203,7 +204,7 @@ void MusicManager::sanitiseCustomList(int f_area_id)
void MusicManager::clearCustomList(int f_area_id)
{
m_custom_lists->remove(f_area_id);
m_custom_lists->insert(f_area_id,{});
m_custom_lists->insert(f_area_id, {});
m_customs_ordered.remove(f_area_id);
m_customs_ordered.insert(f_area_id, {});
}

View File

@ -17,7 +17,16 @@
//////////////////////////////////////////////////////////////////////////////////////
#include "include/aoclient.h"
void AOClient::pktDefault(AreaData* area, int argc, QStringList argv, AOPacket packet)
#include <QQueue>
#include "include/aopacket.h"
#include "include/area_data.h"
#include "include/config_manager.h"
#include "include/db_manager.h"
#include "include/music_manager.h"
#include "include/server.h"
void AOClient::pktDefault(AreaData *area, int argc, QStringList argv, AOPacket packet)
{
Q_UNUSED(area);
Q_UNUSED(argc);
@ -29,7 +38,7 @@ void AOClient::pktDefault(AreaData* area, int argc, QStringList argv, AOPacket p
#endif
}
void AOClient::pktHardwareId(AreaData* area, int argc, QStringList argv, AOPacket packet)
void AOClient::pktHardwareId(AreaData *area, int argc, QStringList argv, AOPacket packet)
{
Q_UNUSED(area);
Q_UNUSED(argc);
@ -37,16 +46,16 @@ void AOClient::pktHardwareId(AreaData* area, int argc, QStringList argv, AOPacke
m_hwid = argv[0];
emit server->logConnectionAttempt(m_remote_ip.toString(), m_ipid, m_hwid);
auto l_ban = server->db_manager->isHDIDBanned(m_hwid);
auto l_ban = server->getDatabaseManager()->isHDIDBanned(m_hwid);
if (l_ban.first) {
sendPacket("BD", {l_ban.second + "\nBan ID: " + QString::number(server->db_manager->getBanID(m_hwid))});
sendPacket("BD", {l_ban.second + "\nBan ID: " + QString::number(server->getDatabaseManager()->getBanID(m_hwid))});
m_socket->close();
return;
}
sendPacket("ID", {QString::number(m_id), "akashi", QCoreApplication::applicationVersion()});
}
void AOClient::pktSoftwareId(AreaData* area, int argc, QStringList argv, AOPacket packet)
void AOClient::pktSoftwareId(AreaData *area, int argc, QStringList argv, AOPacket packet)
{
Q_UNUSED(area);
Q_UNUSED(argc);
@ -56,14 +65,12 @@ void AOClient::pktSoftwareId(AreaData* area, int argc, QStringList argv, AOPacke
// The only ones that are critical to ensuring the server works are
// "noencryption" and "fastloading"
QStringList l_feature_list = {
"noencryption", "yellowtext", "prezoom",
"flipping", "customobjections", "fastloading",
"deskmod", "evidence", "cccc_ic_support",
"arup", "casing_alerts", "modcall_reason",
"looping_sfx", "additive", "effects",
"y_offset", "expanded_desk_mods", "auth_packet"
};
"noencryption", "yellowtext", "prezoom",
"flipping", "customobjections", "fastloading",
"deskmod", "evidence", "cccc_ic_support",
"arup", "casing_alerts", "modcall_reason",
"looping_sfx", "additive", "effects",
"y_offset", "expanded_desk_mods", "auth_packet"};
m_version.string = argv[1];
QRegularExpression rx("\\b(\\d+)\\.(\\d+)\\.(\\d+)\\b"); // matches X.X.X (e.g. 2.9.0, 2.4.10, etc.)
@ -74,16 +81,16 @@ void AOClient::pktSoftwareId(AreaData* area, int argc, QStringList argv, AOPacke
m_version.minor = l_match.captured(3).toInt();
}
sendPacket("PN", {QString::number(server->m_player_count), QString::number(ConfigManager::maxPlayers()), ConfigManager::serverDescription()});
sendPacket("PN", {QString::number(server->getPlayerCount()), QString::number(ConfigManager::maxPlayers()), ConfigManager::serverDescription()});
sendPacket("FL", l_feature_list);
if (ConfigManager::assetUrl().isValid()) {
QByteArray l_asset_url = ConfigManager::assetUrl().toEncoded(QUrl::EncodeSpaces);
sendPacket("ASS", {l_asset_url});
QByteArray l_asset_url = ConfigManager::assetUrl().toEncoded(QUrl::EncodeSpaces);
sendPacket("ASS", {l_asset_url});
}
}
void AOClient::pktBeginLoad(AreaData* area, int argc, QStringList argv, AOPacket packet)
void AOClient::pktBeginLoad(AreaData *area, int argc, QStringList argv, AOPacket packet)
{
Q_UNUSED(area);
Q_UNUSED(argc);
@ -93,30 +100,30 @@ void AOClient::pktBeginLoad(AreaData* area, int argc, QStringList argv, AOPacket
// Evidence isn't loaded during this part anymore
// As a result, we can always send "0" for evidence length
// Client only cares about what it gets from LE
sendPacket("SI", {QString::number(server->m_characters.length()), "0", QString::number(server->m_area_names.length() + server->m_music_list.length())});
sendPacket("SI", {QString::number(server->getCharacterCount()), "0", QString::number(server->getAreaCount() + server->getMusicList().length())});
}
void AOClient::pktRequestChars(AreaData* area, int argc, QStringList argv, AOPacket packet)
void AOClient::pktRequestChars(AreaData *area, int argc, QStringList argv, AOPacket packet)
{
Q_UNUSED(area);
Q_UNUSED(argc);
Q_UNUSED(argv);
Q_UNUSED(packet);
sendPacket("SC", server->m_characters);
sendPacket("SC", server->getCharacters());
}
void AOClient::pktRequestMusic(AreaData* area, int argc, QStringList argv, AOPacket packet)
void AOClient::pktRequestMusic(AreaData *area, int argc, QStringList argv, AOPacket packet)
{
Q_UNUSED(area);
Q_UNUSED(argc);
Q_UNUSED(argv);
Q_UNUSED(packet);
sendPacket("SM", server->m_area_names + server->m_music_list);
sendPacket("SM", server->getAreaNames() + server->getMusicList());
}
void AOClient::pktLoadingDone(AreaData* area, int argc, QStringList argv, AOPacket packet)
void AOClient::pktLoadingDone(AreaData *area, int argc, QStringList argv, AOPacket packet)
{
Q_UNUSED(argc);
Q_UNUSED(argv);
@ -132,44 +139,43 @@ void AOClient::pktLoadingDone(AreaData* area, int argc, QStringList argv, AOPack
return;
}
server->m_player_count++;
m_joined = true;
server->updateCharsTaken(area);
sendEvidenceList(area);
sendPacket("HP", {"1", QString::number(area->defHP())});
sendPacket("HP", {"2", QString::number(area->proHP())});
sendPacket("FA", server->m_area_names);
//Here lies OPPASS, the genius of FanatSors who send the modpass to everyone in plain text.
sendPacket("FA", server->getAreaNames());
// Here lies OPPASS, the genius of FanatSors who send the modpass to everyone in plain text.
sendPacket("DONE");
sendPacket("BN", {area->background()});
sendServerMessage("=== MOTD ===\r\n" + ConfigManager::motd() + "\r\n=============");
fullArup(); // Give client all the area data
if (server->timer->isActive()) {
sendPacket("TI", {"0", "2"});
sendPacket("TI", {"0", "0", QString::number(QTime(0,0).msecsTo(QTime(0,0).addMSecs(server->timer->remainingTime())))});
sendPacket("TI", {"0", "0", QString::number(QTime(0, 0).msecsTo(QTime(0, 0).addMSecs(server->timer->remainingTime())))});
}
else {
sendPacket("TI", {"0", "3"});
}
const QList<QTimer*> l_timers = area->timers();
for (QTimer* l_timer : l_timers) {
const QList<QTimer *> l_timers = area->timers();
for (QTimer *l_timer : l_timers) {
int l_timer_id = area->timers().indexOf(l_timer) + 1;
if (l_timer->isActive()) {
sendPacket("TI", {QString::number(l_timer_id), "2"});
sendPacket("TI", {QString::number(l_timer_id), "0", QString::number(QTime(0,0).msecsTo(QTime(0,0).addMSecs(l_timer->remainingTime())))});
sendPacket("TI", {QString::number(l_timer_id), "0", QString::number(QTime(0, 0).msecsTo(QTime(0, 0).addMSecs(l_timer->remainingTime())))});
}
else {
sendPacket("TI", {QString::number(l_timer_id), "3"});
}
}
emit server->updatePlayerCount(server->m_player_count);
emit joined();
area->clientJoinedArea(-1, m_id);
arup(ARUPType::PLAYER_COUNT, true); // Tell everyone there is a new player
}
void AOClient::pktCharPassword(AreaData* area, int argc, QStringList argv, AOPacket packet)
void AOClient::pktCharPassword(AreaData *area, int argc, QStringList argv, AOPacket packet)
{
Q_UNUSED(area);
Q_UNUSED(argc);
@ -178,7 +184,7 @@ void AOClient::pktCharPassword(AreaData* area, int argc, QStringList argv, AOPac
m_password = argv[0];
}
void AOClient::pktSelectChar(AreaData* area, int argc, QStringList argv, AOPacket packet)
void AOClient::pktSelectChar(AreaData *area, int argc, QStringList argv, AOPacket packet)
{
Q_UNUSED(area);
Q_UNUSED(argc);
@ -194,7 +200,7 @@ void AOClient::pktSelectChar(AreaData* area, int argc, QStringList argv, AOPacke
m_char_id = l_selected_char_id;
}
void AOClient::pktIcChat(AreaData* area, int argc, QStringList argv, AOPacket packet)
void AOClient::pktIcChat(AreaData *area, int argc, QStringList argv, AOPacket packet)
{
Q_UNUSED(argc);
Q_UNUSED(argv);
@ -204,7 +210,7 @@ void AOClient::pktIcChat(AreaData* area, int argc, QStringList argv, AOPacket pa
return;
}
if (!server->can_send_ic_messages) {
if (!server->isMessageAllowed()) {
return;
}
@ -216,14 +222,13 @@ void AOClient::pktIcChat(AreaData* area, int argc, QStringList argv, AOPacket pa
validated_packet.contents[5] = m_pos;
server->broadcast(validated_packet, m_current_area);
emit logIC((m_current_char + " " + m_showname), m_ooc_name, m_ipid,server->m_areas[m_current_area]->name(), m_last_message);
emit logIC((m_current_char + " " + m_showname), m_ooc_name, m_ipid, server->getAreaById(m_current_area)->name(), m_last_message);
area->updateLastICMessage(validated_packet.contents);
server->can_send_ic_messages = false;
server->next_message_timer.start(ConfigManager::messageFloodguard());
server->startMessageFloodguard(ConfigManager::messageFloodguard());
}
void AOClient::pktOocChat(AreaData* area, int argc, QStringList argv, AOPacket packet)
void AOClient::pktOocChat(AreaData *area, int argc, QStringList argv, AOPacket packet)
{
Q_UNUSED(argc);
Q_UNUSED(packet);
@ -234,7 +239,7 @@ void AOClient::pktOocChat(AreaData* area, int argc, QStringList argv, AOPacket p
}
m_ooc_name = dezalgo(argv[0]).replace(QRegExp("\\[|\\]|\\{|\\}|\\#|\\$|\\%|\\&"), ""); // no fucky wucky shit here
if (m_ooc_name.isEmpty() || m_ooc_name == ConfigManager::serverName()) // impersonation & empty name protection
if (m_ooc_name.isEmpty() || m_ooc_name == ConfigManager::serverName()) // impersonation & empty name protection
return;
if (m_ooc_name.length() > 30) {
@ -246,12 +251,12 @@ void AOClient::pktOocChat(AreaData* area, int argc, QStringList argv, AOPacket p
loginAttempt(argv[1]);
return;
}
QString l_message = dezalgo(argv[1]);
if (l_message.length() == 0 || l_message.length() > ConfigManager::maxCharacters())
return;
AOPacket final_packet("CT", {m_ooc_name, l_message, "0"});
if(l_message.at(0) == '/') {
if (l_message.at(0) == '/') {
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
QStringList l_cmd_argv = l_message.split(" ", QString::SplitBehavior::SkipEmptyParts);
#else
@ -263,7 +268,7 @@ void AOClient::pktOocChat(AreaData* area, int argc, QStringList argv, AOPacket p
int l_cmd_argc = l_cmd_argv.length();
handleCommand(l_command, l_cmd_argc, l_cmd_argv);
emit logCMD((m_current_char + " " + m_showname), m_ipid, m_ooc_name, l_command, l_cmd_argv,server->m_areas[m_current_area]->name());
emit logCMD((m_current_char + " " + m_showname), m_ipid, m_ooc_name, l_command, l_cmd_argv, server->getAreaById(m_current_area)->name());
return;
}
else {
@ -272,7 +277,7 @@ void AOClient::pktOocChat(AreaData* area, int argc, QStringList argv, AOPacket p
emit logOOC((m_current_char + " " + m_showname), m_ooc_name, m_ipid, area->name(), l_message);
}
void AOClient::pktPing(AreaData* area, int argc, QStringList argv, AOPacket packet)
void AOClient::pktPing(AreaData *area, int argc, QStringList argv, AOPacket packet)
{
Q_UNUSED(area);
Q_UNUSED(argc);
@ -285,7 +290,7 @@ void AOClient::pktPing(AreaData* area, int argc, QStringList argv, AOPacket pack
sendPacket("CHECK");
}
void AOClient::pktChangeMusic(AreaData* area, int argc, QStringList argv, AOPacket packet)
void AOClient::pktChangeMusic(AreaData *area, int argc, QStringList argv, AOPacket packet)
{
Q_UNUSED(packet);
@ -297,7 +302,7 @@ void AOClient::pktChangeMusic(AreaData* area, int argc, QStringList argv, AOPack
// argument is a valid song
QString l_argument = argv[0];
if (server->m_music_list.contains(l_argument) || m_music_manager->isCustom(m_current_area, l_argument) || l_argument == "~stop.mp3") { // ~stop.mp3 is a dummy track used by 2.9+
if (server->getMusicList().contains(l_argument) || m_music_manager->isCustom(m_current_area, l_argument) || l_argument == "~stop.mp3") { // ~stop.mp3 is a dummy track used by 2.9+
// We have a song here
if (m_is_dj_blocked) {
sendServerMessage("You are blocked from changing the music.");
@ -314,13 +319,13 @@ void AOClient::pktChangeMusic(AreaData* area, int argc, QStringList argv, AOPack
l_effects = "0";
QString l_final_song;
//As categories can be used to stop music we need to check if it has a dot for the extension. If not, we assume its a category.
// As categories can be used to stop music we need to check if it has a dot for the extension. If not, we assume its a category.
if (!l_argument.contains("."))
l_final_song = "~stop.mp3";
else
l_final_song = l_argument;
//Jukebox intercepts the direct playing of messages.
// Jukebox intercepts the direct playing of messages.
if (area->isjukeboxEnabled()) {
QString l_jukebox_reply = area->addJukeboxSong(l_final_song);
sendServerMessage(l_jukebox_reply);
@ -328,33 +333,33 @@ void AOClient::pktChangeMusic(AreaData* area, int argc, QStringList argv, AOPack
}
if (l_final_song != "~stop.mp3") {
//We might have an aliased song. We check for its real songname and send it to the clients.
QPair<QString,float> l_song = m_music_manager->songInformation(l_final_song, m_current_area);
// We might have an aliased song. We check for its real songname and send it to the clients.
QPair<QString, float> l_song = m_music_manager->songInformation(l_final_song, m_current_area);
l_final_song = l_song.first;
}
AOPacket l_music_change("MC", {l_final_song, argv[1], m_showname, "1", "0", l_effects});
server->broadcast(l_music_change, m_current_area);
//Since we can't ensure a user has their showname set, we check if its empty to prevent
// Since we can't ensure a user has their showname set, we check if its empty to prevent
//"played by ." in /currentmusic.
if (m_showname.isEmpty()) {
area->changeMusic(m_current_char,l_final_song);
area->changeMusic(m_current_char, l_final_song);
return;
}
area->changeMusic(m_showname,l_final_song);
area->changeMusic(m_showname, l_final_song);
return;
}
for (int i = 0; i < server->m_area_names.length(); i++) {
QString l_area = server->m_area_names[i];
if(l_area == l_argument) {
for (int i = 0; i < server->getAreaCount(); i++) {
QString l_area = server->getAreaName(i);
if (l_area == l_argument) {
changeArea(i);
break;
}
}
}
void AOClient::pktWtCe(AreaData* area, int argc, QStringList argv, AOPacket packet)
void AOClient::pktWtCe(AreaData *area, int argc, QStringList argv, AOPacket packet)
{
Q_UNUSED(argc);
Q_UNUSED(argv);
@ -370,7 +375,7 @@ void AOClient::pktWtCe(AreaData* area, int argc, QStringList argv, AOPacket pack
updateJudgeLog(area, this, "WT/CE");
}
void AOClient::pktHpBar(AreaData* area, int argc, QStringList argv, AOPacket packet)
void AOClient::pktHpBar(AreaData *area, int argc, QStringList argv, AOPacket packet)
{
Q_UNUSED(argc);
Q_UNUSED(packet);
@ -394,7 +399,7 @@ void AOClient::pktHpBar(AreaData* area, int argc, QStringList argv, AOPacket pac
updateJudgeLog(area, this, "updated the penalties");
}
void AOClient::pktWebSocketIp(AreaData* area, int argc, QStringList argv, AOPacket packet)
void AOClient::pktWebSocketIp(AreaData *area, int argc, QStringList argv, AOPacket packet)
{
Q_UNUSED(area);
Q_UNUSED(argc);
@ -413,7 +418,7 @@ void AOClient::pktWebSocketIp(AreaData* area, int argc, QStringList argv, AOPack
l_remote_ip = server->parseToIPv4(l_remote_ip);
}
if (server->isIPBanned(l_remote_ip)){
if (server->isIPBanned(l_remote_ip)) {
QString l_reason = "Your IP has been banned by a moderator.";
AOPacket l_ban_reason("BD", {l_reason});
m_socket->write(l_ban_reason.toUtf8());
@ -422,7 +427,7 @@ void AOClient::pktWebSocketIp(AreaData* area, int argc, QStringList argv, AOPack
}
calculateIpid();
auto l_ban = server->db_manager->isIPBanned(m_ipid);
auto l_ban = server->getDatabaseManager()->isIPBanned(m_ipid);
if (l_ban.first) {
sendPacket("BD", {l_ban.second});
m_socket->close();
@ -430,7 +435,8 @@ void AOClient::pktWebSocketIp(AreaData* area, int argc, QStringList argv, AOPack
}
int l_multiclient_count = 0;
for (AOClient* l_joined_client : qAsConst(server->m_clients)) {
const QVector<AOClient *> l_clients = server->getClients();
for (AOClient *l_joined_client : l_clients) {
if (m_remote_ip.isEqual(l_joined_client->m_remote_ip))
l_multiclient_count++;
}
@ -442,7 +448,7 @@ void AOClient::pktWebSocketIp(AreaData* area, int argc, QStringList argv, AOPack
}
}
void AOClient::pktModCall(AreaData* area, int argc, QStringList argv, AOPacket packet)
void AOClient::pktModCall(AreaData *area, int argc, QStringList argv, AOPacket packet)
{
Q_UNUSED(argc);
Q_UNUSED(argv);
@ -460,18 +466,24 @@ void AOClient::pktModCall(AreaData* area, int argc, QStringList argv, AOPacket p
else
l_modcallNotice.append("No reason given.");
for (AOClient* client : qAsConst(server->m_clients)) {
if (client->m_authenticated) {
client->sendPacket(AOPacket("ZZ", {l_modcallNotice}));
}
const QVector<AOClient *> l_clients = server->getClients();
for (AOClient *l_client : l_clients) {
if (l_client->m_authenticated)
l_client->sendPacket(AOPacket("ZZ", {l_modcallNotice}));
}
emit logModcall((m_current_char + " " + m_showname), m_ipid, m_ooc_name, server->m_areas[m_current_area]->name());
emit logModcall((m_current_char + " " + m_showname), m_ipid, m_ooc_name, server->getAreaById(m_current_area)->name());
if (ConfigManager::discordModcallWebhookEnabled())
emit server->modcallWebhookRequest(l_name, l_areaName, packet.contents[0],server->getAreaBuffer(l_areaName));
if (ConfigManager::discordModcallWebhookEnabled()) {
QString l_name = m_ooc_name;
if (m_ooc_name.isEmpty())
l_name = m_current_char;
QString l_areaName = area->name();
emit server->modcallWebhookRequest(l_name, l_areaName, packet.contents[0], server->getAreaBuffer(l_areaName));
}
}
void AOClient::pktAddEvidence(AreaData* area, int argc, QStringList argv, AOPacket packet)
void AOClient::pktAddEvidence(AreaData *area, int argc, QStringList argv, AOPacket packet)
{
Q_UNUSED(argc);
Q_UNUSED(packet);
@ -483,7 +495,7 @@ void AOClient::pktAddEvidence(AreaData* area, int argc, QStringList argv, AOPack
sendEvidenceList(area);
}
void AOClient::pktRemoveEvidence(AreaData* area, int argc, QStringList argv, AOPacket packet)
void AOClient::pktRemoveEvidence(AreaData *area, int argc, QStringList argv, AOPacket packet)
{
Q_UNUSED(argc);
Q_UNUSED(packet);
@ -498,7 +510,7 @@ void AOClient::pktRemoveEvidence(AreaData* area, int argc, QStringList argv, AOP
sendEvidenceList(area);
}
void AOClient::pktEditEvidence(AreaData* area, int argc, QStringList argv, AOPacket packet)
void AOClient::pktEditEvidence(AreaData *area, int argc, QStringList argv, AOPacket packet)
{
Q_UNUSED(argc);
Q_UNUSED(packet);
@ -514,14 +526,14 @@ void AOClient::pktEditEvidence(AreaData* area, int argc, QStringList argv, AOPac
sendEvidenceList(area);
}
void AOClient::pktSetCase(AreaData* area, int argc, QStringList argv, AOPacket packet)
void AOClient::pktSetCase(AreaData *area, int argc, QStringList argv, AOPacket packet)
{
Q_UNUSED(area);
Q_UNUSED(argc);
Q_UNUSED(packet);
QList<bool> l_prefs_list;
for (int i = 2; i <=6; i++) {
for (int i = 2; i <= 6; i++) {
bool is_int = false;
bool pref = argv[i].toInt(&is_int);
if (!is_int)
@ -531,7 +543,7 @@ void AOClient::pktSetCase(AreaData* area, int argc, QStringList argv, AOPacket p
m_casing_preferences = l_prefs_list;
}
void AOClient::pktAnnounceCase(AreaData* area, int argc, QStringList argv, AOPacket packet)
void AOClient::pktAnnounceCase(AreaData *area, int argc, QStringList argv, AOPacket packet)
{
Q_UNUSED(area);
Q_UNUSED(argc);
@ -540,7 +552,7 @@ void AOClient::pktAnnounceCase(AreaData* area, int argc, QStringList argv, AOPac
QString l_case_title = argv[0];
QStringList l_needed_roles;
QList<bool> l_needs_list;
for (int i = 1; i <=5; i++) {
for (int i = 1; i <= 5; i++) {
bool is_int = false;
bool need = argv[i].toInt(&is_int);
if (!is_int)
@ -549,22 +561,23 @@ void AOClient::pktAnnounceCase(AreaData* area, int argc, QStringList argv, AOPac
}
QStringList l_roles = {"defense attorney", "prosecutor", "judge", "jurors", "stenographer"};
for (int i = 0; i < 5; i++) {
if (l_needs_list[i])
l_needed_roles.append(l_roles[i]);
if (l_needs_list[i])
l_needed_roles.append(l_roles[i]);
}
if (l_needed_roles.isEmpty())
return;
QString l_message = "=== Case Announcement ===\r\n" + (m_ooc_name == "" ? m_current_char : m_ooc_name) + " needs " + l_needed_roles.join(", ") + " for " + (l_case_title == "" ? "a case" : l_case_title) + "!";
QList<AOClient*> l_clients_to_alert;
QList<AOClient *> l_clients_to_alert;
// here lies morton, RIP
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
QSet<bool> l_needs_set(l_needs_list.begin(), l_needs_list.end());
#else
QSet<bool> l_needs_set = l_needs_list.toSet();
#endif
for (AOClient* l_client : qAsConst(server->m_clients)) {
const QVector<AOClient *> l_clients = server->getClients();
for (AOClient *l_client : l_clients) {
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
QSet<bool> l_matches(l_client->m_casing_preferences.begin(), l_client->m_casing_preferences.end());
l_matches.intersect(l_needs_set);
@ -575,7 +588,7 @@ void AOClient::pktAnnounceCase(AreaData* area, int argc, QStringList argv, AOPac
l_clients_to_alert.append(l_client);
}
for (AOClient* l_client : l_clients_to_alert) {
for (AOClient *l_client : l_clients_to_alert) {
l_client->sendPacket(AOPacket("CASEA", {l_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!
@ -584,15 +597,16 @@ void AOClient::pktAnnounceCase(AreaData* area, int argc, QStringList argv, AOPac
}
}
void AOClient::sendEvidenceList(AreaData* area)
void AOClient::sendEvidenceList(AreaData *area)
{
for (AOClient* l_client : qAsConst(server->m_clients)) {
const QVector<AOClient *> l_clients = server->getClients();
for (AOClient *l_client : l_clients) {
if (l_client->m_current_area == m_current_area)
l_client->updateEvidenceList(area);
}
}
void AOClient::updateEvidenceList(AreaData* area)
void AOClient::updateEvidenceList(AreaData *area)
{
QStringList l_evidence_list;
QString l_evidence_format("%1&%2&%3");
@ -633,7 +647,7 @@ AOPacket AOClient::validateIcPacket(AOPacket packet)
if (m_current_char == "" || !m_joined)
// Spectators cannot use IC
return l_invalid;
AreaData* area = server->m_areas[m_current_area];
AreaData *area = server->getAreaById(m_current_area);
if (area->lockStatus() == AreaData::LockStatus::SPECTATABLE && !area->invited().contains(m_id) && !checkAuth(ACLFlags.value("BYPASS_LOCKS")))
// Non-invited players cannot speak in spectatable areas
return l_invalid;
@ -645,7 +659,13 @@ AOPacket AOClient::validateIcPacket(AOPacket packet)
// desk modifier
QStringList allowed_desk_mods;
allowed_desk_mods << "chat" << "0" << "1" << "2" << "3" << "4" << "5";
allowed_desk_mods << "chat"
<< "0"
<< "1"
<< "2"
<< "3"
<< "4"
<< "5";
if (allowed_desk_mods.contains(l_incoming_args[0].toString())) {
l_args.append(l_incoming_args[0].toString());
}
@ -660,7 +680,7 @@ AOPacket AOClient::validateIcPacket(AOPacket packet)
// Selected char is different from supplied folder name
// This means the user is INI-swapped
if (!area->iniswapAllowed()) {
if (!server->m_characters.contains(l_incoming_args[2].toString(), Qt::CaseInsensitive))
if (!server->getCharacters().contains(l_incoming_args[2].toString(), Qt::CaseInsensitive))
return l_invalid;
}
qDebug() << "INI swap detected from " << getIpid();
@ -679,9 +699,7 @@ AOPacket AOClient::validateIcPacket(AOPacket packet)
return l_invalid;
QString l_incoming_msg = dezalgo(l_incoming_args[4].toString().trimmed());
if (!area->lastICMessage().isEmpty()
&& l_incoming_msg == area->lastICMessage()[4]
&& l_incoming_msg != "")
if (!area->lastICMessage().isEmpty() && l_incoming_msg == area->lastICMessage()[4] && l_incoming_msg != "")
return l_invalid;
if (l_incoming_msg == "" && area->blankpostingAllowed() == false) {
@ -713,7 +731,7 @@ AOPacket AOClient::validateIcPacket(AOPacket packet)
l_args.append(l_incoming_args[5].toString());
if (m_pos != l_incoming_args[5].toString()) {
m_pos = l_incoming_args[5].toString();
updateEvidenceList(server->m_areas[m_current_area]);
updateEvidenceList(server->getAreaById(m_current_area));
}
// sfx name
@ -815,10 +833,7 @@ AOPacket AOClient::validateIcPacket(AOPacket packet)
QString l_other_flip = "0";
for (int l_client_id : area->joinedIDs()) {
AOClient* l_client = server->getClientByID(l_client_id);
if (l_client->m_pairing_with == m_char_id
&& l_other_charid != m_char_id
&& l_client->m_char_id == m_pairing_with
&& l_client->m_pos == m_pos) {
if (l_client->m_pairing_with == m_char_id && l_other_charid != m_char_id && l_client->m_char_id == m_pairing_with && l_client->m_pos == m_pos) {
l_other_name = l_client->m_current_iniswap;
l_other_emote = l_client->m_emote;
l_other_offset = l_client->m_offset;
@ -893,7 +908,7 @@ AOPacket AOClient::validateIcPacket(AOPacket packet)
int l_additive = l_incoming_args[24].toInt();
if (l_additive != 0 && l_additive != 1)
return l_invalid;
else if (area->lastICMessage().isEmpty()){
else if (area->lastICMessage().isEmpty()) {
l_additive = 0;
}
else if (!(m_char_id == area->lastICMessage()[8].toInt())) {
@ -908,7 +923,7 @@ AOPacket AOClient::validateIcPacket(AOPacket packet)
l_args.append(l_incoming_args[25].toString());
}
//Testimony playback
// Testimony playback
if (area->testimonyRecording() == AreaData::TestimonyRecording::RECORDING || area->testimonyRecording() == AreaData::TestimonyRecording::ADD) {
if (l_args[5] != "wit")
return AOPacket("MS", l_args);
@ -916,7 +931,7 @@ AOPacket AOClient::validateIcPacket(AOPacket packet)
if (area->statement() == -1) {
l_args[4] = "~~\\n-- " + l_args[4] + " --";
l_args[14] = "3";
server->broadcast(AOPacket("RT",{"testimony1"}), m_current_area);
server->broadcast(AOPacket("RT", {"testimony1"}), m_current_area);
}
addStatement(l_args);
}
@ -928,7 +943,7 @@ AOPacket AOClient::validateIcPacket(AOPacket packet)
if (l_args[4] == ">") {
m_pos = "wit";
auto l_statement = area->jumpToStatement(area->statement() +1);
auto l_statement = area->jumpToStatement(area->statement() + 1);
l_args = l_statement.first;
l_progress = l_statement.second;
@ -947,7 +962,7 @@ AOPacket AOClient::validateIcPacket(AOPacket packet)
}
}
QString l_decoded_message = decodeMessage(l_args[4]); //Get rid of that pesky encoding first.
QString l_decoded_message = decodeMessage(l_args[4]); // Get rid of that pesky encoding first.
QRegularExpression jump("(?<arrow>>)(?<int>[0,1,2,3,4,5,6,7,8,9]+)");
QRegularExpressionMatch match = jump.match(l_decoded_message);
if (match.hasMatch()) {
@ -956,8 +971,7 @@ AOPacket AOClient::validateIcPacket(AOPacket packet)
l_args = l_statement.first;
l_progress = l_statement.second;
switch (l_progress){
switch (l_progress) {
case AreaData::TestimonyProgress::LOOPED:
{
sendServerMessageArea("Last statement reached. Looping to first statement.");
@ -988,7 +1002,7 @@ QString AOClient::dezalgo(QString p_text)
bool AOClient::checkEvidenceAccess(AreaData *area)
{
switch(area->eviMod()) {
switch (area->eviMod()) {
case AreaData::EvidenceMod::FFA:
return true;
case AreaData::EvidenceMod::CM:
@ -1001,7 +1015,7 @@ bool AOClient::checkEvidenceAccess(AreaData *area)
}
}
void AOClient::updateJudgeLog(AreaData* area, AOClient* client, QString action)
void AOClient::updateJudgeLog(AreaData *area, AOClient *client, QString action)
{
QString l_timestamp = QTime::currentTime().toString("hh:mm:ss");
QString l_uid = QString::number(client->m_id);
@ -1014,10 +1028,10 @@ void AOClient::updateJudgeLog(AreaData* area, AOClient* client, QString action)
QString AOClient::decodeMessage(QString incoming_message)
{
QString decoded_message = incoming_message.replace("<num>", "#")
.replace("<percent>", "%")
.replace("<dollar>", "$")
.replace("<and>", "&");
QString decoded_message = incoming_message.replace("<num>", "#")
.replace("<percent>", "%")
.replace("<dollar>", "$")
.replace("<and>", "&");
return decoded_message;
}
@ -1026,7 +1040,7 @@ void AOClient::loginAttempt(QString message)
switch (ConfigManager::authType()) {
case DataTypes::AuthType::SIMPLE:
if (message == ConfigManager::modpass()) {
sendPacket("AUTH", {"1"}); // Client: "You were granted the Disable Modcalls button."
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
m_authenticated = true;
}
@ -1034,8 +1048,8 @@ void AOClient::loginAttempt(QString message)
sendPacket("AUTH", {"0"}); // Client: "Login unsuccessful."
sendServerMessage("Incorrect password.");
}
emit logLogin((m_current_char + " " + m_showname), m_ooc_name,"Moderator",
m_ipid, server->m_areas.value(m_current_area)->name(), m_authenticated);
emit logLogin((m_current_char + " " + m_showname), m_ooc_name, "Moderator",
m_ipid, server->getAreaById(m_current_area)->name(), m_authenticated);
break;
case DataTypes::AuthType::ADVANCED:
QStringList l_login = message.split(" ");
@ -1047,7 +1061,7 @@ void AOClient::loginAttempt(QString message)
}
QString username = l_login[0];
QString password = l_login[1];
if (server->db_manager->authenticate(username, password)) {
if (server->getDatabaseManager()->authenticate(username, password)) {
m_moderator_name = username;
m_authenticated = true;
sendPacket("AUTH", {"1"}); // Client: "You were granted the Disable Modcalls button."
@ -1060,11 +1074,10 @@ void AOClient::loginAttempt(QString message)
sendServerMessage("Incorrect password.");
}
emit logLogin((m_current_char + " " + m_showname), m_ooc_name, username, m_ipid,
server->m_areas.value(m_current_area)->name(), m_authenticated);
server->getAreaById(m_current_area)->name(), m_authenticated);
break;
}
sendServerMessage("Exiting login prompt.");
m_is_logging_in = false;
return;
}

View File

@ -17,28 +17,38 @@
//////////////////////////////////////////////////////////////////////////////////////
#include "include/server.h"
Server::Server(int p_port, int p_ws_port, QObject* parent) :
#include "include/advertiser.h"
#include "include/aoclient.h"
#include "include/aopacket.h"
#include "include/area_data.h"
#include "include/config_manager.h"
#include "include/db_manager.h"
#include "include/discord.h"
#include "include/logger/u_logger.h"
#include "include/music_manager.h"
#include "include/ws_proxy.h"
Server::Server(int p_port, int p_ws_port, QObject *parent) :
QObject(parent),
m_player_count(0),
port(p_port),
ws_port(p_ws_port)
ws_port(p_ws_port),
m_player_count(0)
{
server = new QTcpServer(this);
connect(server, SIGNAL(newConnection()), this, SLOT(clientConnected()));
proxy = new WSProxy(port, ws_port, this);
if(ws_port != -1)
if (ws_port != -1)
proxy->start();
timer = new QTimer();
timer = new QTimer(this);
db_manager = new DBManager();
//We create it, even if its not used later on.
// We create it, even if its not used later on.
discord = new Discord(this);
logger = new ULogger(this);
connect(this, &Server::logConnectionAttempt,
logger, &ULogger::logConnectionAttempt);
connect(this, &Server::logConnectionAttempt, logger, &ULogger::logConnectionAttempt);
}
void Server::start()
@ -58,81 +68,79 @@ void Server::start()
else {
qDebug() << "Server listening on" << port;
}
//Checks if any Discord webhooks are enabled.
// Checks if any Discord webhooks are enabled.
handleDiscordIntegration();
//Construct modern advertiser if enabled in config
// Construct modern advertiser if enabled in config
if (ConfigManager::advertiseServer()) {
AdvertiserTimer = new QTimer(this);
ms3_Advertiser = new Advertiser();
connect(AdvertiserTimer, &QTimer::timeout,
ms3_Advertiser, &Advertiser::msAdvertiseServer);
connect(this, &Server::updatePlayerCount,
ms3_Advertiser, &Advertiser::updatePlayerCount);
connect(this, &Server::updateHTTPConfiguration,
ms3_Advertiser, &Advertiser::updateAdvertiserSettings);
emit updatePlayerCount(m_player_count);
connect(AdvertiserTimer, &QTimer::timeout, ms3_Advertiser, &Advertiser::msAdvertiseServer);
connect(this, &Server::playerCountUpdated, ms3_Advertiser, &Advertiser::updatePlayerCount);
connect(this, &Server::updateHTTPConfiguration, ms3_Advertiser, &Advertiser::updateAdvertiserSettings);
emit playerCountUpdated(m_player_count);
ms3_Advertiser->msAdvertiseServer();
AdvertiserTimer->start(300000);
}
//Get characters from config file
// Get characters from config file
m_characters = ConfigManager::charlist();
//Get backgrounds from config file
// Get backgrounds from config file
m_backgrounds = ConfigManager::backgrounds();
//Build our music manager.
// Build our music manager.
ConfigManager::musiclist();
music_manager = new MusicManager(this, ConfigManager::ordered_songs(), ConfigManager::cdnList());
connect(music_manager, &MusicManager::sendFMPacket,
this, &Server::unicast);
connect(music_manager, &MusicManager::sendAreaFMPacket,
this, QOverload<AOPacket,int>::of(&Server::broadcast));
music_manager = new MusicManager(ConfigManager::ordered_songs(), ConfigManager::cdnList(), ConfigManager::musiclist(), this);
connect(music_manager, &MusicManager::sendFMPacket, this, &Server::unicast);
connect(music_manager, &MusicManager::sendAreaFMPacket, this, QOverload<AOPacket, int>::of(&Server::broadcast));
//Get musiclist from config file
// Get musiclist from config file
m_music_list = music_manager->rootMusiclist();
//Assembles the area list
// Assembles the area list
m_area_names = ConfigManager::sanitizedAreaNames();
QStringList raw_area_names = ConfigManager::rawAreaNames();
for (int i = 0; i < raw_area_names.length(); i++) {
QString area_name = raw_area_names[i];
AreaData* l_area = new AreaData(area_name, i, music_manager);
AreaData *l_area = new AreaData(area_name, i, music_manager);
m_areas.insert(i, l_area);
connect(l_area, &AreaData::sendAreaPacket,
this, QOverload<AOPacket,int>::of(&Server::broadcast));
connect(l_area, &AreaData::sendAreaPacketClient,
this, &Server::unicast);
connect(l_area, &AreaData::userJoinedArea,
music_manager, &MusicManager::userJoinedArea);
connect(l_area, &AreaData::sendAreaPacket, this, QOverload<AOPacket, int>::of(&Server::broadcast));
connect(l_area, &AreaData::sendAreaPacketClient, this, &Server::unicast);
connect(l_area, &AreaData::userJoinedArea, music_manager, &MusicManager::userJoinedArea);
music_manager->registerArea(i);
}
//Loads the command help information. This is not stored inside the server.
// Loads the command help information. This is not stored inside the server.
ConfigManager::loadCommandHelp();
//Get IP bans
// Get IP bans
m_ipban_list = ConfigManager::iprangeBans();
//Rate-Limiter for IC-Chat
connect(&next_message_timer, &QTimer::timeout, this, &Server::allowMessage);
// Rate-Limiter for IC-Chat
m_message_floodguard_timer = new QTimer(this);
connect(m_message_floodguard_timer, &QTimer::timeout, this, &Server::allowMessage);
//Prepare player IDs and reference hash.
for (int i = ConfigManager::maxPlayers() -1; i >= 0; i--){
// Prepare player IDs and reference hash.
for (int i = ConfigManager::maxPlayers() - 1; i >= 0; i--) {
m_available_ids.push(i);
m_clients_ids.insert(i, nullptr);
}
}
QVector<AOClient *> Server::getClients()
{
return m_clients;
}
void Server::clientConnected()
{
QTcpSocket* socket = server->nextPendingConnection();
QTcpSocket *socket = server->nextPendingConnection();
//Too many players. Reject connection!
//This also enforces the maximum playercount.
// Too many players. Reject connection!
// This also enforces the maximum playercount.
if (m_available_ids.empty()) {
AOPacket disconnect_reason("BD", {"Maximum playercount has been reached."});
socket->write(disconnect_reason.toUtf8());
@ -143,7 +151,7 @@ void Server::clientConnected()
}
int user_id = m_available_ids.pop();
AOClient* client = new AOClient(this, socket, this, user_id, music_manager);
AOClient *client = new AOClient(this, socket, this, user_id, music_manager);
m_clients_ids.insert(user_id, client);
int multiclient_count = 1;
@ -151,7 +159,7 @@ void Server::clientConnected()
client->calculateIpid();
auto ban = db_manager->isIPBanned(client->getIpid());
bool is_banned = ban.first;
for (AOClient* joined_client : qAsConst(m_clients)) {
for (AOClient *joined_client : qAsConst(m_clients)) {
if (client->m_remote_ip.isEqual(joined_client->m_remote_ip))
multiclient_count++;
}
@ -177,7 +185,7 @@ void Server::clientConnected()
l_remote_ip = parseToIPv4(l_remote_ip);
}
if (isIPBanned(l_remote_ip)){
if (isIPBanned(l_remote_ip)) {
QString l_reason = "Your IP has been banned by a moderator.";
AOPacket l_ban_reason("BD", {l_reason});
socket->write(l_ban_reason.toUtf8());
@ -188,9 +196,11 @@ void Server::clientConnected()
}
m_clients.append(client);
connect(socket, &QTcpSocket::disconnected, client,
&AOClient::clientDisconnected);
connect(socket, &QTcpSocket::disconnected, client, &AOClient::clientDisconnected);
connect(socket, &QTcpSocket::disconnected, this, [=] {
if (client->hasJoined()) {
decreasePlayerCount();
}
m_clients.removeAll(client);
client->deleteLater();
});
@ -206,7 +216,7 @@ void Server::clientConnected()
#endif
}
void Server::updateCharsTaken(AreaData* area)
void Server::updateCharsTaken(AreaData *area)
{
QStringList chars_taken;
for (const QString &cur_char : qAsConst(m_characters)) {
@ -217,20 +227,20 @@ void Server::updateCharsTaken(AreaData* area)
AOPacket response_cc("CharsCheck", chars_taken);
for (AOClient* client : qAsConst(m_clients)) {
if (client->m_current_area == area->index()){
if (!client->m_is_charcursed)
client->sendPacket(response_cc);
for (AOClient *l_client : qAsConst(m_clients)) {
if (l_client->m_current_area == area->index()) {
if (!l_client->m_is_charcursed)
l_client->sendPacket(response_cc);
else {
QStringList chars_taken_cursed = getCursedCharsTaken(client, chars_taken);
QStringList chars_taken_cursed = getCursedCharsTaken(l_client, chars_taken);
AOPacket response_cc_cursed("CharsCheck", chars_taken_cursed);
client->sendPacket(response_cc_cursed);
l_client->sendPacket(response_cc_cursed);
}
}
}
}
QStringList Server::getCursedCharsTaken(AOClient* client, QStringList chars_taken)
QStringList Server::getCursedCharsTaken(AOClient *client, QStringList chars_taken)
{
QStringList chars_taken_cursed;
for (int i = 0; i < chars_taken.length(); i++) {
@ -242,6 +252,17 @@ QStringList Server::getCursedCharsTaken(AOClient* client, QStringList chars_take
return chars_taken_cursed;
}
bool Server::isMessageAllowed()
{
return m_can_send_ic_messages;
}
void Server::startMessageFloodguard(int f_duration)
{
m_can_send_ic_messages = false;
m_message_floodguard_timer->start(f_duration);
}
QHostAddress Server::parseToIPv4(QHostAddress f_remote_ip)
{
bool l_ok;
@ -273,14 +294,14 @@ void Server::broadcast(AOPacket packet, int area_index)
void Server::broadcast(AOPacket packet)
{
for (AOClient* client : qAsConst(m_clients)) {
client->sendPacket(packet);
for (AOClient *l_client : qAsConst(m_clients)) {
l_client->sendPacket(packet);
}
}
void Server::broadcast(AOPacket packet, TARGET_TYPE target)
{
for (AOClient* l_client : qAsConst(m_clients)) {
for (AOClient *l_client : qAsConst(m_clients)) {
switch (target) {
case TARGET_TYPE::MODCHAT:
if (l_client->checkAuth(l_client->ACLFlags.value("MODCHAT"))) {
@ -302,44 +323,70 @@ void Server::broadcast(AOPacket packet, AOPacket other_packet, TARGET_TYPE targe
{
switch (target) {
case TARGET_TYPE::AUTHENTICATED:
for (AOClient* client : qAsConst(m_clients)){
if (client->m_authenticated) {
client->sendPacket(other_packet);
for (AOClient *l_client : qAsConst(m_clients)) {
if (l_client->m_authenticated) {
l_client->sendPacket(other_packet);
}
else {
client->sendPacket(packet);
l_client->sendPacket(packet);
}
}
default:
//Unimplemented, so not handled.
// Unimplemented, so not handled.
break;
}
}
void Server::unicast(AOPacket f_packet, int f_client_id)
{
AOClient* l_client = getClientByID(f_client_id);
AOClient *l_client = getClientByID(f_client_id);
if (l_client != nullptr) { // This should never happen, but safety first.
l_client->sendPacket(f_packet);
return;
}
}
QList<AOClient*> Server::getClientsByIpid(QString ipid)
QList<AOClient *> Server::getClientsByIpid(QString ipid)
{
QList<AOClient*> return_clients;
for (AOClient* client : qAsConst(m_clients)) {
if (client->getIpid() == ipid)
return_clients.append(client);
QList<AOClient *> return_clients;
for (AOClient *l_client : qAsConst(m_clients)) {
if (l_client->getIpid() == ipid)
return_clients.append(l_client);
}
return return_clients;
}
AOClient* Server::getClientByID(int id)
AOClient *Server::getClientByID(int id)
{
return m_clients_ids.value(id);
}
int Server::getPlayerCount()
{
return m_player_count;
}
QStringList Server::getCharacters()
{
return m_characters;
}
int Server::getCharacterCount()
{
return m_characters.length();
}
QString Server::getCharacterById(int f_chr_id)
{
QString l_chr;
if (f_chr_id >= 0 && f_chr_id < m_characters.length()) {
l_chr = m_characters.at(f_chr_id);
}
return l_chr;
}
int Server::getCharID(QString char_name)
{
for (const QString &character : qAsConst(m_characters)) {
@ -350,29 +397,79 @@ int Server::getCharID(QString char_name)
return -1; // character does not exist
}
QVector<AreaData *> Server::getAreas()
{
return m_areas;
}
int Server::getAreaCount()
{
return m_areas.length();
}
AreaData *Server::getAreaById(int f_area_id)
{
AreaData *l_area = nullptr;
if (f_area_id >= 0 && f_area_id < m_areas.length()) {
l_area = m_areas.at(f_area_id);
}
return l_area;
}
QQueue<QString> Server::getAreaBuffer(const QString &f_areaName)
{
return logger->buffer(f_areaName);
}
QStringList Server::getAreaNames()
{
return m_area_names;
}
QString Server::getAreaName(int f_area_id)
{
QString l_name;
if (f_area_id >= 0 && f_area_id < m_area_names.length()) {
l_name = m_area_names.at(f_area_id);
}
return l_name;
}
QStringList Server::getMusicList()
{
return m_music_list;
}
QStringList Server::getBackgrounds()
{
return m_backgrounds;
}
DBManager *Server::getDatabaseManager()
{
return db_manager;
}
void Server::allowMessage()
{
can_send_ic_messages = true;
m_can_send_ic_messages = true;
}
void Server::handleDiscordIntegration()
{
// Prevent double connecting by preemtively disconnecting them.
// Prevent double connecting by preemtively disconnecting them.
disconnect(this, nullptr, discord, nullptr);
if (ConfigManager::discordWebhookEnabled()) {
if (ConfigManager::discordModcallWebhookEnabled())
connect(this, &Server::modcallWebhookRequest,
discord, &Discord::onModcallWebhookRequested);
connect(this, &Server::modcallWebhookRequest, discord, &Discord::onModcallWebhookRequested);
if (ConfigManager::discordBanWebhookEnabled())
connect(this, &Server::banWebhookRequest,
discord, &Discord::onBanWebhookRequested);
connect(this, &Server::banWebhookRequest, discord, &Discord::onBanWebhookRequested);
if (ConfigManager::discordUptimeEnabled())
discord->startUptimeTimer();
@ -388,30 +485,34 @@ void Server::markIDFree(const int &f_user_id)
m_clients_ids.insert(f_user_id, nullptr);
}
void Server::hookupAOClient(AOClient* client)
void Server::hookupAOClient(AOClient *client)
{
connect(client, &AOClient::logIC,
logger, &ULogger::logIC);
connect(client, &AOClient::logOOC,
logger, &ULogger::logOOC);
connect(client, &AOClient::logLogin,
logger, &ULogger::logLogin);
connect(client, &AOClient::logCMD,
logger, &ULogger::logCMD);
connect(client, &AOClient::logBan,
logger, &ULogger::logBan);
connect(client, &AOClient::logKick,
logger, &ULogger::logKick);
connect(client, &AOClient::logModcall,
logger, &ULogger::logModcall);
connect(client, &AOClient::clientSuccessfullyDisconnected,
this, &Server::markIDFree);
connect(client, &AOClient::joined, this, &Server::increasePlayerCount);
connect(client, &AOClient::logIC, logger, &ULogger::logIC);
connect(client, &AOClient::logOOC, logger, &ULogger::logOOC);
connect(client, &AOClient::logLogin, logger, &ULogger::logLogin);
connect(client, &AOClient::logCMD, logger, &ULogger::logCMD);
connect(client, &AOClient::logBan, logger, &ULogger::logBan);
connect(client, &AOClient::logKick, logger, &ULogger::logKick);
connect(client, &AOClient::logModcall, logger, &ULogger::logModcall);
}
void Server::increasePlayerCount()
{
m_player_count++;
emit playerCountUpdated(m_player_count);
}
void Server::decreasePlayerCount()
{
m_player_count--;
emit playerCountUpdated(m_player_count);
}
bool Server::isIPBanned(QHostAddress f_remote_IP)
{
bool l_match_found = false;
for(const QString &l_ipban : qAsConst(m_ipban_list)) {
for (const QString &l_ipban : qAsConst(m_ipban_list)) {
if (f_remote_IP.isInSubnet(QHostAddress::parseSubnet(l_ipban))) {
l_match_found = true;
break;
@ -422,8 +523,8 @@ bool Server::isIPBanned(QHostAddress f_remote_IP)
Server::~Server()
{
for (AOClient* client : qAsConst(m_clients)) {
client->deleteLater();
for (AOClient *l_client : qAsConst(m_clients)) {
l_client->deleteLater();
}
server->deleteLater();
proxy->deleteLater();

View File

@ -17,12 +17,16 @@
//////////////////////////////////////////////////////////////////////////////////////
#include "include/aoclient.h"
#include "include/area_data.h"
#include "include/config_manager.h"
#include "include/server.h"
void AOClient::addStatement(QStringList packet)
{
if (checkTestimonySymbols(packet[4])) {
return;
}
AreaData* area = server->m_areas[m_current_area];
AreaData *area = server->getAreaById(m_current_area);
int c_statement = area->statement();
if (c_statement >= -1) {
if (area->testimonyRecording() == AreaData::TestimonyRecording::RECORDING) {
@ -39,10 +43,10 @@ void AOClient::addStatement(QStringList packet)
}
}
else if (area->testimonyRecording() == AreaData::TestimonyRecording::ADD) {
packet[14] = "1";
area->addStatement(c_statement, packet);
area->setTestimonyRecording(AreaData::TestimonyRecording::PLAYBACK);
}
packet[14] = "1";
area->addStatement(c_statement, packet);
area->setTestimonyRecording(AreaData::TestimonyRecording::PLAYBACK);
}
else {
sendServerMessage("Unable to add more statements. The maximum amount of statements has been reached.");
area->setTestimonyRecording(AreaData::TestimonyRecording::PLAYBACK);
@ -55,7 +59,7 @@ QStringList AOClient::updateStatement(QStringList packet)
if (checkTestimonySymbols(packet[4])) {
return packet;
}
AreaData* area = server->m_areas[m_current_area];
AreaData *area = server->getAreaById(m_current_area);
int c_statement = area->statement();
area->setTestimonyRecording(AreaData::TestimonyRecording::PLAYBACK);
if (c_statement <= 0 || area->testimony()[c_statement].empty())
@ -71,11 +75,11 @@ QStringList AOClient::updateStatement(QStringList packet)
void AOClient::clearTestimony()
{
AreaData* area = server->m_areas[m_current_area];
AreaData *area = server->getAreaById(m_current_area);
area->clearTestimony();
}
bool AOClient::checkTestimonySymbols(const QString& message)
bool AOClient::checkTestimonySymbols(const QString &message)
{
if (message.contains('>') || message.contains('<')) {
sendServerMessage("Unable to add statements containing '>' or '<'.");

View File

@ -43,7 +43,7 @@ void WSClient::onTcpData()
// Workaround for WebAO bug needing every packet in its own message
QStringList all_packets = QString::fromUtf8(tcp_message).split("%");
all_packets.removeLast(); // Remove empty space after final delimiter
for(const QString &packet : qAsConst(all_packets)) {
for (const QString &packet : qAsConst(all_packets)) {
web_socket->sendTextMessage(packet + "%");
}
}
@ -65,15 +65,15 @@ void WSClient::onTcpConnect()
tcp_socket->flush();
}
WSClient::WSClient(QTcpSocket *p_tcp_socket, QWebSocket *p_web_socket, QObject *parent)
: QObject(parent),
tcp_socket(p_tcp_socket),
web_socket(p_web_socket)
WSClient::WSClient(QTcpSocket *p_tcp_socket, QWebSocket *p_web_socket, QObject *parent) :
QObject(parent),
tcp_socket(p_tcp_socket),
web_socket(p_web_socket)
{
bool l_is_local = web_socket->peerAddress() == QHostAddress::LocalHost |
web_socket->peerAddress() == QHostAddress::LocalHostIPv6;
//TLDR : We check if the header comes trough a proxy/tunnel running locally.
//This is to ensure nobody can send those headers from the web.
bool l_is_local = (web_socket->peerAddress() == QHostAddress::LocalHost) ||
(web_socket->peerAddress() == QHostAddress::LocalHostIPv6);
// TLDR : We check if the header comes trough a proxy/tunnel running locally.
// This is to ensure nobody can send those headers from the web.
QNetworkRequest l_request = web_socket->request();
if (l_request.hasRawHeader("x-forwarded-for") && l_is_local) {
websocket_ip = l_request.rawHeader("x-forwarded-for");

View File

@ -17,7 +17,9 @@
//////////////////////////////////////////////////////////////////////////////////////
#include "include/ws_proxy.h"
WSProxy::WSProxy(int p_local_port, int p_ws_port, QObject* parent) :
#include "include/ws_client.h"
WSProxy::WSProxy(int p_local_port, int p_ws_port, QObject *parent) :
QObject(parent),
local_port(p_local_port),
ws_port(p_ws_port)
@ -30,18 +32,19 @@ WSProxy::WSProxy(int p_local_port, int p_ws_port, QObject* parent) :
void WSProxy::start()
{
if(!server->listen(QHostAddress::Any, ws_port)) {
if (!server->listen(QHostAddress::Any, ws_port)) {
qDebug() << "WebSocket proxy failed to start: " << server->errorString();
} else {
}
else {
qDebug() << "WebSocket proxy listening";
}
}
void WSProxy::wsConnected()
{
QWebSocket* new_ws = server->nextPendingConnection();
QTcpSocket* new_tcp = new QTcpSocket(this);
WSClient* client = new WSClient(new_tcp, new_ws, this);
QWebSocket *new_ws = server->nextPendingConnection();
QTcpSocket *new_tcp = new QTcpSocket(this);
WSClient *client = new WSClient(new_tcp, new_ws, this);
clients.append(client);
connect(new_ws, &QWebSocket::textMessageReceived, client, &WSClient::onWsData);

View File

@ -14,13 +14,13 @@ class Area : public QObject
{
Q_OBJECT
public:
public:
/**
* @brief An AreaData pointer to test with.
*/
AreaData* m_area;
AreaData *m_area;
private slots:
private slots:
/**
* @brief Initialises every tests with creating a new area with the title "Test Area", and the index of 0.
*/
@ -78,14 +78,14 @@ void Area::clientJoinLeave()
{
{
// There must be exactly one client in the area, and it must have a charid of 5 and userid 0.
m_area->clientJoinedArea(5,0);
m_area->clientJoinedArea(5, 0);
QCOMPARE(m_area->joinedIDs().size(), 1);
QCOMPARE(m_area->charactersTaken().at(0), 5);
}
{
// No clients must be left in the area.
m_area->clientLeftArea(5,0);
m_area->clientLeftArea(5, 0);
QCOMPARE(m_area->joinedIDs().size(), 0);
}
@ -143,7 +143,8 @@ void Area::changeHP()
if (AreaData::Side::DEFENCE == side) {
QCOMPARE(expectedHP, m_area->defHP());
} else {
}
else {
QCOMPARE(expectedHP, m_area->proHP());
}
}
@ -152,7 +153,7 @@ void Area::changeCharacter()
{
{
// A client with a charid of 6 and userid 0 joins. There's only them in there.
m_area->clientJoinedArea(6,0);
m_area->clientJoinedArea(6, 0);
QCOMPARE(m_area->charactersTaken().size(), 1);
QCOMPARE(m_area->charactersTaken().at(0), 6);
@ -211,8 +212,7 @@ void Area::testimony()
{
// Add all statements, and check that they're added.
for (const auto& l_statement : l_testimony)
{
for (const auto &l_statement : l_testimony) {
m_area->recordStatement(l_statement);
QCOMPARE(l_statement, m_area->testimony().at(m_area->statement() - 1));
@ -223,22 +223,22 @@ void Area::testimony()
m_area->jumpToStatement(1);
for (int i = 1; i < l_testimony.size() - 1; i++) {
const auto& l_results = m_area->jumpToStatement(m_area->statement() + 1);
const auto &l_results = m_area->jumpToStatement(m_area->statement() + 1);
QCOMPARE(l_results.first, l_testimony.at(i + 1));
QCOMPARE(l_results.second, AreaData::TestimonyProgress::OK);
QCOMPARE(l_results.first, l_testimony.at(i + 1));
QCOMPARE(l_results.second, AreaData::TestimonyProgress::OK);
}
}
{
// Next advancement loops the testimony.
const auto& l_results = m_area->jumpToStatement(m_area->statement() + 1);
const auto &l_results = m_area->jumpToStatement(m_area->statement() + 1);
QCOMPARE(l_results.first, l_testimony.at(1));
QCOMPARE(l_results.second, AreaData::TestimonyProgress::LOOPED);
}
{
// Going back makes the testimony stay at the first statement.
const auto& l_results = m_area->jumpToStatement(m_area->statement() - 1);
const auto &l_results = m_area->jumpToStatement(m_area->statement() - 1);
QCOMPARE(l_results.first, l_testimony.at(1));
QCOMPARE(l_results.second, AreaData::TestimonyProgress::STAYED_AT_FIRST);

View File

@ -11,14 +11,14 @@ namespace unittests {
class MusicListManager : public QObject
{
Q_OBJECT
public :
MusicManager* m_music_manager;
public:
MusicManager *m_music_manager;
private slots:
private slots:
/**
* @brief Initialises every tests with creating a new MusicManager with a small sample root list.
*/
* @brief Initialises every tests with creating a new MusicManager with a small sample root list.
*/
void init();
/**
@ -70,56 +70,56 @@ private slots:
* @brief Tests the retrieval of the full musiclist for an area.
*/
void musiclist();
};
void MusicListManager::init()
{
QMap<QString,QPair<QString,int>> l_test_list;
l_test_list.insert("==Music==",{"==Music==",0});
l_test_list.insert("Announce The Truth (AJ).opus",{"Announce The Truth (AJ).opus",59});
l_test_list.insert("Announce The Truth (JFA).opus",{"Announce The Truth (JFA).opus",98});
QMap<QString, QPair<QString, int>> l_test_list;
l_test_list.insert("==Music==", {"==Music==", 0});
l_test_list.insert("Announce The Truth (AJ).opus", {"Announce The Truth (AJ).opus", 59});
l_test_list.insert("Announce The Truth (JFA).opus", {"Announce The Truth (JFA).opus", 98});
QStringList l_list = {};
l_list << "==Music==" << "Announce The Truth (AJ).opus" << "Announce The Truth (JFA).opus";
l_list << "==Music=="
<< "Announce The Truth (AJ).opus"
<< "Announce The Truth (JFA).opus";
m_music_manager = new MusicManager(nullptr, l_list ,{"my.cdn.com","your.cdn.com"}, l_test_list);
m_music_manager = new MusicManager(l_list, {"my.cdn.com", "your.cdn.com"}, l_test_list, nullptr);
}
void MusicListManager::registerArea()
{
{
//We register a single area with the music manager of ID 0.
//Creation should work as there are no other areas yet.
// We register a single area with the music manager of ID 0.
// Creation should work as there are no other areas yet.
bool l_creation_success = m_music_manager->registerArea(0);
QCOMPARE(l_creation_success,true);
QCOMPARE(l_creation_success, true);
}
{
//Someone tries to register the same area again!
//This should fail as this area already exists.
// Someone tries to register the same area again!
// This should fail as this area already exists.
bool l_creation_success = m_music_manager->registerArea(0);
QCOMPARE(l_creation_success,false);
QCOMPARE(l_creation_success, false);
}
}
void MusicListManager::toggleRootEnabled()
{
{
//We register an area of ID0 and toggle the inclusion of global list.
// We register an area of ID0 and toggle the inclusion of global list.
m_music_manager->registerArea(0);
QCOMPARE(m_music_manager->toggleRootEnabled(0), false);
}
{
//We toggle it again. It should return true now.
//Since this is now true, we should have the root list with customs cleared.
// We toggle it again. It should return true now.
// Since this is now true, we should have the root list with customs cleared.
QCOMPARE(m_music_manager->toggleRootEnabled(0), true);
}
}
void MusicListManager::validateSong_data()
{
//Songname can also be the realname.
// Songname can also be the realname.
QTest::addColumn<QString>("songname");
QTest::addColumn<bool>("expectedResult");
@ -137,47 +137,47 @@ void MusicListManager::validateSong_data()
void MusicListManager::validateSong()
{
QFETCH(QString,songname);
QFETCH(bool,expectedResult);
QFETCH(QString, songname);
QFETCH(bool, expectedResult);
bool l_result = m_music_manager->validateSong(songname, {"my.cdn.com","your.cdn.com"});
QCOMPARE(expectedResult,l_result);
bool l_result = m_music_manager->validateSong(songname, {"my.cdn.com", "your.cdn.com"});
QCOMPARE(expectedResult, l_result);
}
void MusicListManager::addCustomSong()
{
{
//Dummy register.
// Dummy register.
m_music_manager->registerArea(0);
//No custom songs, so musiclist = root_list.size()
// No custom songs, so musiclist = root_list.size()
QCOMPARE(m_music_manager->musiclist(0).size(), 3);
}
{
//Add a song that's valid. The musiclist is now root_list.size() + custom_list.size()
m_music_manager->addCustomSong("mysong","mysong.opus",0,0);
// Add a song that's valid. The musiclist is now root_list.size() + custom_list.size()
m_music_manager->addCustomSong("mysong", "mysong.opus", 0, 0);
QCOMPARE(m_music_manager->musiclist(0).size(), 4);
}
{
//Add a song that's part of the root list. This should fail and not increase the size.
bool l_result = m_music_manager->addCustomSong("Announce The Truth (AJ)","Announce The Truth (AJ).opus",0,0);
QCOMPARE(l_result,false);
// Add a song that's part of the root list. This should fail and not increase the size.
bool l_result = m_music_manager->addCustomSong("Announce The Truth (AJ)", "Announce The Truth (AJ).opus", 0, 0);
QCOMPARE(l_result, false);
QCOMPARE(m_music_manager->musiclist(0).size(), 4);
}
{
//Disable the root list. Musiclist is now custom_list.size()
// Disable the root list. Musiclist is now custom_list.size()
m_music_manager->toggleRootEnabled(0);
QCOMPARE(m_music_manager->musiclist(0).size(), 1);
}
{
//Add an item that is in the root list into the custom list. Size is still custom_list.size()
bool l_result = m_music_manager->addCustomSong("Announce The Truth (AJ)","Announce The Truth (AJ).opus",0,0);
QCOMPARE(l_result,true);
// Add an item that is in the root list into the custom list. Size is still custom_list.size()
bool l_result = m_music_manager->addCustomSong("Announce The Truth (AJ)", "Announce The Truth (AJ).opus", 0, 0);
QCOMPARE(l_result, true);
QCOMPARE(m_music_manager->musiclist(0).size(), 2);
}
{
bool l_result = m_music_manager->addCustomSong("Announce The Truth (AJ)2","https://my.cdn.com/mysong.opus",0,0);
QCOMPARE(l_result,true);
bool l_result = m_music_manager->addCustomSong("Announce The Truth (AJ)2", "https://my.cdn.com/mysong.opus", 0, 0);
QCOMPARE(l_result, true);
QCOMPARE(m_music_manager->musiclist(0).size(), 3);
}
}
@ -185,93 +185,91 @@ void MusicListManager::addCustomSong()
void MusicListManager::addCustomCategory()
{
{
//Dummy register.
// Dummy register.
m_music_manager->registerArea(0);
//Add category to the custom list. Category marker are added manually.
bool l_result = m_music_manager->addCustomCategory("Music2",0);
QCOMPARE(l_result,true);
// Add category to the custom list. Category marker are added manually.
bool l_result = m_music_manager->addCustomCategory("Music2", 0);
QCOMPARE(l_result, true);
QCOMPARE(m_music_manager->musiclist(0).size(), 4);
QCOMPARE(m_music_manager->musiclist(0).at(3), "==Music2==");
}
{
//Add a category that already exists on root. This should fail and not increase the size of our list.
bool l_result = m_music_manager->addCustomCategory("Music",0);
// Add a category that already exists on root. This should fail and not increase the size of our list.
bool l_result = m_music_manager->addCustomCategory("Music", 0);
QCOMPARE(l_result, false);
QCOMPARE(m_music_manager->musiclist(0).size(), 4);
}
{
//We disable the root list. We now insert the category again.
// We disable the root list. We now insert the category again.
m_music_manager->toggleRootEnabled(0);
bool l_result = m_music_manager->addCustomCategory("Music",0);
bool l_result = m_music_manager->addCustomCategory("Music", 0);
QCOMPARE(l_result, true);
QCOMPARE(m_music_manager->musiclist(0).size(), 2);
QCOMPARE(m_music_manager->musiclist(0).at(1), "==Music==");
}
{
//Global now enabled. We add a song with three ===.
// Global now enabled. We add a song with three ===.
m_music_manager->toggleRootEnabled(0);
bool l_result = m_music_manager->addCustomCategory("===Music===",0);
bool l_result = m_music_manager->addCustomCategory("===Music===", 0);
QCOMPARE(l_result, true);
QCOMPARE(m_music_manager->musiclist(0).size(), 5);
QCOMPARE(m_music_manager->musiclist(0).at(4), "===Music===");
}
}
void MusicListManager::sanitiseCustomList()
{
//Prepare a dummy area with root list disabled.Insert both non-root and root elements.
// Prepare a dummy area with root list disabled.Insert both non-root and root elements.
m_music_manager->registerArea(0);
m_music_manager->toggleRootEnabled(0);
m_music_manager->addCustomCategory("Music",0);
m_music_manager->addCustomCategory("Music2",0);
m_music_manager->addCustomSong("Announce The Truth (AJ)","Announce The Truth (AJ).opus",0,0);
m_music_manager->addCustomSong("mysong","mysong.opus",0,0);
m_music_manager->addCustomCategory("Music", 0);
m_music_manager->addCustomCategory("Music2", 0);
m_music_manager->addCustomSong("Announce The Truth (AJ)", "Announce The Truth (AJ).opus", 0, 0);
m_music_manager->addCustomSong("mysong", "mysong.opus", 0, 0);
//We now only have custom elements.
// We now only have custom elements.
QCOMPARE(m_music_manager->musiclist(0).size(), 4);
//We reenable the root list. Sanisation should only leave the non-root elements in the custom list.
// We reenable the root list. Sanisation should only leave the non-root elements in the custom list.
m_music_manager->toggleRootEnabled(0);
QCOMPARE(m_music_manager->musiclist(0).size(), 5);
QCOMPARE(m_music_manager->musiclist(0).at(3), "==Music2==");
QCOMPARE(m_music_manager->musiclist(0).at(4), "mysong.opus");
}
void MusicListManager::removeCategorySong()
{
{
//Prepare dummy area. Add both custom songs and categories.
// Prepare dummy area. Add both custom songs and categories.
m_music_manager->registerArea(0);
m_music_manager->addCustomCategory("Music2",0);
m_music_manager->addCustomSong("mysong","mysong.opus",0,0);
m_music_manager->addCustomCategory("Music3",0);
m_music_manager->addCustomSong("mysong2","mysong.opus",0,0);
m_music_manager->addCustomCategory("Music2", 0);
m_music_manager->addCustomSong("mysong", "mysong.opus", 0, 0);
m_music_manager->addCustomCategory("Music3", 0);
m_music_manager->addCustomSong("mysong2", "mysong.opus", 0, 0);
QCOMPARE(m_music_manager->musiclist(0).size(), 7);
}
{
//Delete a category that is not custom. This should fail.
bool l_success = m_music_manager->removeCategorySong("==Music==",0);
// Delete a category that is not custom. This should fail.
bool l_success = m_music_manager->removeCategorySong("==Music==", 0);
QCOMPARE(l_success, false);
QCOMPARE(m_music_manager->musiclist(0).size(), 7);
}
{
//Correct category name, wrong format.
bool l_success = m_music_manager->removeCategorySong("Music2",0);
// Correct category name, wrong format.
bool l_success = m_music_manager->removeCategorySong("Music2", 0);
QCOMPARE(l_success, false);
QCOMPARE(m_music_manager->musiclist(0).size(), 7);
}
{
//Correct category name. This should be removed.
bool l_success = m_music_manager->removeCategorySong("==Music2==",0);
// Correct category name. This should be removed.
bool l_success = m_music_manager->removeCategorySong("==Music2==", 0);
QCOMPARE(l_success, true);
QCOMPARE(m_music_manager->musiclist(0).size(), 6);
}
{
//Correct song name. This should be removed. This needs to be with the extension.
bool l_success = m_music_manager->removeCategorySong("mysong2.opus",0);
// Correct song name. This should be removed. This needs to be with the extension.
bool l_success = m_music_manager->removeCategorySong("mysong2.opus", 0);
QCOMPARE(l_success, true);
QCOMPARE(m_music_manager->musiclist(0).size(), 5);
}
@ -280,20 +278,20 @@ void MusicListManager::removeCategorySong()
void MusicListManager::songInformation()
{
{
//Prepare dummy area. Add both custom songs and categories.
// Prepare dummy area. Add both custom songs and categories.
m_music_manager->registerArea(0);
m_music_manager->addCustomCategory("Music2",0);
m_music_manager->addCustomSong("mysong","realmysong.opus",47,0);
m_music_manager->addCustomCategory("Music3",0);
m_music_manager->addCustomSong("mysong2","mysong.opus",42,0);
m_music_manager->addCustomCategory("Music2", 0);
m_music_manager->addCustomSong("mysong", "realmysong.opus", 47, 0);
m_music_manager->addCustomCategory("Music3", 0);
m_music_manager->addCustomSong("mysong2", "mysong.opus", 42, 0);
}
{
QPair<QString,int> l_song_information = m_music_manager->songInformation("mysong.opus",0);
QPair<QString, int> l_song_information = m_music_manager->songInformation("mysong.opus", 0);
QCOMPARE(l_song_information.first, "realmysong.opus");
QCOMPARE(l_song_information.second, 47);
}
{
QPair<QString,int> l_song_information = m_music_manager->songInformation("Announce The Truth (AJ).opus",0);
QPair<QString, int> l_song_information = m_music_manager->songInformation("Announce The Truth (AJ).opus", 0);
QCOMPARE(l_song_information.first, "Announce The Truth (AJ).opus");
QCOMPARE(l_song_information.second, 59);
}
@ -302,12 +300,12 @@ void MusicListManager::songInformation()
void MusicListManager::musiclist()
{
{
//Prepare dummy area. Add both custom songs and categories.
// Prepare dummy area. Add both custom songs and categories.
m_music_manager->registerArea(0);
m_music_manager->addCustomCategory("Music2",0);
m_music_manager->addCustomSong("mysong","realmysong.opus",47,0);
m_music_manager->addCustomCategory("Music3",0);
m_music_manager->addCustomSong("mysong2","mysong.opus",42,0);
m_music_manager->addCustomCategory("Music2", 0);
m_music_manager->addCustomSong("mysong", "realmysong.opus", 47, 0);
m_music_manager->addCustomCategory("Music3", 0);
m_music_manager->addCustomSong("mysong2", "mysong.opus", 42, 0);
}
{
QCOMPARE(m_music_manager->musiclist(0).size(), 7);