diff --git a/include/aoclient.h b/include/aoclient.h index 63203ce..7918072 100644 --- a/include/aoclient.h +++ b/include/aoclient.h @@ -57,6 +57,8 @@ class AOClient : public QObject { bool authenticated = false; QString moderator_name = ""; QString ooc_name = ""; + QString showname = ""; + bool global_enabled = true; QMap ACLFlags { {"NONE", 0ULL}, @@ -96,6 +98,7 @@ class AOClient : public QObject { void handlePacket(AOPacket packet); void handleCommand(QString command, int argc, QStringList argv); void changeArea(int new_area); + void changeCharacter(int char_id); void arup(ARUPType type, bool broadcast); void fullArup(); void sendServerMessage(QString message); @@ -188,13 +191,17 @@ class AOClient : public QObject { void cmdUnLock(int argc, QStringList argv); void cmdGetAreas(int argc, QStringList argv); void cmdGetArea(int argc, QStringList argv); + void cmdArea(int argc, QStringList argv); + void cmdAreaKick(int argc, QStringList argv); void cmdSetBackground(int argc, QStringList argv); void cmdBgLock(int argc, QStringList argv); void cmdBgUnlock(int argc, QStringList argv); // Moderation + void cmdMods(int argc, QStringList argv); void cmdBan(int argc, QStringList argv); void cmdKick(int argc, QStringList argv); // Casing/RP + void cmdPlay(int argc, QStringList argv); void cmdNeed(int argc, QStringList argv); void cmdFlip(int argc, QStringList argv); void cmdRoll(int argc, QStringList argv); @@ -204,7 +211,10 @@ class AOClient : public QObject { void cmdTimer(int argc, QStringList argv); // Messaging/Client void cmdPos(int argc, QStringList argv); + void cmdSwitch(int argc, QStringList argv); + void cmdRandomChar(int argc, QStringList argv); void cmdG(int argc, QStringList argv); + void cmdToggleGlobal(int argc, QStringList argv); // Command helper functions QString getAreaTimer(int area_idx, QTimer* timer); @@ -242,7 +252,7 @@ class AOClient : public QObject { {"pos", {ACLFlags.value("NONE"), 1, &AOClient::cmdPos}}, {"g", {ACLFlags.value("NONE"), 1, &AOClient::cmdG}}, {"need", {ACLFlags.value("NONE"), 1, &AOClient::cmdNeed}}, - {"flip", {ACLFlags.value("NONE"), 0, &AOClient::cmdFlip}}, + {"coinflip", {ACLFlags.value("NONE"), 0, &AOClient::cmdFlip}}, {"roll", {ACLFlags.value("NONE"), 0, &AOClient::cmdRoll}}, {"rollp", {ACLFlags.value("NONE"), 0, &AOClient::cmdRollP}}, {"doc", {ACLFlags.value("NONE"), 0, &AOClient::cmdDoc}}, @@ -252,9 +262,20 @@ class AOClient : public QObject { {"invite", {ACLFlags.value("CM"), 1, &AOClient::cmdInvite}}, {"uninvite", {ACLFlags.value("CM"), 1, &AOClient::cmdUnInvite}}, {"lock", {ACLFlags.value("CM"), 0, &AOClient::cmdLock}}, + {"area_lock", {ACLFlags.value("CM"), 0, &AOClient::cmdLock}}, {"spectatable", {ACLFlags.value("CM"), 0, &AOClient::cmdSpectatable}}, + {"area_spectate", {ACLFlags.value("CM"), 0, &AOClient::cmdSpectatable}}, {"unlock", {ACLFlags.value("CM"), 0, &AOClient::cmdUnLock}}, + {"area_unlock", {ACLFlags.value("CM"), 0, &AOClient::cmdUnLock}}, {"timer", {ACLFlags.value("CM"), 0, &AOClient::cmdTimer}}, + {"area", {ACLFlags.value("NONE"), 1, &AOClient::cmdArea}}, + {"play", {ACLFlags.value("CM"), 1, &AOClient::cmdPlay}}, + {"areakick", {ACLFlags.value("CM"), 1, &AOClient::cmdAreaKick}}, + {"area_kick", {ACLFlags.value("CM"), 1, &AOClient::cmdAreaKick}}, + {"randomchar", {ACLFlags.value("NONE"), 0, &AOClient::cmdRandomChar}}, + {"switch", {ACLFlags.value("NONE"), 1, &AOClient::cmdSwitch}}, + {"toggleglobal", {ACLFlags.value("NONE"), 0, &AOClient::cmdToggleGlobal}}, + {"mods", {ACLFlags.value("NONE"), 0, &AOClient::cmdMods}}, }; QString partial_packet; diff --git a/include/server.h b/include/server.h index ae7db9c..152fc37 100644 --- a/include/server.h +++ b/include/server.h @@ -53,6 +53,7 @@ class Server : public QObject { void broadcast(AOPacket packet); QString getServerName(); int getDiceValue(QString value_type); + int getCharID(QString char_name); QVector clients; diff --git a/src/aoclient.cpp b/src/aoclient.cpp index 7d3a90c..5a7f3ac 100644 --- a/src/aoclient.cpp +++ b/src/aoclient.cpp @@ -145,6 +145,54 @@ void AOClient::changeArea(int new_area) sendServerMessage("Area " + server->area_names[current_area] + " is spectate-only; to chat IC you will need to be invited by the CM."); } +void AOClient::changeCharacter(int char_id) +{ + AreaData* area = server->areas[current_area]; + + if (current_char != "") { + area->characters_taken[current_char] = false; + } + + if(char_id > server->characters.length()) + return; + + if (char_id >= 0) { + QString char_selected = server->characters[char_id]; + bool taken = area->characters_taken.value(char_selected); + if (taken || char_selected == "") + return; + + area->characters_taken[char_selected] = true; + current_char = char_selected; + } + else { + current_char = ""; + } + + pos = ""; + + server->updateCharsTaken(area); + sendPacket("PV", {QString::number(id), "CID", QString::number(char_id)}); + fullArup(); + if (server->timer->isActive()) { + sendPacket("TI", {QString::number(0), QString::number(2)}); + sendPacket("TI", {QString::number(0), QString::number(0), QString::number(QTime(0,0).msecsTo(QTime(0,0).addMSecs(server->timer->remainingTime())))}); + } + else { + sendPacket("TI", {QString::number(0), QString::number(3)}); + } + for (QTimer* timer : area->timers) { + int timer_id = area->timers.indexOf(timer) + 1; + if (timer->isActive()) { + sendPacket("TI", {QString::number(timer_id), QString::number(2)}); + sendPacket("TI", {QString::number(timer_id), QString::number(0), QString::number(QTime(0,0).msecsTo(QTime(0,0).addMSecs(timer->remainingTime())))}); + } + else { + sendPacket("TI", {QString::number(timer_id), QString::number(3)}); + } + } +} + void AOClient::handleCommand(QString command, int argc, QStringList argv) { CommandInfo info = commands.value(command, {false, -1, &AOClient::cmdDefault}); diff --git a/src/commands.cpp b/src/commands.cpp index dcbacf0..5396260 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -373,7 +373,10 @@ void AOClient::cmdG(int argc, QStringList argv) QString sender_name = ooc_name; QString sender_area = server->area_names.value(current_area); QString sender_message = argv.join(" "); - server->broadcast(AOPacket("CT", {"[" + sender_area + "]" + sender_name, sender_message})); + for (AOClient* client : server->clients) { + if (client->global_enabled) + client->sendPacket("CT", {"[G][" + sender_area + "]" + sender_name, sender_message}); + } return; } @@ -637,6 +640,82 @@ void AOClient::cmdTimer(int argc, QStringList argv) } } +void AOClient::cmdArea(int argc, QStringList argv) +{ + bool ok; + int new_area = argv[0].toInt(&ok); + if (!ok || new_area >= server->areas.size() || new_area < 0) { + sendServerMessage("That does not look like a valid area ID."); + return; + } + changeArea(new_area); +} + +void AOClient::cmdPlay(int argc, QStringList argv) +{ + sendPacket("MC", {argv.join(" "), QString::number(server->getCharID(current_char)), showname, "1", "0"}); +} + +void AOClient::cmdAreaKick(int argc, QStringList argv) +{ + bool ok; + int idx = argv[0].toInt(&ok); + if (!ok) { + sendServerMessage("That does not look like a valid ID."); + return; + } + AOClient* client_to_kick = server->getClientByID(idx); + client_to_kick->changeArea(0); + sendServerMessage("Client " + argv[0] + " kicked back to area 0."); +} + +void AOClient::cmdSwitch(int argc, QStringList argv) +{ + int char_id = server->getCharID(argv.join(" ")); + if (char_id == -1) { + sendServerMessage("That does not look like a valid character."); + return; + } + changeCharacter(char_id); +} + +void AOClient::cmdRandomChar(int argc, QStringList argv) +{ + int char_id = genRand(0, server->characters.size() - 1); + changeCharacter(char_id); +} + +void AOClient::cmdToggleGlobal(int argc, QStringList argv) +{ + global_enabled = !global_enabled; + QString str_en = global_enabled ? "shown" : "hidden"; + sendServerMessage("Global chat set to " + str_en); +} + +void AOClient::cmdMods(int argc, QStringList argv) +{ + QStringList entries; + QSettings config("config/config.ini", QSettings::IniFormat); + config.beginGroup("Options"); + QString auth_type = config.value("auth", "simple").toString(); + int online_count = 0; + for (AOClient* client : server->clients) { + if (client->authenticated) { + entries << "---"; + if (auth_type != "simple") + entries << "Moderator: " + moderator_name; + entries << "OOC name: " + ooc_name; + entries << "ID: " + QString::number(client->id); + entries << "Area: " + QString::number(client->current_area); + entries << "Character: " + client->current_char; + online_count++; + } + } + entries << "---"; + entries << "Total online: " << QString::number(online_count); + sendServerMessage(entries.join("\n")); +} + QStringList AOClient::buildAreaList(int area_idx) { QStringList entries; diff --git a/src/packets.cpp b/src/packets.cpp index ad68d78..6d2641d 100644 --- a/src/packets.cpp +++ b/src/packets.cpp @@ -118,48 +118,7 @@ void AOClient::pktSelectChar(AreaData* area, int argc, QStringList argv, AOPacke return; } - if (current_char != "") { - area->characters_taken[current_char] = false; - } - - if(char_id > server->characters.length()) - return; - - if (char_id >= 0) { - QString char_selected = server->characters[char_id]; - bool taken = area->characters_taken.value(char_selected); - if (taken || char_selected == "") - return; - - area->characters_taken[char_selected] = true; - current_char = char_selected; - } - else { - current_char = ""; - } - - pos = ""; - - server->updateCharsTaken(area); - sendPacket("PV", {QString::number(id), "CID", argv[1]}); - fullArup(); - if (server->timer->isActive()) { - sendPacket("TI", {QString::number(0), QString::number(2)}); - sendPacket("TI", {QString::number(0), QString::number(0), QString::number(QTime(0,0).msecsTo(QTime(0,0).addMSecs(server->timer->remainingTime())))}); - } - else { - sendPacket("TI", {QString::number(0), QString::number(3)}); - } - for (QTimer* timer : area->timers) { - int timer_id = area->timers.indexOf(timer) + 1; - if (timer->isActive()) { - sendPacket("TI", {QString::number(timer_id), QString::number(2)}); - sendPacket("TI", {QString::number(timer_id), QString::number(0), QString::number(QTime(0,0).msecsTo(QTime(0,0).addMSecs(timer->remainingTime())))}); - } - else { - sendPacket("TI", {QString::number(timer_id), QString::number(3)}); - } - } + changeCharacter(char_id); } void AOClient::pktIcChat(AreaData* area, int argc, QStringList argv, AOPacket packet) @@ -177,7 +136,11 @@ void AOClient::pktIcChat(AreaData* area, int argc, QStringList argv, AOPacket pa void AOClient::pktOocChat(AreaData* area, int argc, QStringList argv, AOPacket packet) { - ooc_name = dezalgo(argv[0]); + ooc_name = dezalgo(argv[0]).replace(QRegExp("\\[|\\]|\\{|\\}|\\#|\\$|\\%|\\&"), ""); // no fucky wucky shit here + + if (ooc_name == server->getServerName()) // impersonation prevention + return; + QString message = dezalgo(argv[1]); AOPacket final_packet("CT", {ooc_name, message, "0"}); if(message.at(0) == '/') { @@ -289,7 +252,7 @@ void AOClient::pktRemoveEvidence(AreaData* area, int argc, QStringList argv, AOP { bool is_int = false; int idx = argv[0].toInt(&is_int); - if (is_int) { + if (is_int && idx <= area->evidence.size() && idx >= 0) { area->evidence.removeAt(idx); } sendEvidenceList(area); @@ -300,7 +263,7 @@ void AOClient::pktEditEvidence(AreaData* area, int argc, QStringList argv, AOPac bool is_int = false; int idx = argv[0].toInt(&is_int); AreaData::Evidence evi = {argv[1], argv[2], argv[3]}; - if (is_int) { + if (is_int && idx <= area->evidence.size() && idx >= 0) { area->evidence.replace(idx, evi); } sendEvidenceList(area); @@ -454,8 +417,9 @@ AOPacket AOClient::validateIcPacket(AOPacket packet) // 2.6 packet extensions if (incoming_args.length() > 15) { // showname - QString showname = dezalgo(incoming_args[15].toString().trimmed()); - args.append(showname); + QString incoming_showname = dezalgo(incoming_args[15].toString().trimmed()); + args.append(incoming_showname); + showname = incoming_showname; // other char id // things get a bit hairy here diff --git a/src/server.cpp b/src/server.cpp index b9acff4..bbe7fc5 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -191,6 +191,16 @@ AOClient* Server::getClientByID(int id) return nullptr; } +int Server::getCharID(QString char_name) +{ + for (QString character : characters) { + if (character.toLower() == char_name.toLower()) { + return characters.indexOf(QRegExp(character, Qt::CaseInsensitive)); + } + } + return -1; // character does not exist +} + Server::~Server() { for (AOClient* client : clients) {