1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-03 13:01:33 +02:00

Implemented support of protocol 4

This commit is contained in:
nordsoft 2022-12-26 02:37:35 +04:00 committed by Nordsoft91
parent b3f6250f4e
commit 8e1d8f835a
5 changed files with 231 additions and 74 deletions

View File

@ -208,6 +208,8 @@ int main(int argc, char * argv[])
("lobby-host", "if this client hosts session")
("lobby-uuid", po::value<std::string>(), "uuid to the server")
("lobby-connections", po::value<ui16>(), "connections of server")
("lobby-username", po::value<std::string>(), "player name")
("lobby-gamemode", po::value<bool>(), "use 0 for new game and 1 for load game")
("uuid", po::value<std::string>(), "uuid for the client");
if(argc > 1)
@ -489,29 +491,8 @@ int main(int argc, char * argv[])
session["autoSkip"].Bool() = vm.count("autoSkip");
session["oneGoodAI"].Bool() = vm.count("oneGoodAI");
session["aiSolo"].Bool() = false;
std::shared_ptr<CMainMenu> mmenu;
session["lobby"].Bool() = false;
if(vm.count("lobby"))
{
session["lobby"].Bool() = true;
session["host"].Bool() = false;
session["address"].String() = vm["lobby-address"].as<std::string>();
CSH->uuid = vm["uuid"].as<std::string>();
session["port"].Integer() = vm["lobby-port"].as<ui16>();
logGlobal->info("Remote lobby mode at %s:%d, uuid is %s", session["address"].String(), session["port"].Integer(), CSH->uuid);
if(vm.count("lobby-host"))
{
session["host"].Bool() = true;
session["hostConnections"].String() = std::to_string(vm["lobby-connections"].as<ui16>());
session["hostUuid"].String() = vm["lobby-uuid"].as<std::string>();
logGlobal->info("This client will host session, server uuid is %s", session["hostUuid"].String());
}
//we should not reconnect to previous game in online mode
Settings saveSession = settings.write["server"]["reconnect"];
saveSession->Bool() = false;
}
if(vm.count("testmap"))
{
session["testmap"].String() = vm["testmap"].as<std::string>();
@ -526,7 +507,44 @@ int main(int argc, char * argv[])
}
else
{
GH.curInt = CMainMenu::create().get();
mmenu = CMainMenu::create();
GH.curInt = mmenu.get();
}
std::vector<std::string> names;
session["lobby"].Bool() = false;
if(vm.count("lobby"))
{
session["lobby"].Bool() = true;
session["host"].Bool() = false;
session["address"].String() = vm["lobby-address"].as<std::string>();
if(vm.count("lobby-username"))
session["username"].String() = vm["lobby-username"].as<std::string>();
else
session["username"].String() = settings["launcher"]["lobbyUsername"].String();
if(vm.count("lobby-gamemode"))
session["gamemode"].Integer() = vm["lobby-gamemode"].as<ui16>();
else
session["gamemode"].Integer() = 0;
CSH->uuid = vm["uuid"].as<std::string>();
session["port"].Integer() = vm["lobby-port"].as<ui16>();
logGlobal->info("Remote lobby mode at %s:%d, uuid is %s", session["address"].String(), session["port"].Integer(), CSH->uuid);
if(vm.count("lobby-host"))
{
session["host"].Bool() = true;
session["hostConnections"].String() = std::to_string(vm["lobby-connections"].as<ui16>());
session["hostUuid"].String() = vm["lobby-uuid"].as<std::string>();
logGlobal->info("This client will host session, server uuid is %s", session["hostUuid"].String());
}
//we should not reconnect to previous game in online mode
Settings saveSession = settings.write["server"]["reconnect"];
saveSession->Bool() = false;
//start lobby immediately
names.push_back(session["username"].String());
ESelectionScreen sscreen = session["gamemode"].Integer() == 0 ? ESelectionScreen::newGame : ESelectionScreen::loadGame;
mmenu->openLobby(sscreen, session["host"].Bool(), &names, ELoadMode::MULTI);
}
// Restore remote session - start game immediately

View File

