refactor command parser

This commit is contained in:
scatterflower 2020-09-28 19:11:12 -05:00
parent acc6966216
commit 20492c6a33
4 changed files with 165 additions and 128 deletions

View File

@ -26,6 +26,7 @@ SOURCES += src/advertiser.cpp \
src/aopacket.cpp \
src/area_data.cpp \
src/ban_manager.cpp \
src/commands.cpp \
src/config_manager.cpp \
src/icchatpacket.cpp \
src/main.cpp \

View File

@ -46,6 +46,8 @@ class AOClient : public QObject {
bool joined;
int current_area;
QString current_char;
bool authenticated = false;
QString ooc_name = "";
public slots:
void clientDisconnected();
@ -54,7 +56,6 @@ class AOClient : public QObject {
void sendPacket(QString header, QStringList contents);
void sendPacket(QString header);
private:
Server* server;
QTcpSocket* socket;
@ -66,19 +67,6 @@ class AOClient : public QObject {
LOCKED
};
struct CommandInfo {
bool privileged;
int minArgs;
};
const QMap<QString, CommandInfo> commands {
{"login", {false, 1}},
{"getareas", {false, 0 }},
{"getarea", {false, 0}},
{"ban", {true, 2}},
{"kick", {true, 2}}
};
void handlePacket(AOPacket packet);
void handleCommand(QString command, int argc, QStringList argv);
void changeArea(int new_area);
@ -86,6 +74,31 @@ class AOClient : public QObject {
void fullArup();
void sendServerMessage(QString message);
// Commands
void cmdDefault(int argc, QStringList argv);
void cmdLogin(int argc, QStringList argv);
void cmdGetAreas(int argc, QStringList argv);
void cmdGetArea(int argc, QStringList argv);
void cmdBan(int argc, QStringList argv);
void cmdKick(int argc, QStringList argv);
// Command helper functions
QStringList buildAreaList(int area_idx);
struct CommandInfo {
bool privileged;
int minArgs;
void (AOClient::*action)(int, QStringList);
};
const QMap<QString, CommandInfo> commands {
{"login", {false, 1, &AOClient::cmdLogin}},
{"getareas", {false, 0 , &AOClient::cmdGetAreas}},
{"getarea", {false, 0, &AOClient::cmdGetArea}},
{"ban", {true, 2, &AOClient::cmdBan}},
{"kick", {true, 2, &AOClient::cmdKick}}
};
QString partial_packet;
bool is_partial;
@ -93,9 +106,6 @@ class AOClient : public QObject {
QString ipid;
long last_wtce_time;
QString last_message;
bool authenticated = false;
QString ooc_name = "";
};
#endif // AOCLIENT_H

View File

@ -283,13 +283,7 @@ void AOClient::changeArea(int new_area)
void AOClient::handleCommand(QString command, int argc, QStringList argv)
{
// Be sure to register the command in the header before adding it here!
CommandInfo info = commands.value(command, {false, -1});
if (info.minArgs == -1) {
sendServerMessage("Invalid command.");
return;
}
CommandInfo info = commands.value(command, {false, -1, &AOClient::cmdDefault});
if (info.privileged && !authenticated) {
sendServerMessage("You do not have permission to use that command.");
@ -301,110 +295,7 @@ void AOClient::handleCommand(QString command, int argc, QStringList argv)
return;
}
if (command == "login") {
QSettings config("config/config.ini", QSettings::IniFormat);
config.beginGroup("Options");
QString modpass = config.value("modpass", "default").toString();;
// TODO: tell the user if no modpass is set
if(argv[0] == modpass) {
sendServerMessage("Logged in as a moderator."); // This string has to be exactly this, because it is hardcoded in the client
authenticated = true;
} else {
sendServerMessage("Incorrect password.");
return;
}
}
else if (command == "getareas") {
QStringList entries;
entries.append("== Area List ==");
for (int i = 0; i < server->area_names.length(); i++) {
QString area_name = server->area_names[i];
AreaData* area = server->areas[i];
entries.append("=== " + area_name + " ===");
entries.append("[" + QString::number(area->player_count) + " users][" + area->status + "]");
for (AOClient* client : server->clients) {
if (client->current_area == i) {
QString char_entry = client->current_char;
if (authenticated)
char_entry += " (" + client->getIpid() + "): " + ooc_name;
entries.append(char_entry);
}
}
}
sendServerMessage(entries.join("\n"));
}
else if (command == "getarea") {
// TODO: get rid of copy-pasted code
QStringList entries;
QString area_name = server->area_names[current_area];
AreaData* area = server->areas[current_area];
entries.append("=== " + area_name + " ===");
entries.append("[" + QString::number(area->player_count) + " users][" + area->status + "]");
for (AOClient* client : server->clients) {
if (client->current_area == current_area) {
QString char_entry = client->current_char;
if (authenticated)
char_entry += " (" + client->getIpid() + "): " + ooc_name;
entries.append(char_entry);
}
}
sendServerMessage(entries.join("\n"));
}
else if (command == "ban") {
QString target_ipid = argv[0];
QHostAddress ip;
QString hdid;
unsigned long time = QDateTime::currentDateTime().toTime_t();
QString reason = argv[1];
bool ban_logged = false;
if (argc > 2) {
for (int i = 2; i < argv.length(); i++) {
reason += " " + argv[i];
}
}
for (AOClient* client : server->clients) {
if (client->getIpid() == target_ipid) {
if (!ban_logged) {
ip = client->remote_ip;
hdid = client->hwid;
server->ban_manager->addBan(target_ipid, ip, hdid, time, reason);
sendServerMessage("Banned user with ipid " + target_ipid + " for reason: " + reason);
ban_logged = true;
}
client->sendPacket("KB", {reason});
client->socket->close();
}
}
if (!ban_logged)
sendServerMessage("User with ipid not found!");
}
else if (command == "kick") {
QString target_ipid = argv[0];
QString reason = argv[1];
bool did_kick = false;
if (argc > 2) {
for (int i = 2; i < argv.length(); i++) {
reason += " " + argv[i];
}
}
for (AOClient* client : server->clients) {
if (client->getIpid() == target_ipid) {
client->sendPacket("KK", {reason});
client->socket->close();
did_kick = true;
}
}
if (did_kick)
sendServerMessage("Banned user with ipid " + target_ipid + " for reason: " + reason);
else
sendServerMessage("User with ipid not found!");
}
(this->*(info.action))(argc, argv);
}
void AOClient::arup(ARUPType type, bool broadcast)

135
src/commands.cpp Normal file
View File

@ -0,0 +1,135 @@
//////////////////////////////////////////////////////////////////////////////////////
// akashi - a server for Attorney Online 2 //
// Copyright (C) 2020 scatterflower //
// //
// This program is free software: you can redistribute it and/or modify //
// it under the terms of the GNU Affero General Public License as //
// published by the Free Software Foundation, either version 3 of the //
// License, or (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU Affero General Public License for more details. //
// //
// You should have received a copy of the GNU Affero General Public License //
// along with this program. If not, see <https://www.gnu.org/licenses/>. //
//////////////////////////////////////////////////////////////////////////////////////
#include "include/aoclient.h"
// Be sure to register the command in the header before adding it here!
void AOClient::cmdDefault(int argc, QStringList argv)
{
sendServerMessage("Invalid command.");
return;
}
void AOClient::cmdLogin(int argc, QStringList argv)
{
QSettings config("config/config.ini", QSettings::IniFormat);
config.beginGroup("Options");
QString modpass = config.value("modpass", "default").toString();;
// TODO: tell the user if no modpass is set
if(argv[0] == modpass) {
sendServerMessage("Logged in as a moderator."); // This string has to be exactly this, because it is hardcoded in the client
authenticated = true;
} else {
sendServerMessage("Incorrect password.");
return;
}
}
void AOClient::cmdGetAreas(int argc, QStringList argv)
{
QStringList entries;
entries.append("== Area List ==");
for (int i = 0; i < server->area_names.length(); i++) {
QStringList cur_area_lines = buildAreaList(i);
entries.append(cur_area_lines);
}
sendServerMessage(entries.join("\n"));
}
void AOClient::cmdGetArea(int argc, QStringList argv)
{
QStringList entries = buildAreaList(current_area);
sendServerMessage(entries.join("\n"));
}
void AOClient::cmdBan(int argc, QStringList argv)
{
QString target_ipid = argv[0];
QHostAddress ip;
QString hdid;
unsigned long time = QDateTime::currentDateTime().toTime_t();
QString reason = argv[1];
bool ban_logged = false;
if (argc > 2) {
for (int i = 2; i < argv.length(); i++) {
reason += " " + argv[i];
}
}
for (AOClient* client : server->clients) {
if (client->getIpid() == target_ipid) {
if (!ban_logged) {
ip = client->remote_ip;
hdid = client->hwid;
server->ban_manager->addBan(target_ipid, ip, hdid, time, reason);
sendServerMessage("Banned user with ipid " + target_ipid + " for reason: " + reason);
ban_logged = true;
}
client->sendPacket("KB", {reason});
client->socket->close();
}
}
if (!ban_logged)
sendServerMessage("User with ipid not found!");
}
void AOClient::cmdKick(int argc, QStringList argv)
{
QString target_ipid = argv[0];
QString reason = argv[1];
bool did_kick = false;
if (argc > 2) {
for (int i = 2; i < argv.length(); i++) {
reason += " " + argv[i];
}
}
for (AOClient* client : server->clients) {
if (client->getIpid() == target_ipid) {
client->sendPacket("KK", {reason});
client->socket->close();
did_kick = true;
}
}
if (did_kick)
sendServerMessage("Banned user with ipid " + target_ipid + " for reason: " + reason);
else
sendServerMessage("User with ipid not found!");
}
QStringList AOClient::buildAreaList(int area_idx)
{
QStringList entries;
QString area_name = server->area_names[area_idx];
AreaData* area = server->areas[area_idx];
entries.append("=== " + area_name + " ===");
entries.append("[" + QString::number(area->player_count) + " users][" + area->status + "]");
for (AOClient* client : server->clients) {
if (client->current_area == area_idx) {
QString char_entry = client->current_char;
if (authenticated)
char_entry += " (" + client->getIpid() + "): " + ooc_name;
entries.append(char_entry);
}
}
return entries;
}