RMG: implement netplay cheat support

This commit is contained in:
Rosalie Wanders committed 2025-01-29 23:00:43 +01:00
1 parent d468794979
commit 8e02a0ecda
10 files changed
+512 -34

No files matched your search

+1
View File
@@ -51,6 +51,7 @@ set(RMG_SOURCES
UserInterface/Widget/KeybindButton.cpp
UserInterface/Dialog/SettingsDialog.cpp
UserInterface/Dialog/SettingsDialog.ui
UserInterface/Dialog/Cheats/CheatsCommon.cpp
UserInterface/Dialog/Cheats/CheatsDialog.cpp
UserInterface/Dialog/Cheats/CheatsDialog.ui
UserInterface/Dialog/Cheats/AddCheatDialog.cpp
@@ -0,0 +1,294 @@
/*
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
* Copyright (C) 2020 Rosalie Wanders <rosalie@mailbox.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "CheatsCommon.hpp"
#include <QJsonObject>
#include <RMG-Core/Core.hpp>
using namespace CheatsCommon;
//
// Local Functions
//
static int find_json_cheat(const QJsonArray& json, const CoreCheat& cheat)
{
QJsonObject cheatObject;
QString targetCheatName = QString::fromStdString(cheat.Name);
for (qsizetype i = 0; i < json.size(); i++)
{
cheatObject = json[i].toObject();
if (cheatObject["name"].toString() == targetCheatName)
{
return (int)i;
}
}
return -1;
}
//
// Exported Function
//
bool CheatsCommon::IsCheatEnabled(bool netplay, const QJsonArray& json, const CoreCheat& cheat)
{
if (netplay)
{
int index = find_json_cheat(json, cheat);
return index != -1 && json[index].toObject().contains("codes");
}
else
{
return CoreIsCheatEnabled(cheat);
}
}
bool CheatsCommon::EnableCheat(bool netplay, QJsonArray& json, const CoreCheat& cheat, bool enabled)
{
if (netplay)
{
QJsonObject cheatObject;
QJsonArray codesArray;
QString targetCheatName = QString::fromStdString(cheat.Name);
if (enabled)
{
for (const auto& cheatCode : cheat.CheatCodes)
{
QJsonObject codeObject;
codeObject["address"] = (qint64)cheatCode.Address;
codeObject["value"] = (qint64)cheatCode.Value;
codeObject["use_option"] = cheatCode.UseOptions;
codeObject["option_index"] = cheatCode.OptionIndex;
codeObject["option_size"] = cheatCode.OptionSize;
codesArray.push_back(codeObject);
}
cheatObject["name"] = targetCheatName;
cheatObject["codes"] = codesArray;
cheatObject["has_options"] = cheat.HasOptions;
int index = find_json_cheat(json, cheat);
if (index != -1)
{
// copy over the option object
cheatObject["option"] = json[index].toObject().value("option").toObject();
json[index] = cheatObject;
}
else
{
json.push_back(cheatObject);
}
}
else
{
int index = find_json_cheat(json, cheat);
if (index != -1)
{
cheatObject = json[index].toObject();
// if cheat object has an option key
// we have to keep that key because
// else the UI will behave inconsistent
// with the non-netplay cheats dialog
if (cheatObject.contains("option"))
{
cheatObject.remove("codes");
json[index] = cheatObject;
}
else
{
json.removeAt(index);
}
}
}
return true;
}
else
{
return CoreEnableCheat(cheat, enabled);
}
}
bool CheatsCommon::HasCheatOptionSet(bool netplay, const QJsonArray& json, const CoreCheat& cheat)
{
if (netplay)
{
int index = find_json_cheat(json, cheat);
return index != -1 && json[index].toObject().contains("option");
}
else
{
return CoreHasCheatOptionSet(cheat);
}
}
bool CheatsCommon::GetCheatOption(bool netplay, const QJsonArray& json, const CoreCheat& cheat, CoreCheatOption& option)
{
if (netplay)
{
QJsonObject cheatObject;
QJsonObject optionObject;
int index = find_json_cheat(json, cheat);
if (index == -1)
{
return false;
}
cheatObject = json[index].toObject();
optionObject = cheatObject["option"].toObject();
option.Name = optionObject["name"].toString().toStdString();
option.Size = optionObject["size"].toInt();
option.Value = optionObject["value"].toInteger();
return true;
}
else
{
return CoreGetCheatOption(cheat, option);
}
}
bool CheatsCommon::SetCheatOption(bool netplay, QJsonArray& json, const CoreCheat& cheat, CoreCheatOption& option)
{
if (netplay)
{
QJsonObject cheatObject;
QJsonObject optionObject;
QString targetCheatName = QString::fromStdString(cheat.Name);
int index = find_json_cheat(json, cheat);
if (index != -1)
{
cheatObject = json[index].toObject();
optionObject["name"] = QString::fromStdString(option.Name);
optionObject["size"] = option.Size;
optionObject["value"] = (qint64)option.Value;
cheatObject["option"] = optionObject;
json[index] = cheatObject;
}
else
{ // create dummy object when option has been set
// without the user having the cheat enabled
optionObject["name"] = QString::fromStdString(option.Name);
optionObject["size"] = option.Size;
optionObject["value"] = (qint64)option.Value;
cheatObject["name"] = targetCheatName;
cheatObject["option"] = optionObject;
json.append(cheatObject);
}
return true;
}
else
{
return CoreGetCheatOption(cheat, option);
}
}
bool CheatsCommon::ParseCheatJson(const QJsonArray& json, std::vector<CoreCheat>& cheats)
{
QJsonObject cheatObject;
QJsonArray cheatCodesArray;
QJsonObject cheatCodeObject;
QJsonObject cheatOptionObject;
CoreCheat cheat;
CoreCheatCode cheatCode;
CoreCheatOption cheatOption;
bool skipCheat = false;
for (qsizetype i = 0; i < json.size(); i++)
{
cheatObject = json[i].toObject();
if (!cheatObject.contains("name") ||
!cheatObject.contains("codes") ||
!cheatObject.contains("has_options"))
{ // skip disabled cheats
continue;
}
// reset cheat
cheat = {};
skipCheat = false;
cheat.Name = cheatObject["name"].toString().toStdString();
cheat.HasOptions = cheatObject["has_options"].toBool();
if (cheat.Name.empty())
{ // name validation
continue;
}
// parse cheat codes
cheatCodesArray = cheatObject["codes"].toArray();
for (qsizetype x = 0; x < cheatCodesArray.size(); x++)
{
cheatCodeObject = cheatCodesArray[x].toObject();
// ensure json object contains required keys
if (!cheatCodeObject.contains("address") ||
!cheatCodeObject.contains("value") ||
!cheatCodeObject.contains("use_option") ||
!cheatCodeObject.contains("option_index") ||
!cheatCodeObject.contains("option_size"))
{
skipCheat = true;
break;
}
cheatCode.Address = (uint32_t)cheatCodeObject["address"].toInteger();
cheatCode.Value = cheatCodeObject["value"].toInt();
cheatCode.UseOptions = cheatCodeObject["use_option"].toBool();
cheatCode.OptionIndex = cheatCodeObject["option_index"].toInt();
cheatCode.OptionSize = cheatCodeObject["option_size"].toInt();
cheat.CheatCodes.push_back(cheatCode);
}
// parse (optional) cheat option
if (cheatObject.contains("option"))
{
cheatOptionObject = cheatObject["option"].toObject();
// ensure json object has required keys
if (!cheatOptionObject.contains("name") ||
!cheatOptionObject.contains("size") ||
!cheatOptionObject.contains("value"))
{
skipCheat = true;
}
else
{
cheatOption.Name = cheatOptionObject["name"].toString().toStdString();
cheatOption.Size = cheatOptionObject["size"].toInt();
cheatOption.Value = (uint32_t)cheatOptionObject["value"].toInteger();
cheat.CheatOptions.push_back(cheatOption);
}
}
if (skipCheat)
{
continue;
}
cheats.push_back(cheat);
}
return true;
}
@@ -0,0 +1,39 @@
/*
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
* Copyright (C) 2020 Rosalie Wanders <rosalie@mailbox.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef CHEATSCOMMONH_HPP
#define CHEATSCOMMONH_HPP
#include <QJsonArray>
#include <QString>
#include <RMG-Core/Core.hpp>
namespace CheatsCommon
{
// Checks whether cheat is enabled
bool IsCheatEnabled(bool netplay, const QJsonArray& json, const CoreCheat& cheat);
// Enables Cheat
bool EnableCheat(bool netplay, QJsonArray& json, const CoreCheat& cheat, bool enabled);
// Returns whether cheat has option set
bool HasCheatOptionSet(bool netplay, const QJsonArray& json, const CoreCheat& cheat);
// Retrieves cheat option
bool GetCheatOption(bool netplay, const QJsonArray& json, const CoreCheat& cheat, CoreCheatOption& option);
// Sets cheat option
bool SetCheatOption(bool netplay, QJsonArray& json, const CoreCheat& cheat, CoreCheatOption& option);
// Parses json into cheat list
bool ParseCheatJson(const QJsonArray& json, std::vector<CoreCheat>& cheats);
}
#endif // CHEATSCOMMONH_HPP
@@ -11,9 +11,10 @@
#include "AddCheatDialog.hpp"
#include "ChooseCheatOptionDialog.hpp"
#include "Utilities/QtMessageBox.hpp"
#include "CheatsCommon.hpp"
#include <QJsonObject>
#include <QFileInfo>
#include <RMG-Core/Core.hpp>
@@ -23,10 +24,13 @@ Q_DECLARE_METATYPE(CoreCheat);
using namespace UserInterface::Dialog;
using namespace Utilities;
CheatsDialog::CheatsDialog(QWidget *parent) : QDialog(parent)
CheatsDialog::CheatsDialog(QWidget *parent, bool netplay, QJsonArray cheatsJson) : QDialog(parent)
{
qRegisterMetaType<CoreCheat>();
this->netplay = netplay;
this->cheatsJson = cheatsJson;
this->setupUi(this);
this->loadCheats();
}
@@ -40,6 +44,11 @@ bool CheatsDialog::HasFailed(void)
return this->failedToParseCheats;
}
QJsonArray CheatsDialog::GetJson(void)
{
return this->cheatsJson;
}
void CheatsDialog::loadCheats(void)
{
std::vector<CoreCheat> cheats;
@@ -59,7 +68,7 @@ void CheatsDialog::loadCheats(void)
QString name = QString::fromStdString(cheat.Name);
QString section;
QStringList sections = name.split("\\");
bool enabled = CoreIsCheatEnabled(cheat);
bool enabled = CheatsCommon::IsCheatEnabled(this->netplay, this->cheatsJson, cheat);
for (int i = 0; i < sections.size(); i++)
{
@@ -173,7 +182,8 @@ QString CheatsDialog::getTreeWidgetItemTextFromCheat(CoreCheat cheat)
if (cheat.HasOptions)
{
CoreCheatOption cheatOption;
if (!CoreHasCheatOptionSet(cheat) || !CoreGetCheatOption(cheat, cheatOption))
if (!CheatsCommon::HasCheatOptionSet(this->netplay, this->cheatsJson, cheat) ||
!CheatsCommon::GetCheatOption(this->netplay, this->cheatsJson, cheat, cheatOption))
{
text = cheatName + " (=> ???? - Not Set)";
}
@@ -203,7 +213,7 @@ void CheatsDialog::on_cheatsTreeWidget_itemChanged(QTreeWidgetItem *item, int co
CoreCheat cheat = item->data(column, Qt::UserRole).value<CoreCheat>();
bool enabled = (item->checkState(column) == Qt::CheckState::Checked);
if (enabled && cheat.HasOptions && !CoreHasCheatOptionSet(cheat))
if (enabled && cheat.HasOptions && !CheatsCommon::HasCheatOptionSet(this->netplay, this->cheatsJson, cheat))
{
// ask user to select an option
this->on_cheatsTreeWidget_itemDoubleClicked(item, column);
@@ -211,14 +221,14 @@ void CheatsDialog::on_cheatsTreeWidget_itemChanged(QTreeWidgetItem *item, int co
// make sure the user selected an option,
// if they did then enable the cheat as requested,
// if not, reset the checkbox
if (!CoreHasCheatOptionSet(cheat))
if (!CheatsCommon::HasCheatOptionSet(this->netplay, this->cheatsJson, cheat))
{
item->setCheckState(0, Qt::CheckState::Unchecked);
return;
}
}
CoreEnableCheat(cheat, enabled);
CheatsCommon::EnableCheat(this->netplay, this->cheatsJson, cheat, enabled);
}
void CheatsDialog::on_cheatsTreeWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
@@ -251,9 +261,12 @@ void CheatsDialog::on_cheatsTreeWidget_itemDoubleClicked(QTreeWidgetItem *item,
return;
}
Dialog::ChooseCheatOptionDialog dialog(cheat, this);
Dialog::ChooseCheatOptionDialog dialog(cheat, this->netplay, this->cheatsJson, this);
dialog.exec();
// update json
this->cheatsJson = dialog.GetJson();
// re-load cheat options
item->setText(column, this->getTreeWidgetItemTextFromCheat(cheat));
}
@@ -312,6 +325,12 @@ void CheatsDialog::on_removeCheatButton_clicked(void)
void CheatsDialog::accept(void)
{
if (this->netplay)
{
QDialog::accept();
return;
}
CoreSettingsSave();
if (!CoreApplyCheats())
@@ -10,8 +10,9 @@
#ifndef CHEATSDIALOG_HPP
#define CHEATSDIALOG_HPP
#include <QWidget>
#include <QJsonArray>
#include <QDialog>
#include <QWidget>
#include <RMG-Core/Core.hpp>
@@ -26,14 +27,18 @@ class CheatsDialog : public QDialog, private Ui::CheatsDialog
Q_OBJECT
public:
CheatsDialog(QWidget *parent);
CheatsDialog(QWidget *parent, bool netplay = false, QJsonArray cheatsJson = {});
~CheatsDialog(void);
bool HasFailed(void);
QJsonArray GetJson(void);
private:
bool needCloseRom = false;
bool failedToParseCheats = false;
bool netplay = false;
QJsonArray cheatsJson;
void loadCheats(void);
@@ -8,6 +8,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "ChooseCheatOptionDialog.hpp"
#include "CheatsCommon.hpp"
#include <QFileInfo>
@@ -17,17 +18,19 @@ Q_DECLARE_METATYPE(CoreCheatOption);
using namespace UserInterface::Dialog;
ChooseCheatOptionDialog::ChooseCheatOptionDialog(CoreCheat cheat, QWidget *parent) : QDialog(parent)
ChooseCheatOptionDialog::ChooseCheatOptionDialog(CoreCheat cheat, bool netplay, QJsonArray cheatsJson, QWidget *parent) : QDialog(parent)
{
qRegisterMetaType<CoreCheatOption>();
this->setupUi(this);
this->cheat = cheat;
this->netplay = netplay;
this->cheatsJson = cheatsJson;
CoreCheatOption setCheatOption;
bool checkCheatOption = CoreHasCheatOptionSet(cheat) &&
CoreGetCheatOption(cheat, setCheatOption);
bool checkCheatOption = CheatsCommon::HasCheatOptionSet(this->netplay, this->cheatsJson, cheat) &&
CheatsCommon::GetCheatOption(this->netplay, this->cheatsJson, cheat, setCheatOption);
for (CoreCheatOption& option : cheat.CheatOptions)
{
@@ -49,7 +52,11 @@ ChooseCheatOptionDialog::ChooseCheatOptionDialog(CoreCheat cheat, QWidget *paren
ChooseCheatOptionDialog::~ChooseCheatOptionDialog()
{
}
QJsonArray ChooseCheatOptionDialog::GetJson(void)
{
return this->cheatsJson;
}
void ChooseCheatOptionDialog::on_cheatOptionsTreeWidget_itemChanged(QTreeWidgetItem *item, int column)
@@ -70,17 +77,8 @@ void ChooseCheatOptionDialog::on_cheatOptionsTreeWidget_itemChanged(QTreeWidgetI
}
}
void ChooseCheatOptionDialog::on_buttonBox_clicked(QAbstractButton *button)
void ChooseCheatOptionDialog::accept(void)
{
QPushButton *pushButton = (QPushButton *)button;
QPushButton *okButton = this->buttonBox->button(QDialogButtonBox::Ok);
// do nothing when the user didn't press ok
if (pushButton != okButton)
{
return;
}
for (int i = 0; i < this->cheatOptionsTreeWidget->topLevelItemCount(); i++)
{
QTreeWidgetItem* item = this->cheatOptionsTreeWidget->topLevelItem(i);
@@ -88,8 +86,9 @@ void ChooseCheatOptionDialog::on_buttonBox_clicked(QAbstractButton *button)
if (item->checkState(0) == Qt::CheckState::Checked)
{
CoreCheatOption cheatOption = item->data(0, Qt::UserRole).value<CoreCheatOption>();
CoreSetCheatOption(this->cheat, cheatOption);
return;
CheatsCommon::SetCheatOption(this->netplay, this->cheatsJson, this->cheat, cheatOption);
}
}
QDialog::accept();
}
@@ -10,8 +10,9 @@
#ifndef CHOOSECHEATOPTIONDIALOG_HPP
#define CHOOSECHEATOPTIONDIALOG_HPP
#include <QWidget>
#include <QJsonArray>
#include <QDialog>
#include <QWidget>
#include <RMG-Core/Core.hpp>
@@ -27,14 +28,18 @@ class ChooseCheatOptionDialog : public QDialog, private Ui::ChooseCheatOptionDia
private:
CoreCheat cheat;
bool netplay;
QJsonArray cheatsJson;
public:
ChooseCheatOptionDialog(CoreCheat cheat, QWidget *parent);
ChooseCheatOptionDialog(CoreCheat cheat, bool netplay, QJsonArray cheatsJson, QWidget *parent);
~ChooseCheatOptionDialog(void);
QJsonArray GetJson(void);
private slots:
void on_cheatOptionsTreeWidget_itemChanged(QTreeWidgetItem *item, int column);
void on_buttonBox_clicked(QAbstractButton *button);
void accept(void) Q_DECL_OVERRIDE;
};
} // namespace Dialog
} // namespace UserInterface
@@ -7,9 +7,11 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "UserInterface/Dialog/Cheats/CheatsCommon.hpp"
#include "UserInterface/Dialog/Cheats/CheatsDialog.hpp"
#include "Utilities/QtMessageBox.hpp"
#include "NetplaySessionDialog.hpp"
#include "NetplayCommon.hpp"
#include "Utilities/QtMessageBox.hpp"
#include <QJsonDocument>
#include <QPushButton>
@@ -31,6 +33,7 @@ NetplaySessionDialog::NetplaySessionDialog(QWidget *parent, QWebSocket* webSocke
QJsonObject session = json.value("room").toObject();
this->sessionJson = json.value("room").toObject();
this->nickName = json.value("player_name").toString();
this->sessionPort = session.value("port").toInt();
this->sessionName = session.value("room_name").toString();
@@ -62,6 +65,10 @@ NetplaySessionDialog::NetplaySessionDialog(QWidget *parent, QWebSocket* webSocke
QPushButton* startButton = this->buttonBox->button(QDialogButtonBox::Ok);
startButton->setText("Start");
startButton->setEnabled(false);
QPushButton* cheatsButton = this->buttonBox->button(QDialogButtonBox::RestoreDefaults);
cheatsButton->setText("Cheats");
cheatsButton->setIcon(QIcon());
}
NetplaySessionDialog::~NetplaySessionDialog(void)
@@ -72,6 +79,35 @@ NetplaySessionDialog::~NetplaySessionDialog(void)
}
}
bool NetplaySessionDialog::applyCheats(void)
{
QJsonObject session = this->sessionJson;
QJsonObject features = session.value("features").toObject();
QString cheatJson = features["cheats"].toString();
if (!cheatJson.isEmpty())
{
QJsonDocument cheatDocument = QJsonDocument::fromJson(cheatJson.toUtf8());
QJsonArray cheatArray = cheatDocument.array();
std::vector<CoreCheat> cheats;
if (!CheatsCommon::ParseCheatJson(cheatArray, cheats))
{
QString error = "Failed to parse cheats json: " + QString(cheatDocument.toJson());
QtMessageBox::Error(this, "CheatsCommon::ParseCheatJson() Failed", error);
return false;
}
if (!CoreSetNetplayCheats(cheats))
{
QtMessageBox::Error(this, "CoreSetNetplayCheats() Failed", QString::fromStdString(CoreGetError()));
return false;
}
}
return true;
}
void NetplaySessionDialog::on_webSocket_textMessageReceived(QString message)
{
QJsonDocument jsonDocument = QJsonDocument::fromJson(message.toUtf8());
@@ -91,14 +127,17 @@ void NetplaySessionDialog::on_webSocket_textMessageReceived(QString message)
this->listWidget->addItem(name);
if (!name.isEmpty())
{
if (this->nickName == name)
bool nameMatch = this->nickName == name;
if (nameMatch)
{
this->sessionNumber = i + 1;
}
if (!this->started && i == 0)
{
QPushButton* startButton = this->buttonBox->button(QDialogButtonBox::Ok);
startButton->setEnabled(this->nickName == name);
QPushButton* cheatsButton = this->buttonBox->button(QDialogButtonBox::RestoreDefaults);
startButton->setEnabled(nameMatch);
cheatsButton->setEnabled(nameMatch);
}
}
}
@@ -113,10 +152,17 @@ void NetplaySessionDialog::on_webSocket_textMessageReceived(QString message)
if (json.value("accept").toInt() == 0)
{
this->started = true;
this->applyCheats();
emit OnPlayGame(this->sessionFile, this->webSocket->peerAddress().toString(), this->sessionPort, this->sessionNumber);
}
else
{
// allow user to try again
QPushButton* startButton = this->buttonBox->button(QDialogButtonBox::Ok);
QPushButton* cheatsButton = this->buttonBox->button(QDialogButtonBox::RestoreDefaults);
startButton->setEnabled(true);
cheatsButton->setEnabled(true);
QtMessageBox::Error(this, "Server Error", json.value("message").toString());
}
}
@@ -126,6 +172,17 @@ void NetplaySessionDialog::on_webSocket_textMessageReceived(QString message)
this->chatPlainTextEdit->appendHtml(message);
this->chatPlainTextEdit->setTextInteractionFlags(Qt::TextBrowserInteraction);
}
else if (type == "reply_edit_room")
{
if (json.value("accept").toInt() == 0)
{
this->sessionJson = json.value("room").toObject();
}
else
{
QtMessageBox::Error(this, "Server Error", json.value("message").toString());
}
}
}
void NetplaySessionDialog::on_chatLineEdit_textChanged(QString text)
@@ -149,10 +206,65 @@ void NetplaySessionDialog::on_sendPushButton_clicked(void)
this->chatLineEdit->clear();
}
void NetplaySessionDialog::on_buttonBox_clicked(QAbstractButton* button)
{
QPushButton* pushButton = (QPushButton*)button;
QPushButton* cheatsButton = this->buttonBox->button(QDialogButtonBox::RestoreDefaults);
if (pushButton == cheatsButton)
{
QString cheatsJson = this->sessionJson.value("features").toObject().value("cheats").toString();
QJsonDocument cheatsDocument = QJsonDocument::fromJson(cheatsJson.toUtf8());
if (!CoreOpenRom(this->sessionFile.toStdString()))
{
QtMessageBox::Error(this, "CoreOpenRom() Failed", QString::fromStdString(CoreGetError()));
return;
}
Dialog::CheatsDialog dialog(this, true, cheatsDocument.array());
dialog.exec();
if (!CoreCloseRom())
{
QtMessageBox::Error(this, "CoreCloseRom() Failed", QString::fromStdString(CoreGetError()));
return;
}
// request an update to the existing session with the new cheats
cheatsDocument.setArray(dialog.GetJson());
QJsonObject session = this->sessionJson;
QJsonObject features = session.value("features").toObject();
if (!cheatsDocument.array().empty())
{ // only add cheats object when it's not empty
features["cheats"] = QString(cheatsDocument.toJson(QJsonDocument::Compact));
}
else
{ // else remove it
features.remove("cheats");
}
session.insert("features", features);
// only request update when needed
if (this->sessionJson != session)
{
QJsonObject json;
json.insert("type", "request_edit_room");
json.insert("player_name", this->nickName);
json.insert("room", session);
NetplayCommon::AddCommonJson(json);
this->webSocket->sendTextMessage(QJsonDocument(json).toJson());
}
}
}
void NetplaySessionDialog::accept()
{
QPushButton* startButton = this->buttonBox->button(QDialogButtonBox::Ok);
QPushButton* cheatsButton = this->buttonBox->button(QDialogButtonBox::RestoreDefaults);
startButton->setEnabled(false);
cheatsButton->setEnabled(false);
QJsonObject json;
QJsonObject session;
@@ -33,18 +33,22 @@ class NetplaySessionDialog : public QDialog, private Ui::NetplaySessionDialog
QString sessionFile;
QString nickName;
QString sessionName;
QJsonObject sessionJson;
int sessionPort = -1;
int sessionNumber = -1;
bool started = false;
QWebSocket* webSocket;
bool applyCheats(void);
private slots:
void on_webSocket_textMessageReceived(QString message);
void on_chatLineEdit_textChanged(QString text);
void on_sendPushButton_clicked(void);
void on_buttonBox_clicked(QAbstractButton* button);
void accept(void) Q_DECL_OVERRIDE;
void reject(void) Q_DECL_OVERRIDE;
@@ -117,7 +117,7 @@
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok|QDialogButtonBox::StandardButton::RestoreDefaults</set>
</property>
<property name="centerButtons">
<bool>false</bool>