@ -12,7 +12,7 @@
#include <QTcpSocket>
#include <QAbstractSocket>
const unsigned int ProtocolVersion = 3;
const unsigned int ProtocolVersion = 4;
const std::string ProtocolEncoding = "utf8";
class ProtocolError: public std::runtime_error
@ -24,10 +24,10 @@ public:
enum ProtocolConsts
{
//client consts
GREETING, USERNAME, MESSAGE, VERSION, CREATE, JOIN, LEAVE, KICK, READY, FORCESTART,
GREETING, USERNAME, MESSAGE, VERSION, CREATE, JOIN, LEAVE, KICK, READY, FORCESTART, HERE, ALIVE, HOSTMODE,
//server consts
SESSIONS, CREATED, JOINED, KICKED, SRVERROR, CHAT, START, STATUS, HOST, MODS, CLIENTMODS
SESSIONS, CREATED, JOINED, KICKED, SRVERROR, CHAT, START, STATUS, HOST, MODS, CLIENTMODS, USERS, HEALTH, GAMEMODE
};
const QMap<ProtocolConsts, QString> ProtocolStrings
@ -78,6 +78,16 @@ const QMap<ProtocolConsts, QString> ProtocolStrings
//[unsupported] start session immediately
//%1: room name
{FORCESTART, "<FORCESTART>%1"},
//request user list
{HERE, "<HERE>"},
//used as reponse to healcheck
{ALIVE, "<ALIVE>"},
//host sets game mode (new game or load game)
//%1: game mode - 0 for new game, 1 for load game
{HOSTMODE, "<HOSTMODE>%1"},
//=== server commands ===
//server commands are started from :>>, arguments are enumerated by : symbol
@ -140,7 +150,20 @@ const QMap<ProtocolConsts, QString> ProtocolStrings
//received chat message
//arg[0]: sender username
//arg[1]: message text
{CHAT, "MSG"}
{CHAT, "MSG"},
//list of users currently in lobby
//arg[0]: amount of players, following arguments depend on it
//arg[x]: username
//arg[x+1]: room (empty if not in the room)
{USERS, "USERS"},
//healthcheck from server
{HEALTH, "HEALTH"},
//game mode (new game or load game) set by host
//arg[0]: game mode
{GAMEMODE, "GAMEMODE"}
};
class ServerCommand

View File

