aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--aoapplication.cpp23
-rw-r--r--aoapplication.h2
-rw-r--r--aotextarea.cpp82
-rw-r--r--aotextarea.h6
-rw-r--r--lobby.cpp8
-rw-r--r--lobby.h1
-rw-r--r--networkmanager.cpp65
-rw-r--r--networkmanager.h22
9 files changed, 132 insertions, 79 deletions
diff --git a/.gitignore b/.gitignore
index 12b1c863..9a949cb9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,5 @@
*.so
base_override.h
+base-full/
+bass.lib
diff --git a/aoapplication.cpp b/aoapplication.cpp
index 8ee33b0f..43629022 100644
--- a/aoapplication.cpp
+++ b/aoapplication.cpp
@@ -12,7 +12,8 @@
AOApplication::AOApplication(int &argc, char **argv) : QApplication(argc, argv)
{
net_manager = new NetworkManager(this);
- QObject::connect(net_manager, SIGNAL(ms_connect_finished(bool)), SLOT(ms_connect_finished(bool)));
+ QObject::connect(net_manager, SIGNAL(ms_connect_finished(bool, bool)),
+ SLOT(ms_connect_finished(bool, bool)));
}
AOApplication::~AOApplication()
@@ -136,7 +137,7 @@ void AOApplication::loading_cancelled()
w_lobby->hide_loading_overlay();
}
-void AOApplication::ms_connect_finished(bool connected)
+void AOApplication::ms_connect_finished(bool connected, bool will_retry)
{
if (connected)
{
@@ -145,10 +146,18 @@ void AOApplication::ms_connect_finished(bool connected)
}
else
{
- call_error("There was an error connecting to the master server.\n"
- "We deploy multiple master servers to mitigate any possible downtime,"
- "but the client appears to have exhausted all possible methods of finding"
- "and connecting to one.\n"
- "Please check your Internet connection and firewall, and please try again.");
+ if (will_retry)
+ {
+ w_lobby->append_error("Error connecting to master server. Will try again in "
+ + QString::number(net_manager->ms_reconnect_delay_ms / 1000.f) + " seconds.");
+ }
+ else
+ {
+ call_error("There was an error connecting to the master server.\n"
+ "We deploy multiple master servers to mitigate any possible downtime, "
+ "but the client appears to have exhausted all possible methods of finding "
+ "and connecting to one.\n"
+ "Please check your Internet connection and firewall, and please try again.");
+ }
}
}
diff --git a/aoapplication.h b/aoapplication.h
index 28d176df..d9737f6a 100644
--- a/aoapplication.h
+++ b/aoapplication.h
@@ -147,7 +147,7 @@ private:
QVector<server_type> favorite_list;
private slots:
- void ms_connect_finished(bool connected);
+ void ms_connect_finished(bool connected, bool will_retry);
public slots:
void server_disconnected();
diff --git a/aotextarea.cpp b/aotextarea.cpp
index d28ae4f4..7c9e160e 100644
--- a/aotextarea.cpp
+++ b/aotextarea.cpp
@@ -7,7 +7,7 @@
AOTextArea::AOTextArea(QWidget *p_parent) : QTextBrowser(p_parent)
{
-
+ this->setStyleSheet(".error {color: #0f0}");
}
void AOTextArea::append_chatmessage(QString p_name, QString p_message)
@@ -21,81 +21,37 @@ void AOTextArea::append_chatmessage(QString p_name, QString p_message)
this->append("");
this->insertHtml("<b>" + p_name.toHtmlEscaped() + "</b>:&nbsp;");
- //QRegExp regExp("((([A-Za-z]{3,9}:(?:\\/\\/)?)(?:[\\-;:&=\\+\\$,\\w]+@)?[A-Za-z0-9\\.\\-]+|(?:www\\.|[\\-;:&=\\+\\$,\\w]+@)[A-Za-z0-9\\.\\-]+)((?:\\/[\\+~%\\/\\.\\w\\-]*)?\\??(?:[\\-\\+=&;%@\\.\\w]*)#?(?:[\\.\\!\\/\\\\\\w]*))?)");
-
- QRegExp omnis_dank_url_regex("\\b(https?://\\S+\\.\\S+)\\b");
-
//cheap workarounds ahoy
p_message += " ";
QString result = p_message.toHtmlEscaped().replace("\n", "<br>").replace(omnis_dank_url_regex, "<a href='\\1'>\\1</a>" );
this->insertHtml(result);
+ this->auto_scroll(old_cursor, old_scrollbar_value, is_scrolled_down);
+}
- /*
- QRegExp rx("\\bhttp://\\S+");
-
- int first_index = rx.indexIn(p_message);
-
- qDebug() << "number of rx indices: " << rx.captureCount();
-
- if (first_index < 0)
- {
- this->insertPlainText(p_message);
- qDebug() << "NO REGEX MATCHES";
- return;
- }
-
- //indices where we found a regex match
- QVector<int> rx_indices;
- QStringList links = rx.capturedTexts();
-
- qDebug() << "link size" << links.size();
-
- rx_indices.append(first_index);
-
-
- //start at one because first_index is already appended
- for (int n_pos = 1 ; n_pos < rx.captureCount() ; ++n_pos)
- rx_indices.append(rx.indexIn(p_message));
-
- for (int msg_pos = 0 ; msg_pos < p_message.size() ; ++msg_pos)
- {
- int tag_index = rx_indices.indexOf(msg_pos);
- if (tag_index < 0)
- {
- this->insertPlainText(p_message.at(msg_pos));
- continue;
- }
-
- QString link = links.at(tag_index);
- QString html_string = "<a href=\"" + link + "\">" + link + "</a>";
- qDebug() << "html: " << html_string;
-
- this->insertHtml(html_string);
-
- msg_pos += link.size() - 1;
+void AOTextArea::append_error(QString p_message)
+{
+ const QTextCursor old_cursor = this->textCursor();
+ const int old_scrollbar_value = this->verticalScrollBar()->value();
+ const bool is_scrolled_down = old_scrollbar_value == this->verticalScrollBar()->maximum();
- }
+ this->moveCursor(QTextCursor::End);
- */
+ this->append("");
+ this->insertHtml("<div class='error'>");
- /*
+ p_message += " ";
+ QString result = p_message.replace("\n", "<br>").replace(omnis_dank_url_regex, "<a href='\\1'>\\1</a>" );
- QStringList word_list = p_message.split(" ");
+ this->insertHtml(result);
+ this->insertHtml("</div>");
- for (QString i_word : word_list)
- {
- if (i_word.startsWith("http"))
- {
- i_word.replace("\n", "").replace("\r", "");
- this->insertHtml("<a href=\"" + i_word + "\">" + i_word + "</a> ");
- }
- else
- this->insertPlainText(i_word + " ");
- }
- */
+ this->auto_scroll(old_cursor, old_scrollbar_value, is_scrolled_down);
+}
+void AOTextArea::auto_scroll(QTextCursor old_cursor, int old_scrollbar_value, bool is_scrolled_down)
+{
if (old_cursor.hasSelection() || !is_scrolled_down)
{
// The user has selected text or scrolled away from the bottom: maintain position.
diff --git a/aotextarea.h b/aotextarea.h
index 420bced1..32635fdb 100644
--- a/aotextarea.h
+++ b/aotextarea.h
@@ -9,6 +9,12 @@ public:
AOTextArea(QWidget *p_parent = nullptr);
void append_chatmessage(QString p_name, QString p_message);
+ void append_error(QString p_message);
+
+private:
+ const QRegExp omnis_dank_url_regex = QRegExp("\\b(https?://\\S+\\.\\S+)\\b");
+
+ void auto_scroll(QTextCursor old_cursor, int scrollbar_value, bool is_scrolled_down);
};
#endif // AOTEXTAREA_H
diff --git a/lobby.cpp b/lobby.cpp
index 2a7589f4..91827e83 100644
--- a/lobby.cpp
+++ b/lobby.cpp
@@ -262,8 +262,9 @@ void Lobby::on_about_clicked()
call_notice("Attorney Online 2 is built using Qt 5.7\n\n"
"Lead development:\n"
"OmniTroid\n\n"
- "Supporting development:\n"
"stonedDiscord\n"
+ "longbyte1\n"
+ "Supporting development:\n"
"Fiercy\n\n"
"UI design:\n"
"Ruekasu\n"
@@ -357,6 +358,11 @@ void Lobby::append_chatmessage(QString f_name, QString f_message)
ui_chatbox->append_chatmessage(f_name, f_message);
}
+void Lobby::append_error(QString f_message)
+{
+ ui_chatbox->append_error(f_message);
+}
+
void Lobby::set_player_count(int players_online, int max_players)
{
QString f_string = "Online: " + QString::number(players_online) + "/" + QString::number(max_players);
diff --git a/lobby.h b/lobby.h
index b2bfbef0..2d3aee5f 100644
--- a/lobby.h
+++ b/lobby.h
@@ -27,6 +27,7 @@ public:
void list_servers();
void list_favorites();
void append_chatmessage(QString f_name, QString f_message);
+ void append_error(QString f_message);
void set_player_count(int players_online, int max_players);
void set_loading_text(QString p_text);
void show_loading_overlay(){ui_loading_background->show();}
diff --git a/networkmanager.cpp b/networkmanager.cpp
index 3c59a82e..5f2aac22 100644
--- a/networkmanager.cpp
+++ b/networkmanager.cpp
@@ -12,6 +12,10 @@ NetworkManager::NetworkManager(AOApplication *parent) : QObject(parent)
ms_socket = new QTcpSocket(this);
server_socket = new QTcpSocket(this);
+ ms_reconnect_timer = new QTimer(this);
+ ms_reconnect_timer->setSingleShot(true);
+ QObject::connect(ms_reconnect_timer, SIGNAL(timeout()), this, SLOT(retry_ms_connect()));
+
QObject::connect(ms_socket, SIGNAL(readyRead()), this, SLOT(handle_ms_packet()));
QObject::connect(server_socket, SIGNAL(readyRead()), this, SLOT(handle_server_packet()));
QObject::connect(server_socket, SIGNAL(disconnected()), ao_app, SLOT(server_disconnected()));
@@ -27,7 +31,16 @@ void NetworkManager::connect_to_master()
ms_socket->close();
ms_socket->abort();
+#ifdef MS_FAILOVER_SUPPORTED
perform_srv_lookup();
+#else
+ QObject::connect(ms_socket, SIGNAL(error(QAbstractSocket::SocketError)),
+ this, SLOT(on_ms_connect_error(QAbstractSocket::SocketError)));
+
+ QObject::connect(ms_socket, SIGNAL(connected()),
+ this, SLOT(on_ms_nosrv_connect_success()));
+ ms_socket->connectToHost(ms_nosrv_hostname, ms_port);
+#endif
}
void NetworkManager::connect_to_server(server_type p_server)
@@ -40,7 +53,14 @@ void NetworkManager::connect_to_server(server_type p_server)
void NetworkManager::ship_ms_packet(QString p_packet)
{
- ms_socket->write(p_packet.toUtf8());
+ if (!ms_socket->isOpen())
+ {
+ retry_ms_connect();
+ }
+ else
+ {
+ ms_socket->write(p_packet.toUtf8());
+ }
}
void NetworkManager::ship_server_packet(QString p_packet)
@@ -82,9 +102,10 @@ void NetworkManager::handle_ms_packet()
}
}
+#ifdef MS_FAILOVER_SUPPORTED
void NetworkManager::perform_srv_lookup()
{
- ms_dns = new QDnsLookup(QDnsLookup::SRV, ms_hostname, this);
+ ms_dns = new QDnsLookup(QDnsLookup::SRV, ms_srv_hostname, this);
connect(ms_dns, SIGNAL(finished()), this, SLOT(on_srv_lookup()));
ms_dns->lookup();
@@ -127,7 +148,13 @@ void NetworkManager::on_srv_lookup()
break;
}
} while (timer.elapsed() < timeout_milliseconds); // Very expensive spin-wait loop - it will bring CPU to 100%!
- if (connected) break;
+ if (connected)
+ {
+ // Connect a one-shot signal in case the master server disconnects randomly
+ QObject::connect(ms_socket, SIGNAL(error(QAbstractSocket::SocketError)),
+ this, SLOT(on_ms_socket_error(QAbstractSocket::SocketError)));
+ break;
+ }
else
{
ms_socket->abort();
@@ -135,7 +162,37 @@ void NetworkManager::on_srv_lookup()
}
}
}
- emit ms_connect_finished(connected);
+ emit ms_connect_finished(connected, false);
+}
+#endif
+
+void NetworkManager::on_ms_nosrv_connect_success()
+{
+ emit ms_connect_finished(true, false);
+
+ QObject::connect(ms_socket, SIGNAL(error(QAbstractSocket::SocketError)),
+ this, SLOT(on_ms_socket_error(QAbstractSocket::SocketError)));
+}
+
+void NetworkManager::on_ms_socket_error(QAbstractSocket::SocketError error)
+{
+ qWarning() << "Master server socket error:" << ms_socket->errorString()
+ << "(" << error << ")";
+
+ // Disconnect the one-shot signal - this way, failover connect attempts
+ // don't trigger a full retry
+ QObject::disconnect(ms_socket, SIGNAL(error(QAbstractSocket::SocketError)),
+ this, SLOT(on_ms_socket_error(QAbstractSocket::SocketError)));
+
+ emit ms_connect_finished(false, true);
+
+ ms_reconnect_timer->start(ms_reconnect_delay_ms);
+}
+
+void NetworkManager::retry_ms_connect()
+{
+ if (!ms_reconnect_timer->isActive() && ms_socket->state() != QAbstractSocket::ConnectingState)
+ connect_to_master();
}
void NetworkManager::handle_server_packet()
diff --git a/networkmanager.h b/networkmanager.h
index 4bfebc67..00a7a960 100644
--- a/networkmanager.h
+++ b/networkmanager.h
@@ -1,12 +1,20 @@
#ifndef NETWORKMANAGER_H
#define NETWORKMANAGER_H
+// Qt for Android has stubbed QDnsLookup. This is not documented in any part of their wiki.
+// This prevents SRV lookup/failover behavior from functioning.
+// https://bugreports.qt.io/browse/QTBUG-56143
+#ifndef ANDROID
+#define MS_FAILOVER_SUPPORTED
+#endif
+
#include "aopacket.h"
#include "aoapplication.h"
#include <QTcpSocket>
#include <QDnsLookup>
#include <QTime>
+#include <QTimer>
class NetworkManager : public QObject
{
@@ -20,11 +28,16 @@ public:
QTcpSocket *ms_socket;
QTcpSocket *server_socket;
QDnsLookup *ms_dns;
+ QTimer *ms_reconnect_timer;
+
+ const QString ms_srv_hostname = "_aoms._tcp.aceattorneyonline.com";
+ const QString ms_nosrv_hostname = "master.aceattorneyonline.com";
- QString ms_hostname = "_aoms._tcp.aceattorneyonline.com";
- int ms_port = 27016;
+ const int ms_port = 27016;
const int timeout_milliseconds = 2000;
+ const int ms_reconnect_delay_ms = 5000;
+
bool ms_partial_packet = false;
QString ms_temp_packet = "";
@@ -41,7 +54,7 @@ public slots:
void ship_server_packet(QString p_packet);
signals:
- void ms_connect_finished(bool success);
+ void ms_connect_finished(bool success, bool will_retry);
private:
void perform_srv_lookup();
@@ -50,6 +63,9 @@ private slots:
void on_srv_lookup();
void handle_ms_packet();
void handle_server_packet();
+ void on_ms_nosrv_connect_success();
+ void on_ms_socket_error(QAbstractSocket::SocketError error);
+ void retry_ms_connect();
};
#endif // NETWORKMANAGER_H