Added server/client feature set communication
This commit is contained in:
parent
baa61d0571
commit
044c2356ff
26 changed files with 225 additions and 22 deletions
|
@ -19,6 +19,7 @@
|
||||||
#include "get_pb_extension.h"
|
#include "get_pb_extension.h"
|
||||||
#include <google/protobuf/descriptor.h>
|
#include <google/protobuf/descriptor.h>
|
||||||
#include "client_metatypes.h"
|
#include "client_metatypes.h"
|
||||||
|
#include "featureset.h"
|
||||||
|
|
||||||
AbstractClient::AbstractClient(QObject *parent)
|
AbstractClient::AbstractClient(QObject *parent)
|
||||||
: QObject(parent), nextCmdId(0), status(StatusDisconnected)
|
: QObject(parent), nextCmdId(0), status(StatusDisconnected)
|
||||||
|
@ -45,6 +46,10 @@ AbstractClient::AbstractClient(QObject *parent)
|
||||||
qRegisterMetaType<ServerInfo_User>("ServerInfo_User");
|
qRegisterMetaType<ServerInfo_User>("ServerInfo_User");
|
||||||
qRegisterMetaType<QList<ServerInfo_User> >("QList<ServerInfo_User>");
|
qRegisterMetaType<QList<ServerInfo_User> >("QList<ServerInfo_User>");
|
||||||
qRegisterMetaType<Event_ReplayAdded>("Event_ReplayAdded");
|
qRegisterMetaType<Event_ReplayAdded>("Event_ReplayAdded");
|
||||||
|
qRegisterMetaType<QList<QString> >("missingFeatures");
|
||||||
|
|
||||||
|
FeatureSet features;
|
||||||
|
features.initalizeFeatureList(clientFeatures);
|
||||||
|
|
||||||
connect(this, SIGNAL(sigQueuePendingCommand(PendingCommand *)), this, SLOT(queuePendingCommand(PendingCommand *)));
|
connect(this, SIGNAL(sigQueuePendingCommand(PendingCommand *)), this, SLOT(queuePendingCommand(PendingCommand *)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ class Event_NotifyUser;
|
||||||
class Event_ConnectionClosed;
|
class Event_ConnectionClosed;
|
||||||
class Event_ServerShutdown;
|
class Event_ServerShutdown;
|
||||||
class Event_ReplayAdded;
|
class Event_ReplayAdded;
|
||||||
|
class FeatureSet;
|
||||||
|
|
||||||
enum ClientStatus {
|
enum ClientStatus {
|
||||||
StatusDisconnected,
|
StatusDisconnected,
|
||||||
|
@ -96,6 +97,8 @@ public:
|
||||||
static PendingCommand *prepareRoomCommand(const ::google::protobuf::Message &cmd, int roomId);
|
static PendingCommand *prepareRoomCommand(const ::google::protobuf::Message &cmd, int roomId);
|
||||||
static PendingCommand *prepareModeratorCommand(const ::google::protobuf::Message &cmd);
|
static PendingCommand *prepareModeratorCommand(const ::google::protobuf::Message &cmd);
|
||||||
static PendingCommand *prepareAdminCommand(const ::google::protobuf::Message &cmd);
|
static PendingCommand *prepareAdminCommand(const ::google::protobuf::Message &cmd);
|
||||||
|
|
||||||
|
QMap<QString, bool> clientFeatures;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,6 +24,6 @@ Q_DECLARE_METATYPE(Event_UserMessage)
|
||||||
Q_DECLARE_METATYPE(ServerInfo_User)
|
Q_DECLARE_METATYPE(ServerInfo_User)
|
||||||
Q_DECLARE_METATYPE(QList<ServerInfo_User>)
|
Q_DECLARE_METATYPE(QList<ServerInfo_User>)
|
||||||
Q_DECLARE_METATYPE(Event_ReplayAdded)
|
Q_DECLARE_METATYPE(Event_ReplayAdded)
|
||||||
|
Q_DECLARE_METATYPE(QList<QString>)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -45,6 +45,7 @@ GeneralSettingsPage::GeneralSettingsPage()
|
||||||
|
|
||||||
picDownloadCheckBox.setChecked(settingsCache->getPicDownload());
|
picDownloadCheckBox.setChecked(settingsCache->getPicDownload());
|
||||||
picDownloadHqCheckBox.setChecked(settingsCache->getPicDownloadHq());
|
picDownloadHqCheckBox.setChecked(settingsCache->getPicDownloadHq());
|
||||||
|
updateNotificationCheckBox.setChecked(settingsCache->getNotifyAboutUpdates());
|
||||||
|
|
||||||
pixmapCacheEdit.setMinimum(PIXMAPCACHE_SIZE_MIN);
|
pixmapCacheEdit.setMinimum(PIXMAPCACHE_SIZE_MIN);
|
||||||
// 2047 is the max value to avoid overflowing of QPixmapCache::setCacheLimit(int size)
|
// 2047 is the max value to avoid overflowing of QPixmapCache::setCacheLimit(int size)
|
||||||
|
@ -64,19 +65,21 @@ GeneralSettingsPage::GeneralSettingsPage()
|
||||||
connect(&picDownloadHqCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPicDownloadHq(int)));
|
connect(&picDownloadHqCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPicDownloadHq(int)));
|
||||||
connect(&pixmapCacheEdit, SIGNAL(valueChanged(int)), settingsCache, SLOT(setPixmapCacheSize(int)));
|
connect(&pixmapCacheEdit, SIGNAL(valueChanged(int)), settingsCache, SLOT(setPixmapCacheSize(int)));
|
||||||
connect(&picDownloadHqCheckBox, SIGNAL(clicked(bool)), this, SLOT(setEnabledStatus(bool)));
|
connect(&picDownloadHqCheckBox, SIGNAL(clicked(bool)), this, SLOT(setEnabledStatus(bool)));
|
||||||
|
connect(&updateNotificationCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setNotifyAboutUpdate(int)));
|
||||||
connect(highQualityURLEdit, SIGNAL(textChanged(QString)), settingsCache, SLOT(setPicUrlHq(QString)));
|
connect(highQualityURLEdit, SIGNAL(textChanged(QString)), settingsCache, SLOT(setPicUrlHq(QString)));
|
||||||
|
|
||||||
QGridLayout *personalGrid = new QGridLayout;
|
QGridLayout *personalGrid = new QGridLayout;
|
||||||
personalGrid->addWidget(&languageLabel, 0, 0);
|
personalGrid->addWidget(&languageLabel, 0, 0);
|
||||||
personalGrid->addWidget(&languageBox, 0, 1);
|
personalGrid->addWidget(&languageBox, 0, 1);
|
||||||
personalGrid->addWidget(&pixmapCacheLabel, 1, 0, 1, 1);
|
personalGrid->addWidget(&pixmapCacheLabel, 1, 0);
|
||||||
personalGrid->addWidget(&pixmapCacheEdit, 1, 1, 1, 1);
|
personalGrid->addWidget(&pixmapCacheEdit, 1, 1);
|
||||||
personalGrid->addWidget(&picDownloadCheckBox, 2, 0, 1, 2);
|
personalGrid->addWidget(&updateNotificationCheckBox, 2, 0);
|
||||||
personalGrid->addWidget(&picDownloadHqCheckBox, 3, 0, 1, 2);
|
personalGrid->addWidget(&picDownloadCheckBox, 3, 0);
|
||||||
personalGrid->addWidget(&clearDownloadedPicsButton, 4, 0, 1, 1);
|
personalGrid->addWidget(&picDownloadHqCheckBox, 4, 0);
|
||||||
personalGrid->addWidget(&highQualityURLLabel, 5, 0, 1, 1);
|
personalGrid->addWidget(&highQualityURLLabel, 5, 0);
|
||||||
personalGrid->addWidget(highQualityURLEdit, 5, 1, 1, 1);
|
personalGrid->addWidget(highQualityURLEdit, 5, 1);
|
||||||
personalGrid->addWidget(&highQualityURLLinkLabel, 6, 1, 1, 1);
|
personalGrid->addWidget(&highQualityURLLinkLabel, 6, 1);
|
||||||
|
personalGrid->addWidget(&clearDownloadedPicsButton, 6, 0);
|
||||||
|
|
||||||
highQualityURLLinkLabel.setTextInteractionFlags(Qt::LinksAccessibleByMouse);
|
highQualityURLLinkLabel.setTextInteractionFlags(Qt::LinksAccessibleByMouse);
|
||||||
highQualityURLLinkLabel.setOpenExternalLinks(true);
|
highQualityURLLinkLabel.setOpenExternalLinks(true);
|
||||||
|
@ -246,6 +249,7 @@ void GeneralSettingsPage::retranslateUi()
|
||||||
highQualityURLLabel.setText(tr("Custom Card Download URL:"));
|
highQualityURLLabel.setText(tr("Custom Card Download URL:"));
|
||||||
highQualityURLLinkLabel.setText(QString("<a href='%1'>%2</a>").arg(LINKING_FAQ_URL).arg(tr("Linking FAQ")));
|
highQualityURLLinkLabel.setText(QString("<a href='%1'>%2</a>").arg(LINKING_FAQ_URL).arg(tr("Linking FAQ")));
|
||||||
clearDownloadedPicsButton.setText(tr("Reset/Clear Downloaded Pictures"));
|
clearDownloadedPicsButton.setText(tr("Reset/Clear Downloaded Pictures"));
|
||||||
|
updateNotificationCheckBox.setText(tr("Notify when new client features are available"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeneralSettingsPage::setEnabledStatus(bool status)
|
void GeneralSettingsPage::setEnabledStatus(bool status)
|
||||||
|
@ -914,3 +918,4 @@ void DlgSettings::retranslateUi()
|
||||||
for (int i = 0; i < pagesWidget->count(); i++)
|
for (int i = 0; i < pagesWidget->count(); i++)
|
||||||
dynamic_cast<AbstractSettingsPage *>(pagesWidget->widget(i))->retranslateUi();
|
dynamic_cast<AbstractSettingsPage *>(pagesWidget->widget(i))->retranslateUi();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,7 @@ private:
|
||||||
QComboBox languageBox;
|
QComboBox languageBox;
|
||||||
QCheckBox picDownloadCheckBox;
|
QCheckBox picDownloadCheckBox;
|
||||||
QCheckBox picDownloadHqCheckBox;
|
QCheckBox picDownloadHqCheckBox;
|
||||||
|
QCheckBox updateNotificationCheckBox;
|
||||||
QLabel languageLabel;
|
QLabel languageLabel;
|
||||||
QLabel pixmapCacheLabel;
|
QLabel pixmapCacheLabel;
|
||||||
QLabel deckPathLabel;
|
QLabel deckPathLabel;
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
#include <QSystemTrayIcon>
|
#include <QSystemTrayIcon>
|
||||||
#include "QtNetwork/QNetworkInterface"
|
#include "QtNetwork/QNetworkInterface"
|
||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "window_main.h"
|
#include "window_main.h"
|
||||||
#include "dlg_settings.h"
|
#include "dlg_settings.h"
|
||||||
|
@ -43,6 +42,7 @@
|
||||||
#include "pixmapgenerator.h"
|
#include "pixmapgenerator.h"
|
||||||
#include "rng_sfmt.h"
|
#include "rng_sfmt.h"
|
||||||
#include "soundengine.h"
|
#include "soundengine.h"
|
||||||
|
#include "featureset.h"
|
||||||
|
|
||||||
//Q_IMPORT_PLUGIN(qjpeg)
|
//Q_IMPORT_PLUGIN(qjpeg)
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <QList>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include "remoteclient.h"
|
#include "remoteclient.h"
|
||||||
|
@ -81,7 +82,6 @@ void RemoteClient::processServerIdentificationEvent(const Event_ServerIdentifica
|
||||||
cmdRegister.set_country(country.toStdString());
|
cmdRegister.set_country(country.toStdString());
|
||||||
cmdRegister.set_real_name(realName.toStdString());
|
cmdRegister.set_real_name(realName.toStdString());
|
||||||
cmdRegister.set_clientid(settingsCache->getClientID().toStdString());
|
cmdRegister.set_clientid(settingsCache->getClientID().toStdString());
|
||||||
|
|
||||||
PendingCommand *pend = prepareSessionCommand(cmdRegister);
|
PendingCommand *pend = prepareSessionCommand(cmdRegister);
|
||||||
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(registerResponse(Response)));
|
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(registerResponse(Response)));
|
||||||
sendCommand(pend);
|
sendCommand(pend);
|
||||||
|
@ -105,8 +105,7 @@ void RemoteClient::processServerIdentificationEvent(const Event_ServerIdentifica
|
||||||
doLogin();
|
doLogin();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteClient::doLogin()
|
void RemoteClient::doLogin() {
|
||||||
{
|
|
||||||
setStatus(StatusLoggingIn);
|
setStatus(StatusLoggingIn);
|
||||||
|
|
||||||
Command_Login cmdLogin;
|
Command_Login cmdLogin;
|
||||||
|
@ -114,6 +113,13 @@ void RemoteClient::doLogin()
|
||||||
cmdLogin.set_password(password.toStdString());
|
cmdLogin.set_password(password.toStdString());
|
||||||
cmdLogin.set_clientid(settingsCache->getClientID().toStdString());
|
cmdLogin.set_clientid(settingsCache->getClientID().toStdString());
|
||||||
cmdLogin.set_clientver(VERSION_STRING);
|
cmdLogin.set_clientver(VERSION_STRING);
|
||||||
|
|
||||||
|
if (!clientFeatures.isEmpty()) {
|
||||||
|
QMap<QString, bool>::iterator i;
|
||||||
|
for (i = clientFeatures.begin(); i != clientFeatures.end(); ++i)
|
||||||
|
cmdLogin.add_clientfeatures(i.key().toStdString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
PendingCommand *pend = prepareSessionCommand(cmdLogin);
|
PendingCommand *pend = prepareSessionCommand(cmdLogin);
|
||||||
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(loginResponse(Response)));
|
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(loginResponse(Response)));
|
||||||
sendCommand(pend);
|
sendCommand(pend);
|
||||||
|
@ -140,8 +146,17 @@ void RemoteClient::loginResponse(const Response &response)
|
||||||
for (int i = resp.ignore_list_size() - 1; i >= 0; --i)
|
for (int i = resp.ignore_list_size() - 1; i >= 0; --i)
|
||||||
ignoreList.append(resp.ignore_list(i));
|
ignoreList.append(resp.ignore_list(i));
|
||||||
emit ignoreListReceived(ignoreList);
|
emit ignoreListReceived(ignoreList);
|
||||||
|
|
||||||
|
if (resp.missing_features_size() > 0 && settingsCache->getNotifyAboutUpdates())
|
||||||
|
emit notifyUserAboutUpdate();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
emit loginError(response.response_code(), QString::fromStdString(resp.denied_reason_str()), resp.denied_end_time());
|
QList<QString> missingFeatures;
|
||||||
|
if (resp.missing_features_size() > 0) {
|
||||||
|
for (int i = 0; i < resp.missing_features_size(); ++i)
|
||||||
|
missingFeatures << QString::fromStdString(resp.missing_features(i));
|
||||||
|
}
|
||||||
|
emit loginError(response.response_code(), QString::fromStdString(resp.denied_reason_str()), resp.denied_end_time(), missingFeatures);
|
||||||
setStatus(StatusDisconnecting);
|
setStatus(StatusDisconnecting);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ class RemoteClient : public AbstractClient {
|
||||||
signals:
|
signals:
|
||||||
void maxPingTime(int seconds, int maxSeconds);
|
void maxPingTime(int seconds, int maxSeconds);
|
||||||
void serverTimeout();
|
void serverTimeout();
|
||||||
void loginError(Response::ResponseCode resp, QString reasonStr, quint32 endTime);
|
void loginError(Response::ResponseCode resp, QString reasonStr, quint32 endTime, QList<QString> missingFeatures);
|
||||||
void registerError(Response::ResponseCode resp, QString reasonStr, quint32 endTime);
|
void registerError(Response::ResponseCode resp, QString reasonStr, quint32 endTime);
|
||||||
void activateError();
|
void activateError();
|
||||||
void socketError(const QString &errorString);
|
void socketError(const QString &errorString);
|
||||||
|
@ -21,6 +21,7 @@ signals:
|
||||||
void sigRegisterToServer(const QString &hostname, unsigned int port, const QString &_userName, const QString &_password, const QString &_email, const int _gender, const QString &_country, const QString &_realname);
|
void sigRegisterToServer(const QString &hostname, unsigned int port, const QString &_userName, const QString &_password, const QString &_email, const int _gender, const QString &_country, const QString &_realname);
|
||||||
void sigActivateToServer(const QString &_token);
|
void sigActivateToServer(const QString &_token);
|
||||||
void sigDisconnectFromServer();
|
void sigDisconnectFromServer();
|
||||||
|
void notifyUserAboutUpdate();
|
||||||
private slots:
|
private slots:
|
||||||
void slotConnected();
|
void slotConnected();
|
||||||
void readData();
|
void readData();
|
||||||
|
|
|
@ -130,6 +130,7 @@ SettingsCache::SettingsCache()
|
||||||
if(!QFile(settingsPath+"global.ini").exists())
|
if(!QFile(settingsPath+"global.ini").exists())
|
||||||
translateLegacySettings();
|
translateLegacySettings();
|
||||||
|
|
||||||
|
notifyAboutUpdates = settings->value("personal/updatenotification", true).toBool();
|
||||||
lang = settings->value("personal/lang").toString();
|
lang = settings->value("personal/lang").toString();
|
||||||
keepalive = settings->value("personal/keepalive", 5).toInt();
|
keepalive = settings->value("personal/keepalive", 5).toInt();
|
||||||
deckPath = settings->value("paths/decks").toString();
|
deckPath = settings->value("paths/decks").toString();
|
||||||
|
@ -620,4 +621,10 @@ void SettingsCache::setRememberGameSettings(const bool _rememberGameSettings)
|
||||||
{
|
{
|
||||||
rememberGameSettings = _rememberGameSettings;
|
rememberGameSettings = _rememberGameSettings;
|
||||||
settings->setValue("game/remembergamesettings", rememberGameSettings);
|
settings->setValue("game/remembergamesettings", rememberGameSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsCache::setNotifyAboutUpdate(int _notifyaboutupdate)
|
||||||
|
{
|
||||||
|
notifyAboutUpdates = _notifyaboutupdate;
|
||||||
|
settings->setValue("personal/updatenotification", notifyAboutUpdates);
|
||||||
}
|
}
|
|
@ -58,6 +58,7 @@ private:
|
||||||
QByteArray mainWindowGeometry;
|
QByteArray mainWindowGeometry;
|
||||||
QString lang;
|
QString lang;
|
||||||
QString deckPath, replaysPath, picsPath, cardDatabasePath, tokenDatabasePath, themeName;
|
QString deckPath, replaysPath, picsPath, cardDatabasePath, tokenDatabasePath, themeName;
|
||||||
|
bool notifyAboutUpdates;
|
||||||
bool picDownload;
|
bool picDownload;
|
||||||
bool picDownloadHq;
|
bool picDownloadHq;
|
||||||
bool notificationsEnabled;
|
bool notificationsEnabled;
|
||||||
|
@ -129,6 +130,7 @@ public:
|
||||||
bool getPicDownloadHq() const { return picDownloadHq; }
|
bool getPicDownloadHq() const { return picDownloadHq; }
|
||||||
bool getNotificationsEnabled() const { return notificationsEnabled; }
|
bool getNotificationsEnabled() const { return notificationsEnabled; }
|
||||||
bool getSpectatorNotificationsEnabled() const { return spectatorNotificationsEnabled; }
|
bool getSpectatorNotificationsEnabled() const { return spectatorNotificationsEnabled; }
|
||||||
|
bool getNotifyAboutUpdates() const { return notifyAboutUpdates; }
|
||||||
|
|
||||||
bool getDoubleClickToPlay() const { return doubleClickToPlay; }
|
bool getDoubleClickToPlay() const { return doubleClickToPlay; }
|
||||||
bool getPlayToStack() const { return playToStack; }
|
bool getPlayToStack() const { return playToStack; }
|
||||||
|
@ -251,6 +253,7 @@ public slots:
|
||||||
void setSpectatorsCanTalk(const bool _spectatorsCanTalk);
|
void setSpectatorsCanTalk(const bool _spectatorsCanTalk);
|
||||||
void setSpectatorsCanSeeEverything(const bool _spectatorsCanSeeEverything);
|
void setSpectatorsCanSeeEverything(const bool _spectatorsCanSeeEverything);
|
||||||
void setRememberGameSettings(const bool _rememberGameSettings);
|
void setRememberGameSettings(const bool _rememberGameSettings);
|
||||||
|
void setNotifyAboutUpdate(int _notifyaboutupdate);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SettingsCache *settingsCache;
|
extern SettingsCache *settingsCache;
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QSystemTrayIcon>
|
#include <QSystemTrayIcon>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
#if QT_VERSION < 0x050000
|
#if QT_VERSION < 0x050000
|
||||||
#include <QtGui/qtextdocument.h> // for Qt::escape()
|
#include <QtGui/qtextdocument.h> // for Qt::escape()
|
||||||
#endif
|
#endif
|
||||||
|
@ -293,9 +294,23 @@ void MainWindow::serverTimeout()
|
||||||
actConnect();
|
actConnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::loginError(Response::ResponseCode r, QString reasonStr, quint32 endTime)
|
void MainWindow::loginError(Response::ResponseCode r, QString reasonStr, quint32 endTime, QList<QString> missingFeatures)
|
||||||
{
|
{
|
||||||
switch (r) {
|
switch (r) {
|
||||||
|
case Response::RespClientUpdateRequired: {
|
||||||
|
QString formatedMissingFeatures;
|
||||||
|
formatedMissingFeatures = "Missing Features: ";
|
||||||
|
for (int i = 0; i < missingFeatures.size(); ++i)
|
||||||
|
formatedMissingFeatures.append(QString("\n %1").arg(QChar(0x2022)) + " " + missingFeatures.value(i) );
|
||||||
|
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setIcon(QMessageBox::Critical);
|
||||||
|
msgBox.setWindowTitle(tr("Failed Login"));
|
||||||
|
msgBox.setText(tr("Your client does not support features that the server requires, please update your client and try again."));
|
||||||
|
msgBox.setDetailedText(formatedMissingFeatures);
|
||||||
|
msgBox.exec();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case Response::RespWrongPassword:
|
case Response::RespWrongPassword:
|
||||||
QMessageBox::critical(this, tr("Error"), tr("Incorrect username or password. Please check your authentication information and try again."));
|
QMessageBox::critical(this, tr("Error"), tr("Incorrect username or password. Please check your authentication information and try again."));
|
||||||
break;
|
break;
|
||||||
|
@ -561,13 +576,13 @@ MainWindow::MainWindow(QWidget *parent)
|
||||||
client = new RemoteClient;
|
client = new RemoteClient;
|
||||||
connect(client, SIGNAL(connectionClosedEventReceived(const Event_ConnectionClosed &)), this, SLOT(processConnectionClosedEvent(const Event_ConnectionClosed &)));
|
connect(client, SIGNAL(connectionClosedEventReceived(const Event_ConnectionClosed &)), this, SLOT(processConnectionClosedEvent(const Event_ConnectionClosed &)));
|
||||||
connect(client, SIGNAL(serverShutdownEventReceived(const Event_ServerShutdown &)), this, SLOT(processServerShutdownEvent(const Event_ServerShutdown &)));
|
connect(client, SIGNAL(serverShutdownEventReceived(const Event_ServerShutdown &)), this, SLOT(processServerShutdownEvent(const Event_ServerShutdown &)));
|
||||||
connect(client, SIGNAL(loginError(Response::ResponseCode, QString, quint32)), this, SLOT(loginError(Response::ResponseCode, QString, quint32)));
|
connect(client, SIGNAL(loginError(Response::ResponseCode, QString, quint32, QList<QString>)), this, SLOT(loginError(Response::ResponseCode, QString, quint32, QList<QString>)));
|
||||||
connect(client, SIGNAL(socketError(const QString &)), this, SLOT(socketError(const QString &)));
|
connect(client, SIGNAL(socketError(const QString &)), this, SLOT(socketError(const QString &)));
|
||||||
connect(client, SIGNAL(serverTimeout()), this, SLOT(serverTimeout()));
|
connect(client, SIGNAL(serverTimeout()), this, SLOT(serverTimeout()));
|
||||||
connect(client, SIGNAL(statusChanged(ClientStatus)), this, SLOT(statusChanged(ClientStatus)));
|
connect(client, SIGNAL(statusChanged(ClientStatus)), this, SLOT(statusChanged(ClientStatus)));
|
||||||
connect(client, SIGNAL(protocolVersionMismatch(int, int)), this, SLOT(protocolVersionMismatch(int, int)));
|
connect(client, SIGNAL(protocolVersionMismatch(int, int)), this, SLOT(protocolVersionMismatch(int, int)));
|
||||||
connect(client, SIGNAL(userInfoChanged(const ServerInfo_User &)), this, SLOT(userInfoReceived(const ServerInfo_User &)), Qt::BlockingQueuedConnection);
|
connect(client, SIGNAL(userInfoChanged(const ServerInfo_User &)), this, SLOT(userInfoReceived(const ServerInfo_User &)), Qt::BlockingQueuedConnection);
|
||||||
|
connect(client, SIGNAL(notifyUserAboutUpdate()), this, SLOT(notifyUserAboutUpdate()));
|
||||||
connect(client, SIGNAL(registerAccepted()), this, SLOT(registerAccepted()));
|
connect(client, SIGNAL(registerAccepted()), this, SLOT(registerAccepted()));
|
||||||
connect(client, SIGNAL(registerAcceptedNeedsActivate()), this, SLOT(registerAcceptedNeedsActivate()));
|
connect(client, SIGNAL(registerAcceptedNeedsActivate()), this, SLOT(registerAcceptedNeedsActivate()));
|
||||||
connect(client, SIGNAL(registerError(Response::ResponseCode, QString, quint32)), this, SLOT(registerError(Response::ResponseCode, QString, quint32)));
|
connect(client, SIGNAL(registerError(Response::ResponseCode, QString, quint32)), this, SLOT(registerError(Response::ResponseCode, QString, quint32)));
|
||||||
|
@ -795,3 +810,8 @@ void MainWindow::refreshShortcuts()
|
||||||
aExit->setShortcuts(settingsCache->shortcuts().getShortcut("MainWindow/aExit"));
|
aExit->setShortcuts(settingsCache->shortcuts().getShortcut("MainWindow/aExit"));
|
||||||
aCheckCardUpdates->setShortcuts(settingsCache->shortcuts().getShortcut("MainWindow/aCheckCardUpdates"));
|
aCheckCardUpdates->setShortcuts(settingsCache->shortcuts().getShortcut("MainWindow/aCheckCardUpdates"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::notifyUserAboutUpdate()
|
||||||
|
{
|
||||||
|
QMessageBox::information(this, tr("Information"), tr("Your client appears to be missing features that the server supports.\nThis usually means that your client version is out of date,pleae check to see if there is a new client available for download."));
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#ifndef WINDOW_H
|
#ifndef WINDOW_H
|
||||||
#define WINDOW_H
|
#define WINDOW_H
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QSystemTrayIcon>
|
#include <QSystemTrayIcon>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
@ -42,7 +43,7 @@ private slots:
|
||||||
void processConnectionClosedEvent(const Event_ConnectionClosed &event);
|
void processConnectionClosedEvent(const Event_ConnectionClosed &event);
|
||||||
void processServerShutdownEvent(const Event_ServerShutdown &event);
|
void processServerShutdownEvent(const Event_ServerShutdown &event);
|
||||||
void serverTimeout();
|
void serverTimeout();
|
||||||
void loginError(Response::ResponseCode r, QString reasonStr, quint32 endTime);
|
void loginError(Response::ResponseCode r, QString reasonStr, quint32 endTime, QList<QString> missingFeatures);
|
||||||
void registerError(Response::ResponseCode r, QString reasonStr, quint32 endTime);
|
void registerError(Response::ResponseCode r, QString reasonStr, quint32 endTime);
|
||||||
void activateError();
|
void activateError();
|
||||||
void socketError(const QString &errorStr);
|
void socketError(const QString &errorStr);
|
||||||
|
@ -53,7 +54,7 @@ private slots:
|
||||||
void activateAccepted();
|
void activateAccepted();
|
||||||
void localGameEnded();
|
void localGameEnded();
|
||||||
void pixmapCacheSizeChanged(int newSizeInMBs);
|
void pixmapCacheSizeChanged(int newSizeInMBs);
|
||||||
|
void notifyUserAboutUpdate();
|
||||||
void actConnect();
|
void actConnect();
|
||||||
void actDisconnect();
|
void actDisconnect();
|
||||||
void actSinglePlayer();
|
void actSinglePlayer();
|
||||||
|
|
|
@ -7,6 +7,7 @@ add_subdirectory(pb)
|
||||||
|
|
||||||
SET(common_SOURCES
|
SET(common_SOURCES
|
||||||
decklist.cpp
|
decklist.cpp
|
||||||
|
featureset.cpp
|
||||||
get_pb_extension.cpp
|
get_pb_extension.cpp
|
||||||
rng_abstract.cpp
|
rng_abstract.cpp
|
||||||
rng_sfmt.cpp
|
rng_sfmt.cpp
|
||||||
|
|
55
common/featureset.cpp
Normal file
55
common/featureset.cpp
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
#include "featureset.h"
|
||||||
|
#include <QMap>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
FeatureSet::FeatureSet()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QString, bool> FeatureSet::getDefaultFeatureList() {
|
||||||
|
initalizeFeatureList(featureList);
|
||||||
|
return featureList;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeatureSet::initalizeFeatureList(QMap<QString, bool> &featureList){
|
||||||
|
featureList.insert("client_id", false);
|
||||||
|
featureList.insert("client_ver", false);
|
||||||
|
featureList.insert("feature_set", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeatureSet::enableRequiredFeature(QMap<QString, bool> &featureList, QString featureName){
|
||||||
|
if (featureList.contains(featureName))
|
||||||
|
featureList.insert(featureName,true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeatureSet::disableRequiredFeature(QMap<QString, bool> &featureList, QString featureName){
|
||||||
|
if (featureList.contains(featureName))
|
||||||
|
featureList.insert(featureName,false);
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QString, bool> FeatureSet::addFeature(QMap<QString, bool> &featureList, QString featureName, bool isFeatureRequired){
|
||||||
|
featureList.insert(featureName,isFeatureRequired);
|
||||||
|
return featureList;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QString, bool> FeatureSet::identifyMissingFeatures(QMap<QString, bool> suppliedFeatures, QMap<QString, bool> requiredFeatures){
|
||||||
|
QMap<QString, bool> missingList;
|
||||||
|
QMap<QString, bool>::iterator i;
|
||||||
|
for (i = requiredFeatures.begin(); i != requiredFeatures.end(); ++i) {
|
||||||
|
if (!suppliedFeatures.contains(i.key())) {
|
||||||
|
missingList.insert(i.key(), i.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return missingList;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FeatureSet::isRequiredFeaturesMissing(QMap<QString, bool> suppliedFeatures, QMap<QString, bool> requiredFeatures) {
|
||||||
|
QMap<QString, bool>::iterator i;
|
||||||
|
for (i = requiredFeatures.begin(); i != requiredFeatures.end(); ++i) {
|
||||||
|
if (i.value() && suppliedFeatures.contains(i.key())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
24
common/featureset.h
Normal file
24
common/featureset.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef FEATURESET_H
|
||||||
|
#define FEATURESET_H
|
||||||
|
|
||||||
|
#include <QMap>
|
||||||
|
#include <QSet>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class FeatureSet
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FeatureSet();
|
||||||
|
QMap<QString, bool> getDefaultFeatureList();
|
||||||
|
void initalizeFeatureList(QMap<QString, bool> &featureList);
|
||||||
|
void enableRequiredFeature(QMap<QString, bool> &featureList, QString featureName);
|
||||||
|
void disableRequiredFeature(QMap<QString, bool> &featureList, QString featureName);
|
||||||
|
QMap<QString, bool> addFeature(QMap<QString, bool> &featureList, QString featureName, bool isFeatureRequired);
|
||||||
|
QMap<QString, bool> identifyMissingFeatures(QMap<QString, bool> featureListToCheck, QMap<QString, bool> featureListToCompareTo);
|
||||||
|
bool isRequiredFeaturesMissing(QMap<QString, bool> featureListToCheck, QMap<QString, bool> featureListToCompareTo);
|
||||||
|
private:
|
||||||
|
QMap<QString, bool> featureList;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // FEEATURESET_H
|
|
@ -37,6 +37,7 @@ message Response {
|
||||||
RespActivationFailed = 32; // Server didn't accept a reg user activation token
|
RespActivationFailed = 32; // Server didn't accept a reg user activation token
|
||||||
RespRegistrationAcceptedNeedsActivation = 33; // Server accepted cient registration, but it will need token activation
|
RespRegistrationAcceptedNeedsActivation = 33; // Server accepted cient registration, but it will need token activation
|
||||||
RespClientIdRequired = 34; // Server requires client to generate and send its client id before allowing access
|
RespClientIdRequired = 34; // Server requires client to generate and send its client id before allowing access
|
||||||
|
RespClientUpdateRequired = 35; // Client is missing features that the server is requiring
|
||||||
}
|
}
|
||||||
enum ResponseType {
|
enum ResponseType {
|
||||||
JOIN_ROOM = 1000;
|
JOIN_ROOM = 1000;
|
||||||
|
|
|
@ -11,4 +11,5 @@ message Response_Login {
|
||||||
repeated ServerInfo_User ignore_list = 3;
|
repeated ServerInfo_User ignore_list = 3;
|
||||||
optional string denied_reason_str = 4;
|
optional string denied_reason_str = 4;
|
||||||
optional uint64 denied_end_time = 5;
|
optional uint64 denied_end_time = 5;
|
||||||
|
repeated string missing_features = 6;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ message Command_Login {
|
||||||
optional string password = 2;
|
optional string password = 2;
|
||||||
optional string clientid = 3;
|
optional string clientid = 3;
|
||||||
optional string clientver = 4;
|
optional string clientver = 4;
|
||||||
|
repeated string clientfeatures = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Command_Message {
|
message Command_Message {
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "pb/session_event.pb.h"
|
#include "pb/session_event.pb.h"
|
||||||
#include "pb/event_connection_closed.pb.h"
|
#include "pb/event_connection_closed.pb.h"
|
||||||
#include "pb/isl_message.pb.h"
|
#include "pb/isl_message.pb.h"
|
||||||
|
#include "featureset.h"
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
|
@ -51,10 +51,10 @@ public:
|
||||||
Server_AbstractUserInterface *findUser(const QString &userName) const;
|
Server_AbstractUserInterface *findUser(const QString &userName) const;
|
||||||
const QMap<QString, Server_ProtocolHandler *> &getUsers() const { return users; }
|
const QMap<QString, Server_ProtocolHandler *> &getUsers() const { return users; }
|
||||||
const QMap<qint64, Server_ProtocolHandler *> &getUsersBySessionId() const { return usersBySessionId; }
|
const QMap<qint64, Server_ProtocolHandler *> &getUsersBySessionId() const { return usersBySessionId; }
|
||||||
|
virtual QMap<QString, bool> getServerRequiredFeatureList() const { return QMap<QString, bool>(); }
|
||||||
void addClient(Server_ProtocolHandler *player);
|
void addClient(Server_ProtocolHandler *player);
|
||||||
void removeClient(Server_ProtocolHandler *player);
|
void removeClient(Server_ProtocolHandler *player);
|
||||||
virtual QString getLoginMessage() const { return QString(); }
|
virtual QString getLoginMessage() const { return QString(); }
|
||||||
|
|
||||||
virtual bool permitUnregisteredUsers() const { return true; }
|
virtual bool permitUnregisteredUsers() const { return true; }
|
||||||
virtual bool getGameShouldPing() const { return false; }
|
virtual bool getGameShouldPing() const { return false; }
|
||||||
virtual bool getClientIdRequired() const { return false; }
|
virtual bool getClientIdRequired() const { return false; }
|
||||||
|
@ -94,6 +94,7 @@ private:
|
||||||
mutable QReadWriteLock persistentPlayersLock;
|
mutable QReadWriteLock persistentPlayersLock;
|
||||||
int nextLocalGameId;
|
int nextLocalGameId;
|
||||||
QMutex nextLocalGameIdMutex;
|
QMutex nextLocalGameIdMutex;
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void externalUserJoined(const ServerInfo_User &userInfo);
|
void externalUserJoined(const ServerInfo_User &userInfo);
|
||||||
void externalUserLeft(const QString &userName);
|
void externalUserLeft(const QString &userName);
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#include "pb/event_game_joined.pb.h"
|
#include "pb/event_game_joined.pb.h"
|
||||||
#include "pb/event_room_say.pb.h"
|
#include "pb/event_room_say.pb.h"
|
||||||
#include <google/protobuf/descriptor.h>
|
#include <google/protobuf/descriptor.h>
|
||||||
|
#include "featureset.h"
|
||||||
|
|
||||||
|
|
||||||
Server_ProtocolHandler::Server_ProtocolHandler(Server *_server, Server_DatabaseInterface *_databaseInterface, QObject *parent)
|
Server_ProtocolHandler::Server_ProtocolHandler(Server *_server, Server_DatabaseInterface *_databaseInterface, QObject *parent)
|
||||||
: QObject(parent),
|
: QObject(parent),
|
||||||
|
@ -382,10 +384,32 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd
|
||||||
{
|
{
|
||||||
QString userName = QString::fromStdString(cmd.user_name()).simplified();
|
QString userName = QString::fromStdString(cmd.user_name()).simplified();
|
||||||
QString clientId = QString::fromStdString(cmd.clientid()).simplified();
|
QString clientId = QString::fromStdString(cmd.clientid()).simplified();
|
||||||
|
|
||||||
if (userName.isEmpty() || (userInfo != 0))
|
if (userName.isEmpty() || (userInfo != 0))
|
||||||
return Response::RespContextError;
|
return Response::RespContextError;
|
||||||
|
|
||||||
|
// check client feature set against server feature set
|
||||||
|
FeatureSet features;
|
||||||
|
QMap<QString, bool> receivedClientFeatures;
|
||||||
|
QMap<QString, bool> missingClientFeatures;
|
||||||
|
|
||||||
|
for (int i = 0; i < cmd.clientfeatures().size(); ++i)
|
||||||
|
receivedClientFeatures.insert(QString::fromStdString(cmd.clientfeatures(i)).simplified(), false);
|
||||||
|
|
||||||
|
missingClientFeatures = features.identifyMissingFeatures(receivedClientFeatures, server->getServerRequiredFeatureList());
|
||||||
|
|
||||||
|
if (!missingClientFeatures.isEmpty()) {
|
||||||
|
if (features.isRequiredFeaturesMissing(missingClientFeatures, server->getServerRequiredFeatureList())) {
|
||||||
|
Response_Login *re = new Response_Login;
|
||||||
|
re->set_denied_reason_str("Client upgrade required");
|
||||||
|
QMap<QString, bool>::iterator i;
|
||||||
|
for (i = missingClientFeatures.begin(); i != missingClientFeatures.end(); ++i)
|
||||||
|
re->add_missing_features(i.key().toStdString().c_str());
|
||||||
|
rc.setResponseExtension(re);
|
||||||
|
return Response::RespClientUpdateRequired;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QString reasonStr;
|
QString reasonStr;
|
||||||
int banSecondsLeft = 0;
|
int banSecondsLeft = 0;
|
||||||
AuthenticationResult res = server->loginUser(this, userName, QString::fromStdString(cmd.password()), reasonStr, banSecondsLeft, clientId);
|
AuthenticationResult res = server->loginUser(this, userName, QString::fromStdString(cmd.password()), reasonStr, banSecondsLeft, clientId);
|
||||||
|
@ -430,6 +454,13 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd
|
||||||
re->add_ignore_list()->CopyFrom(ignoreIterator.next().value());
|
re->add_ignore_list()->CopyFrom(ignoreIterator.next().value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return to client any missing features the server has that the client does not
|
||||||
|
if (!missingClientFeatures.isEmpty()) {
|
||||||
|
QMap<QString, bool>::iterator i;
|
||||||
|
for (i = missingClientFeatures.begin(); i != missingClientFeatures.end(); ++i)
|
||||||
|
re->add_missing_features(i.key().toStdString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
joinPersistentGames(rc);
|
joinPersistentGames(rc);
|
||||||
|
|
||||||
rc.setResponseExtension(re);
|
rc.setResponseExtension(re);
|
||||||
|
|
|
@ -8,11 +8,13 @@
|
||||||
#include "pb/response.pb.h"
|
#include "pb/response.pb.h"
|
||||||
#include "pb/server_message.pb.h"
|
#include "pb/server_message.pb.h"
|
||||||
|
|
||||||
|
class Features;
|
||||||
class Server_DatabaseInterface;
|
class Server_DatabaseInterface;
|
||||||
class Server_Player;
|
class Server_Player;
|
||||||
class ServerInfo_User;
|
class ServerInfo_User;
|
||||||
class Server_Room;
|
class Server_Room;
|
||||||
class QTimer;
|
class QTimer;
|
||||||
|
class FeatureSet;
|
||||||
|
|
||||||
class ServerMessage;
|
class ServerMessage;
|
||||||
class Response;
|
class Response;
|
||||||
|
|
|
@ -50,6 +50,12 @@ max_player_inactivity_time=15
|
||||||
' require that clients report the client ID in order to log into the server. Default is false
|
' require that clients report the client ID in order to log into the server. Default is false
|
||||||
requireclientid=false
|
requireclientid=false
|
||||||
|
|
||||||
|
; You can limit the types of clients that connect to the server by requiring different features be available
|
||||||
|
; on the client. This setting can contain a comma-seperated list of features. if any of the features
|
||||||
|
; listed in this line are not available on the client the client will be denied access to the server upon
|
||||||
|
; attempting to log in. Example: "client_id,client_ver"
|
||||||
|
requiredfeatures=""
|
||||||
|
|
||||||
[authentication]
|
[authentication]
|
||||||
|
|
||||||
; Servatrice can authenticate users connecting. It currently supports 3 different authentication methods:
|
; Servatrice can authenticate users connecting. It currently supports 3 different authentication methods:
|
||||||
|
|
|
@ -198,6 +198,7 @@ int main(int argc, char *argv[])
|
||||||
#else
|
#else
|
||||||
qInstallMessageHandler(myMessageOutput);
|
qInstallMessageHandler(myMessageOutput);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
retval = app.exec();
|
retval = app.exec();
|
||||||
|
|
||||||
std::cerr << "Server quit." << std::endl;
|
std::cerr << "Server quit." << std::endl;
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "pb/event_server_message.pb.h"
|
#include "pb/event_server_message.pb.h"
|
||||||
#include "pb/event_server_shutdown.pb.h"
|
#include "pb/event_server_shutdown.pb.h"
|
||||||
#include "pb/event_connection_closed.pb.h"
|
#include "pb/event_connection_closed.pb.h"
|
||||||
|
#include "featureset.h"
|
||||||
|
|
||||||
Servatrice_GameServer::Servatrice_GameServer(Servatrice *_server, int _numberPools, const QSqlDatabase &_sqlDatabase, QObject *parent)
|
Servatrice_GameServer::Servatrice_GameServer(Servatrice *_server, int _numberPools, const QSqlDatabase &_sqlDatabase, QObject *parent)
|
||||||
: QTcpServer(parent),
|
: QTcpServer(parent),
|
||||||
|
@ -179,6 +180,16 @@ bool Servatrice::initServer()
|
||||||
if (registrationEnabled)
|
if (registrationEnabled)
|
||||||
qDebug() << "Require email address to register: " << requireEmailForRegistration;
|
qDebug() << "Require email address to register: " << requireEmailForRegistration;
|
||||||
|
|
||||||
|
FeatureSet features;
|
||||||
|
features.initalizeFeatureList(serverRequiredFeatureList);
|
||||||
|
requiredFeatures = settingsCache->value("server/requiredfeatures","").toString();
|
||||||
|
QStringList listReqFeatures = requiredFeatures.split(",", QString::SkipEmptyParts);
|
||||||
|
if (!listReqFeatures.isEmpty())
|
||||||
|
foreach(QString reqFeature, listReqFeatures)
|
||||||
|
features.enableRequiredFeature(serverRequiredFeatureList,reqFeature);
|
||||||
|
|
||||||
|
qDebug() << "Required client features: " << serverRequiredFeatureList;
|
||||||
|
|
||||||
QString dbTypeStr = settingsCache->value("database/type").toString();
|
QString dbTypeStr = settingsCache->value("database/type").toString();
|
||||||
if (dbTypeStr == "mysql")
|
if (dbTypeStr == "mysql")
|
||||||
databaseType = DatabaseMySql;
|
databaseType = DatabaseMySql;
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(QSqlDatabase)
|
Q_DECLARE_METATYPE(QSqlDatabase)
|
||||||
|
|
||||||
class QSqlQuery;
|
class QSqlQuery;
|
||||||
|
@ -41,6 +42,7 @@ class Servatrice_ConnectionPool;
|
||||||
class Servatrice_DatabaseInterface;
|
class Servatrice_DatabaseInterface;
|
||||||
class ServerSocketInterface;
|
class ServerSocketInterface;
|
||||||
class IslInterface;
|
class IslInterface;
|
||||||
|
class FeatureSet;
|
||||||
|
|
||||||
class Servatrice_GameServer : public QTcpServer {
|
class Servatrice_GameServer : public QTcpServer {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -109,6 +111,8 @@ private:
|
||||||
mutable QMutex loginMessageMutex;
|
mutable QMutex loginMessageMutex;
|
||||||
QString loginMessage;
|
QString loginMessage;
|
||||||
QString dbPrefix;
|
QString dbPrefix;
|
||||||
|
QString requiredFeatures;
|
||||||
|
QMap<QString, bool> serverRequiredFeatureList;
|
||||||
Servatrice_DatabaseInterface *servatriceDatabaseInterface;
|
Servatrice_DatabaseInterface *servatriceDatabaseInterface;
|
||||||
int serverId;
|
int serverId;
|
||||||
int uptime;
|
int uptime;
|
||||||
|
@ -134,8 +138,10 @@ public:
|
||||||
Servatrice(QObject *parent = 0);
|
Servatrice(QObject *parent = 0);
|
||||||
~Servatrice();
|
~Servatrice();
|
||||||
bool initServer();
|
bool initServer();
|
||||||
|
QMap<QString, bool> getServerRequiredFeatureList() const { return serverRequiredFeatureList; }
|
||||||
QString getServerName() const { return serverName; }
|
QString getServerName() const { return serverName; }
|
||||||
QString getLoginMessage() const { QMutexLocker locker(&loginMessageMutex); return loginMessage; }
|
QString getLoginMessage() const { QMutexLocker locker(&loginMessageMutex); return loginMessage; }
|
||||||
|
QString getRequiredFeatures() const { return requiredFeatures; }
|
||||||
bool permitUnregisteredUsers() const { return authenticationMethod != AuthenticationNone; }
|
bool permitUnregisteredUsers() const { return authenticationMethod != AuthenticationNone; }
|
||||||
bool getGameShouldPing() const { return true; }
|
bool getGameShouldPing() const { return true; }
|
||||||
bool getClientIdRequired() const { return clientIdRequired; }
|
bool getClientIdRequired() const { return clientIdRequired; }
|
||||||
|
|
Loading…
Reference in a new issue