@ -135,9 +135,12 @@ void Lobby::serverCommand(const ServerCommand & command) try
if(args[1] == username)
{
ui->buttonReady->setText("Ready");
ui->chat->clear(); //cleanup the chat
ui->optNewGame->setChecked(true);
sysMessage(joinStr.arg("you", args[0]));
session = args[0];
bool isHost = command.command == JOINED && hostSession == session;
ui->optNewGame->setEnabled(isHost);
ui->optLoadGame->setEnabled(isHost);
ui->stackedWidget->setCurrentWidget(command.command == JOINED ? ui->roomPage : ui->sessionsPage);
}
else
@ -217,6 +220,8 @@ void Lobby::serverCommand(const ServerCommand & command) try
gameArgs << "--lobby";
gameArgs << "--lobby-address" << serverUrl;
gameArgs << "--lobby-port" << QString::number(serverPort);
gameArgs << "--lobby-username" << username;
gameArgs << "--lobby-gamemode" << QString::number(isLoadGameMode);
gameArgs << "--uuid" << args[0];
startGame(gameArgs);
break;
@ -238,6 +243,35 @@ void Lobby::serverCommand(const ServerCommand & command) try
chatMessage(args[0], msg);
break;
}
case HEALTH: {
protocolAssert(args.size() == 0);
socketLobby.send(ProtocolStrings[ALIVE]);
break;
}
case USERS: {
protocolAssert(args.size() > 0);
amount = args[0].toInt();
protocolAssert(amount == (args.size() - 1));
ui->listUsers->clear();
for(int i = 0; i < amount; ++i)
{
ui->listUsers->addItem(new QListWidgetItem(args[i + 1]));
}
break;
}
case GAMEMODE: {
protocolAssert(args.size() == 1);
isLoadGameMode = args[0].toInt();
if(isLoadGameMode == 1)
ui->optLoadGame->setChecked(true);
else
ui->optNewGame->setChecked(true);
break;
}
default:
sysMessage("Unknown server command");
@ -291,7 +325,7 @@ void Lobby::onDisconnected()
ui->userEdit->setEnabled(true);
ui->newButton->setEnabled(false);
ui->joinButton->setEnabled(false);
ui->sessionsTable->clear();
ui->sessionsTable->setRowCount(0);
}
void Lobby::chatMessage(QString title, QString body, bool isSystem)
@ -329,6 +363,7 @@ void Lobby::on_connectButton_toggled(bool checked)
{
if(checked)
{
ui->connectButton->setText("Disconnect");
authentificationStatus = AuthStatus::AUTH_NONE;
username = ui->userEdit->text();
const int connectionTimeout = settings["launcher"]["connectionTimeout"].Integer();
@ -360,8 +395,10 @@ void Lobby::on_connectButton_toggled(bool checked)
}
else
{
ui->connectButton->setText("Connection");
ui->serverEdit->setEnabled(true);
ui->userEdit->setEnabled(true);
ui->listUsers->clear();
socketLobby.disconnectServer();
}
}
@ -417,3 +454,27 @@ void Lobby::on_kickButton_clicked()
socketLobby.send(ProtocolStrings[KICK].arg(ui->playersList->currentItem()->text()));
}
void Lobby::on_buttonResolve_clicked()
{
//TODO: auto-resolve mods conflicts
}
void Lobby::on_optNewGame_toggled(bool checked)
{
if(checked)
{
if(isLoadGameMode)
socketLobby.send(ProtocolStrings[HOSTMODE].arg(0));
}
}
void Lobby::on_optLoadGame_toggled(bool checked)
{
if(checked)
{
if(!isLoadGameMode)
socketLobby.send(ProtocolStrings[HOSTMODE].arg(1));
}
}

View File

@ -49,9 +49,16 @@ private slots:
void on_kickButton_clicked();
void on_buttonResolve_clicked();
void on_optNewGame_toggled(bool checked);
void on_optLoadGame_toggled(bool checked);
private:
QString serverUrl;
int serverPort;
bool isLoadGameMode = false;
Ui::Lobby *ui;
SocketLobby socketLobby;

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>652</width>
<height>329</height>
<height>331</height>
</rect>
</property>
<property name="windowTitle">
@ -30,9 +30,6 @@
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QLineEdit" name="messageEdit"/>
</item>
<item row="0" column="3">
<widget class="QLabel" name="label_4">
<property name="sizePolicy">
@ -56,13 +53,6 @@
</property>
</widget>
</item>
<item row="2" column="0" colspan="3">
<widget class="QPlainTextEdit" name="chat">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
@ -147,34 +137,10 @@
</widget>
<widget class="QWidget" name="roomPage">
<layout class="QGridLayout" name="gridLayout_3">
<item row="5" column="1">
<widget class="QPushButton" name="buttonReady">
<item row="1" column="1">
<widget class="QPushButton" name="kickButton">
<property name="text">
<string>Ready</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Mods mismatch</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QPushButton" name="buttonLeave">
<property name="text">
<string>Leave</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QListWidget" name="modsList">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
<string>Kick player</string>
</property>
</widget>
</item>
@ -191,13 +157,6 @@
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="kickButton">
<property name="text">
<string>Kick player</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
@ -205,10 +164,99 @@
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QPushButton" name="buttonLeave">
<property name="text">
<string>Leave</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Mods mismatch</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QListWidget" name="modsList">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QPushButton" name="buttonReady">
<property name="text">
<string>Ready</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QPushButton" name="buttonResolve">
<property name="text">
<string>Resolve conflicts</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QRadioButton" name="optNewGame">
<property name="text">
<string>New game</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="optLoadGame">
<property name="text">
<string>Load game</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
<item row="1" column="0" rowspan="3" colspan="3">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QListWidget" name="listUsers">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>120</verstretch>
</sizepolicy>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="chat">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="messageEdit"/>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>