From be8d8b215e1f6d42868c5bd7e94b7cf3b9be8997 Mon Sep 17 00:00:00 2001 From: scatterflower Date: Tue, 25 Aug 2020 06:56:40 -0500 Subject: [PATCH] you can add characters now --- include/aoclient.h | 2 ++ include/area_data.h | 16 ++++++++++ include/config_manager.h | 1 + include/server.h | 4 +++ src/aoclient.cpp | 2 ++ src/aopacket.cpp | 16 ++-------- src/area_data.cpp | 9 ++++++ src/config_manager.cpp | 67 ++++++++++++++++++++++++++++++++++++++++ src/server.cpp | 66 ++++++++++++++++++++++++++++++++------- 9 files changed, 159 insertions(+), 24 deletions(-) create mode 100644 include/area_data.h create mode 100644 src/area_data.cpp diff --git a/include/aoclient.h b/include/aoclient.h index 9891bcd..e452887 100644 --- a/include/aoclient.h +++ b/include/aoclient.h @@ -18,6 +18,8 @@ public: QHostAddress remote_ip; QString password; bool joined; + int current_area; + QString current_char; private: QString hwid; diff --git a/include/area_data.h b/include/area_data.h new file mode 100644 index 0000000..527bbcc --- /dev/null +++ b/include/area_data.h @@ -0,0 +1,16 @@ +#ifndef AREA_DATA_H +#define AREA_DATA_H + +#include +#include + +class AreaData { +public: + AreaData(QStringList characters); + + QString name; + QMap characters_taken; + int player_count; +}; + +#endif // AREA_DATA_H diff --git a/include/config_manager.h b/include/config_manager.h index 3d9a9a2..6a9e32c 100644 --- a/include/config_manager.h +++ b/include/config_manager.h @@ -6,6 +6,7 @@ #include #include #include +#include #include class ConfigManager { diff --git a/include/server.h b/include/server.h index 63742e7..a68e097 100644 --- a/include/server.h +++ b/include/server.h @@ -3,6 +3,7 @@ #include "include/aoclient.h" #include "include/aopacket.h" +#include "include/area_data.h" #include #include @@ -11,6 +12,7 @@ #include #include #include +#include class Server : public QObject { Q_OBJECT @@ -41,6 +43,8 @@ private: bool is_partial; int player_count; + QStringList characters; + QVector areas; }; #endif // SERVER_H diff --git a/src/aoclient.cpp b/src/aoclient.cpp index d09930d..56061c5 100644 --- a/src/aoclient.cpp +++ b/src/aoclient.cpp @@ -4,6 +4,8 @@ AOClient::AOClient(QHostAddress p_remote_ip) { joined = false; password = ""; + current_area = 0; + current_char = ""; remote_ip = p_remote_ip; } diff --git a/src/aopacket.cpp b/src/aopacket.cpp index 643cbb5..ba5b60a 100644 --- a/src/aopacket.cpp +++ b/src/aopacket.cpp @@ -11,19 +11,9 @@ AOPacket::AOPacket(QString p_packet) QStringList packet_contents = p_packet.split("#"); if (p_packet.at(0) == '#') { // The header is encrypted with FantaCrypt - // The server always uses the same key for FantaCrypt - // That way, we can just hardcode FantaCrypted headers - // TODO: replace this with a key/value map? - packet_contents.removeFirst(); - if (packet_contents[0] == "48E0") - header = "HI"; - else if (packet_contents[0] == "493F") - header = "ID"; - else if (packet_contents[0] == "615810BC07D12A5A") - header = "askchaa"; - else - header = packet_contents[0]; // If no known decryption exists, just leave - // the packet as-is + // This should never happen with AO2 2.4.3 or newer + // TODO: implement fantacrypt? maybe? + qDebug() << "FantaCrypt packet received"; } else { header = packet_contents[0]; diff --git a/src/area_data.cpp b/src/area_data.cpp new file mode 100644 index 0000000..8457f9e --- /dev/null +++ b/src/area_data.cpp @@ -0,0 +1,9 @@ +#include "include/area_data.h" + +AreaData::AreaData(QStringList characters) +{ + for(QString cur_char : characters) + { + characters_taken.insert(cur_char, false); + } +} diff --git a/src/config_manager.cpp b/src/config_manager.cpp index 6252263..6e5d59f 100644 --- a/src/config_manager.cpp +++ b/src/config_manager.cpp @@ -8,6 +8,73 @@ ConfigManager::ConfigManager() // Validate and set up the config bool ConfigManager::initConfig() { + QFileInfo char_list_info("characters.txt"); + if(!(char_list_info.exists() && char_list_info.isFile())) + { + // TODO: signals go here + QFile char_list("characters.txt"); + if (!char_list.open(QIODevice::WriteOnly | QIODevice::Text)) + qDebug() << "Couldn't create character list"; + QTextStream file_stream(&char_list); + + qDebug() << "Creating vanilla character list"; + + file_stream << "Adrian\n"; + file_stream << "Apollo\n"; + file_stream << "April\n"; + file_stream << "Armstrong\n"; + file_stream << "Atmey\n"; + file_stream << "Butz\n"; + file_stream << "Diego\n"; + file_stream << "Edgeworth\n"; + file_stream << "Edgeworthw\n"; + file_stream << "Ema\n"; + file_stream << "EmaSkye\n"; + file_stream << "Franny\n"; + file_stream << "Franziska\n"; + file_stream << "Gant\n"; + file_stream << "Gavin\n"; + file_stream << "Gavin K\n"; + file_stream << "Godot\n"; + file_stream << "Gregory\n"; + file_stream << "Grossberg\n"; + file_stream << "Gumshoe\n"; + file_stream << "Gumshoey\n"; + file_stream << "Hawk\n"; + file_stream << "Hobo_Phoenix\n"; + file_stream << "Ini\n"; + file_stream << "Judge\n"; + file_stream << "Judge's Bro\n"; + file_stream << "Klav\n"; + file_stream << "Klavier\n"; + file_stream << "Kristoph\n"; + file_stream << "Lana\n"; + file_stream << "Layton\n"; + file_stream << "Lotta\n"; + file_stream << "Luis\n"; + file_stream << "Maggey\n"; + file_stream << "Manfred\n"; + file_stream << "Marshall\n"; + file_stream << "Matt\n"; + file_stream << "Maya\n"; + file_stream << "Mia\n"; + file_stream << "Miles\n"; + file_stream << "Oldbag\n"; + file_stream << "Payne\n"; + file_stream << "Pearl\n"; + file_stream << "Phoenix\n"; + file_stream << "Valant\n"; + file_stream << "Vasquez\n"; + file_stream << "Wellington\n"; + file_stream << "Winston\n"; + file_stream << "WinstonPayne\n"; + file_stream << "Young Mia\n"; + file_stream << "Zak\n"; + + char_list.flush(); + char_list.close(); + } + config->beginGroup("Info"); QString config_version = config->value("version", "none").toString(); config->endGroup(); diff --git a/src/server.cpp b/src/server.cpp index 9998243..789e589 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -33,6 +33,17 @@ void Server::start() // TODO: signal server start success qDebug() << "Server listening on" << port; } + + QFile char_list("characters.txt"); + char_list.open(QIODevice::ReadOnly | QIODevice::Text); + while(!char_list.atEnd()) + { + characters.append(char_list.readLine().trimmed()); + } + + // TODO: actually read areas from config + areas.append(new AreaData(characters)); + areas[0]->name = "basement lol"; } void Server::clientConnected() @@ -43,7 +54,8 @@ void Server::clientConnected() connect(client, SIGNAL(disconnected()), this, SLOT(clientDisconnected())); connect(client, SIGNAL(readyRead()), this, SLOT(clientData())); - AOPacket decryptor("decryptor", {"34"}); + AOPacket decryptor("decryptor", {"NOENCRYPT"}); // This is the infamous workaround for tsuserver4 + // It should disable fantacrypt completely in any client 2.4.3 or newer client->write(decryptor.toUtf8()); qDebug() << client->peerAddress().toString() << "connected"; @@ -53,10 +65,12 @@ void Server::clientDisconnected() { if (QTcpSocket *client = dynamic_cast(sender())) { qDebug() << client->peerAddress() << "disconnected"; - if (clients.value(client)->joined) + AOClient* ao_client = clients.value(client); + if (ao_client->joined) player_count--; + areas.value(ao_client->current_area)->characters_taken[ao_client->current_char] = false; - delete clients.value(client); + delete ao_client; clients.remove(client); } } @@ -86,8 +100,10 @@ void Server::clientData() void Server::handlePacket(AOPacket packet, QTcpSocket *socket) { + // TODO: like everything here should send a signal qDebug() << "Received packet:" << packet.header << ":" << packet.contents; AOClient *client = clients.value(socket); + AreaData *area = areas.value(client->current_area); // Lord forgive me if (packet.header == "HI") { AOClient *client = clients.value(socket); @@ -121,11 +137,12 @@ void Server::handlePacket(AOPacket packet, QTcpSocket *socket) else if (packet.header == "askchaa") { // TODO: add user configurable content // For testing purposes, we will just send enough to get things working - AOPacket response("SI", {"2", "0", "1"}); + AOPacket response("SI", {QString::number(characters.length()), "0", "1"}); + qDebug() << response.toString(); socket->write(response.toUtf8()); } else if (packet.header == "RC") { - AOPacket response("SC", {"Phoenix", "Edgeworth"}); + AOPacket response("SC", characters); socket->write(response.toUtf8()); } else if (packet.header == "RM") { @@ -136,7 +153,13 @@ void Server::handlePacket(AOPacket packet, QTcpSocket *socket) player_count++; client->joined = true; - AOPacket response_cc("CharsCheck", {"0", "0"}); + QStringList chars_taken; + for(QString cur_char : area->characters_taken.keys()) + { + chars_taken.append(area->characters_taken.value(cur_char) ? QStringLiteral("-1") : QStringLiteral("0")); + } + + AOPacket response_cc("CharsCheck", chars_taken); AOPacket response_op("OPPASS", {"DEADBEEF"}); AOPacket response_done("DONE", {}); socket->write(response_cc.toUtf8()); @@ -147,12 +170,33 @@ void Server::handlePacket(AOPacket packet, QTcpSocket *socket) client->password = packet.contents[0]; } else if (packet.header == "CC") { - // TODO: properly implement this when adding characters - qDebug() << client->getIpid() << "chose character" << packet.contents[1] - << "using password" << client->password; + bool argument_ok; + int char_id = packet.contents[1].toInt(&argument_ok); + if(!argument_ok) + return; - AOPacket response("PV", {"271828", "CID", packet.contents[1]}); - socket->write(response.toUtf8()); + QString char_selected = characters[char_id]; + bool taken = area->characters_taken.value(char_selected); + if(taken || char_selected == "") + return; + + if(client->current_char != "") { + area->characters_taken[client->current_char] = false; + } + + area->characters_taken[char_selected] = true; + client->current_char = char_selected; + + QStringList chars_taken; + for(QString cur_char : area->characters_taken.keys()) + { + chars_taken.append(area->characters_taken.value(cur_char) ? QStringLiteral("-1") : QStringLiteral("0")); + } + + AOPacket response_cc("CharsCheck", chars_taken); + AOPacket response_pv("PV", {"271828", "CID", packet.contents[1]}); + socket->write(response_pv.toUtf8()); + socket->write(response_cc.toUtf8()); } else if (packet.header == "MS") { // TODO: validate, validate, validate