瀏覽代碼

Client-side support for hosting game server via lobby

Ivan Savenko 1 年之前
父節點
當前提交
ffa58152ac

+ 14 - 0
Mods/vcmi/config/vcmi/english.json

@@ -77,6 +77,20 @@
 	"vcmi.lobby.login.connecting" : "Connecting...",
 	"vcmi.lobby.login.error" : "Connection error: %s",
 
+	"vcmi.lobby.room.create" : "Create Room",
+	"vcmi.lobby.room.players.limit" : "Players Limit",
+	"vcmi.lobby.room.public" : "Public",
+	"vcmi.lobby.room.private" : "Private",
+	"vcmi.lobby.room.description.public" : "Any player can join public room.",
+	"vcmi.lobby.room.description.private" : "Only invited players can join private room.",
+	"vcmi.lobby.room.description.new" : "To start the game, select a scenario or set up a random map.",
+	"vcmi.lobby.room.description.load" : "To start the game, use one of your saved games.",
+	"vcmi.lobby.room.description.limit" : "Up to %d players can enter your room, including you.",
+	"vcmi.lobby.room.new" : "New Game",
+	"vcmi.lobby.room.load" : "Load Game",
+	"vcmi.lobby.room.type" : "Room Type",
+	"vcmi.lobby.room.mode" : "Game Mode",
+
 	"vcmi.client.errors.missingCampaigns" : "{Missing data files}\n\nCampaigns data files were not found! You may be using incomplete or corrupted Heroes 3 data files. Please reinstall game data.",
 	"vcmi.server.errors.existingProcess" : "Another VCMI server process is running. Please terminate it before starting a new game.",
 	"vcmi.server.errors.modsToEnable"    : "{Following mods are required}",

+ 0 - 42
client/CMT.cpp

@@ -139,14 +139,6 @@ int main(int argc, char * argv[])
 		("donotstartserver,d","do not attempt to start server and just connect to it instead server")
 		("serverport", po::value<si64>(), "override port specified in config file")
 		("savefrequency", po::value<si64>(), "limit auto save creation to each N days")
-		("lobby", "parameters address, port, uuid to connect ro remote lobby session")
-		("lobby-address", po::value<std::string>(), "address to remote lobby")
-		("lobby-port", po::value<ui16>(), "port to remote lobby")
-		("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<ui16>(), "use 0 for new game and 1 for load game")
 		("uuid", po::value<std::string>(), "uuid for the client");
 
 	if(argc > 1)
@@ -371,40 +363,6 @@ int main(int argc, char * argv[])
 	}
 	
 	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;
-		CMM->openLobby(sscreen, session["host"].Bool(), &names, ELoadMode::MULTI);
-	}
 
 	if(!settings["session"]["headless"].Bool())
 	{

+ 2 - 0
client/CMakeLists.txt

@@ -97,6 +97,7 @@ set(client_SRCS
 
 	globalLobby/GlobalLobbyClient.cpp
 	globalLobby/GlobalLobbyLoginWindow.cpp
+	globalLobby/GlobalLobbyServerSetup.cpp
 	globalLobby/GlobalLobbyWidget.cpp
 	globalLobby/GlobalLobbyWindow.cpp
 
@@ -277,6 +278,7 @@ set(client_HEADERS
 
 	globalLobby/GlobalLobbyClient.h
 	globalLobby/GlobalLobbyLoginWindow.h
+	globalLobby/GlobalLobbyServerSetup.h
 	globalLobby/GlobalLobbyWidget.h
 	globalLobby/GlobalLobbyWindow.h
 

+ 11 - 21
client/CServerHandler.cpp

@@ -182,7 +182,7 @@ GlobalLobbyClient & CServerHandler::getGlobalLobby()
 	return *lobbyClient;
 }
 
-void CServerHandler::startLocalServerAndConnect()
+void CServerHandler::startLocalServerAndConnect(bool connectToLobby)
 {
 	if(threadRunLocalServer)
 		threadRunLocalServer->join();
@@ -191,14 +191,10 @@ void CServerHandler::startLocalServerAndConnect()
 
 #if defined(SINGLE_PROCESS_APP)
 	boost::condition_variable cond;
-	std::vector<std::string> args{"--uuid=" + uuid, "--port=" + std::to_string(getLocalPort())};
-	if(settings["session"]["lobby"].Bool() && settings["session"]["host"].Bool())
-	{
-		args.push_back("--lobby=" + settings["session"]["address"].String());
-		args.push_back("--connections=" + settings["session"]["hostConnections"].String());
-		args.push_back("--lobby-port=" + std::to_string(settings["session"]["port"].Integer()));
-		args.push_back("--lobby-uuid=" + settings["session"]["hostUuid"].String());
-	}
+	std::vector<std::string> args{"--port=" + std::to_string(getLocalPort())};
+	if(connectToLobby)
+		args.push_back("--lobby");
+
 	threadRunLocalServer = std::make_unique<boost::thread>([&cond, args, this] {
 		setThreadName("CVCMIServer");
 		CVCMIServer::create(&cond, args);
@@ -211,7 +207,7 @@ void CServerHandler::startLocalServerAndConnect()
 		envHelper.callStaticVoidMethod(CAndroidVMHelper::NATIVE_METHODS_DEFAULT_CLASS, "startServer", true);
 	}
 #else
-	threadRunLocalServer = std::make_unique<boost::thread>(&CServerHandler::threadRunServer, this); //runs server executable;
+	threadRunLocalServer = std::make_unique<boost::thread>(&CServerHandler::threadRunServer, this, connectToLobby); //runs server executable;
 #endif
 	logNetwork->trace("Setting up thread calling server: %d ms", th->getDiff());
 
@@ -800,7 +796,7 @@ void CServerHandler::debugStartTest(std::string filename, bool save)
 	if(settings["session"]["donotstartserver"].Bool())
 		connectToServer(getLocalHostname(), getLocalPort());
 	else
-		startLocalServerAndConnect();
+		startLocalServerAndConnect(false);
 
 	boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
 
@@ -916,22 +912,16 @@ void CServerHandler::visitForClient(CPackForClient & clientPack)
 	client->handlePack(&clientPack);
 }
 
-void CServerHandler::threadRunServer()
+void CServerHandler::threadRunServer(bool connectToLobby)
 {
 #if !defined(VCMI_MOBILE)
 	setThreadName("runServer");
 	const std::string logName = (VCMIDirs::get().userLogsPath() / "server_log.txt").string();
 	std::string comm = VCMIDirs::get().serverPath().string()
 		+ " --port=" + std::to_string(getLocalPort())
-		+ " --run-by-client"
-		+ " --uuid=" + uuid;
-	if(settings["session"]["lobby"].Bool() && settings["session"]["host"].Bool())
-	{
-		comm += " --lobby=" + settings["session"]["address"].String();
-		comm += " --connections=" + settings["session"]["hostConnections"].String();
-		comm += " --lobby-port=" + std::to_string(settings["session"]["port"].Integer());
-		comm += " --lobby-uuid=" + settings["session"]["hostUuid"].String();
-	}
+		+ " --run-by-client";
+	if(connectToLobby)
+		comm += " --lobby";
 
 	comm += " > \"" + logName + '\"';
 	logGlobal->info("Server command line: %s", comm);

+ 2 - 2
client/CServerHandler.h

@@ -94,7 +94,7 @@ class CServerHandler : public IServerAPI, public LobbyInfo, public INetworkClien
 	std::shared_ptr<HighScoreCalculation> highScoreCalc;
 
 	void threadRunNetwork();
-	void threadRunServer();
+	void threadRunServer(bool connectToLobby);
 	void onServerFinished();
 	void sendLobbyPack(const CPackForLobby & pack) const override;
 
@@ -137,7 +137,7 @@ public:
 	~CServerHandler();
 	
 	void resetStateForLobby(const StartInfo::EMode mode, const std::vector<std::string> * names = nullptr);
-	void startLocalServerAndConnect();
+	void startLocalServerAndConnect(bool connectToLobby);
 	void connectToServer(const std::string & addr, const ui16 port);
 
 	GlobalLobbyClient & getGlobalLobby();

+ 9 - 0
client/NetPacksLobbyClient.cpp

@@ -19,6 +19,7 @@
 #include "lobby/ExtraOptionsTab.h"
 #include "lobby/SelectionTab.h"
 #include "lobby/CBonusSelection.h"
+#include "globalLobby/GlobalLobbyWindow.h"
 
 #include "CServerHandler.h"
 #include "CGameInfo.h"
@@ -40,12 +41,20 @@ void ApplyOnLobbyHandlerNetPackVisitor::visitLobbyClientConnected(LobbyClientCon
 	{
 		handler.c->connectionID = pack.clientId;
 		if(handler.mapToStart)
+		{
 			handler.setMapInfo(handler.mapToStart);
+		}
 		else if(!settings["session"]["headless"].Bool())
 		{
 			if (GH.windows().topWindow<CSimpleJoinScreen>())
 				GH.windows().popWindows(1);
 
+			while (!GH.windows().findWindows<GlobalLobbyWindow>().empty())
+			{
+				// if global lobby is open, pop all dialogs on top of it as well as lobby itself
+				GH.windows().popWindows(1);
+			}
+
 			GH.windows().createAndPushWindow<CLobbyScreen>(static_cast<ESelectionScreen>(handler.screenType));
 		}
 		handler.state = EClientState::LOBBY;

+ 2 - 1
client/globalLobby/GlobalLobbyLoginWindow.cpp

@@ -66,7 +66,8 @@ void GlobalLobbyLoginWindow::onLogin()
 	config->String() = inputUsername->getText();
 
 	labelStatus->setText(CGI->generaltexth->translate("vcmi.lobby.login.connecting"));
-	CSH->getGlobalLobby().connect();
+	if (!CSH->getGlobalLobby().isConnected())
+		CSH->getGlobalLobby().connect();
 	buttonClose->block(true);
 }
 

+ 144 - 0
client/globalLobby/GlobalLobbyServerSetup.cpp

@@ -0,0 +1,144 @@
+/*
+ * GlobalLobbyServerSetup.cpp, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+#include "StdInc.h"
+#include "GlobalLobbyServerSetup.h"
+
+#include "../gui/CGuiHandler.h"
+#include "../widgets/TextControls.h"
+#include "../widgets/Images.h"
+#include "../widgets/Buttons.h"
+#include "../CGameInfo.h"
+#include "../CServerHandler.h"
+#include "../mainmenu/CMainMenu.h"
+
+#include "../../lib/CGeneralTextHandler.h"
+#include "../../lib/MetaString.h"
+#include "../../lib/CConfigHandler.h"
+
+GlobalLobbyServerSetup::GlobalLobbyServerSetup()
+	: CWindowObject(BORDERED)
+{
+	OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
+
+	pos.w = 284;
+	pos.h = 340;
+
+	background = std::make_shared<FilledTexturePlayerColored>(ImagePath::builtin("DiBoxBck"), Rect(0, 0, pos.w, pos.h));
+	labelTitle = std::make_shared<CLabel>( pos.w / 2, 20, FONT_BIG, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->translate("vcmi.lobby.room.create"));
+	labelPlayerLimit = std::make_shared<CLabel>( pos.w / 2, 48, FONT_MEDIUM, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->translate("vcmi.lobby.room.players.limit"));
+	labelRoomType = std::make_shared<CLabel>( pos.w / 2, 108, FONT_MEDIUM, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->translate("vcmi.lobby.room.type"));
+	labelGameMode = std::make_shared<CLabel>( pos.w / 2, 158, FONT_MEDIUM, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->translate("vcmi.lobby.room.mode"));
+
+	togglePlayerLimit = std::make_shared<CToggleGroup>(nullptr);
+	togglePlayerLimit->addToggle(2, std::make_shared<CToggleButton>(Point(10 + 39*0, 60), AnimationPath::builtin("RanNum2"), CButton::tooltip(), 0));
+	togglePlayerLimit->addToggle(3, std::make_shared<CToggleButton>(Point(10 + 39*1, 60), AnimationPath::builtin("RanNum3"), CButton::tooltip(), 0));
+	togglePlayerLimit->addToggle(4, std::make_shared<CToggleButton>(Point(10 + 39*2, 60), AnimationPath::builtin("RanNum4"), CButton::tooltip(), 0));
+	togglePlayerLimit->addToggle(5, std::make_shared<CToggleButton>(Point(10 + 39*3, 60), AnimationPath::builtin("RanNum5"), CButton::tooltip(), 0));
+	togglePlayerLimit->addToggle(6, std::make_shared<CToggleButton>(Point(10 + 39*4, 60), AnimationPath::builtin("RanNum6"), CButton::tooltip(), 0));
+	togglePlayerLimit->addToggle(7, std::make_shared<CToggleButton>(Point(10 + 39*5, 60), AnimationPath::builtin("RanNum7"), CButton::tooltip(), 0));
+	togglePlayerLimit->addToggle(8, std::make_shared<CToggleButton>(Point(10 + 39*6, 60), AnimationPath::builtin("RanNum8"), CButton::tooltip(), 0));
+	togglePlayerLimit->setSelected(settings["lobby"]["roomPlayerLimit"].Integer());
+	togglePlayerLimit->addCallback([this](int index){onPlayerLimitChanged(index);});
+
+	auto buttonPublic  = std::make_shared<CToggleButton>(Point(10, 120),  AnimationPath::builtin("GSPBUT2"), CButton::tooltip(), 0);
+	auto buttonPrivate = std::make_shared<CToggleButton>(Point(146, 120), AnimationPath::builtin("GSPBUT2"), CButton::tooltip(), 0);
+	buttonPublic->addTextOverlay(CGI->generaltexth->translate("vcmi.lobby.room.public"), EFonts::FONT_SMALL, Colors::YELLOW);
+	buttonPrivate->addTextOverlay(CGI->generaltexth->translate("vcmi.lobby.room.private"), EFonts::FONT_SMALL, Colors::YELLOW);
+
+	toggleRoomType = std::make_shared<CToggleGroup>(nullptr);
+	toggleRoomType->addToggle(0, buttonPublic);
+	toggleRoomType->addToggle(1, buttonPrivate);
+	toggleRoomType->setSelected(settings["lobby"]["roomType"].Integer());
+	toggleRoomType->addCallback([this](int index){onRoomTypeChanged(index);});
+
+	auto buttonNewGame = std::make_shared<CToggleButton>(Point(10, 170),  AnimationPath::builtin("GSPBUT2"), CButton::tooltip(), 0);
+	auto buttonLoadGame = std::make_shared<CToggleButton>(Point(146, 170), AnimationPath::builtin("GSPBUT2"), CButton::tooltip(), 0);
+	buttonNewGame->addTextOverlay(CGI->generaltexth->translate("vcmi.lobby.room.new"), EFonts::FONT_SMALL, Colors::YELLOW);
+	buttonLoadGame->addTextOverlay(CGI->generaltexth->translate("vcmi.lobby.room.load"), EFonts::FONT_SMALL, Colors::YELLOW);
+
+	toggleGameMode = std::make_shared<CToggleGroup>(nullptr);
+	toggleGameMode->addToggle(0, buttonNewGame);
+	toggleGameMode->addToggle(1, buttonLoadGame);
+	toggleGameMode->setSelected(settings["lobby"]["roomMode"].Integer());
+	toggleGameMode->addCallback([this](int index){onGameModeChanged(index);});
+
+	labelDescription = std::make_shared<CTextBox>("", Rect(10, 195, pos.w - 20, 80), 1, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE);
+
+	buttonCreate = std::make_shared<CButton>(Point(10, 300), AnimationPath::builtin("MuBchck"), CButton::tooltip(), [this](){ onCreate(); });
+	buttonClose = std::make_shared<CButton>(Point(210, 300), AnimationPath::builtin("MuBcanc"), CButton::tooltip(), [this](){ onClose(); });
+
+	background->playerColored(PlayerColor(1));
+
+	updateDescription();
+	center();
+}
+
+void GlobalLobbyServerSetup::updateDescription()
+{
+	MetaString description;
+	description.appendRawString("%s %s %s");
+	if (toggleRoomType->getSelected() == 0)
+		description.replaceTextID("vcmi.lobby.room.description.public");
+	else
+		description.replaceTextID("vcmi.lobby.room.description.private");
+
+	if (toggleGameMode->getSelected() == 0)
+		description.replaceTextID("vcmi.lobby.room.description.new");
+	else
+		description.replaceTextID("vcmi.lobby.room.description.load");
+
+	description.replaceTextID("vcmi.lobby.room.description.limit");
+	description.replaceNumber(togglePlayerLimit->getSelected());
+
+	labelDescription->setText(description.toString());
+}
+
+void GlobalLobbyServerSetup::onPlayerLimitChanged(int value)
+{
+	Settings config = settings.write["lobby"]["roomPlayerLimit"];
+	config->Integer() = value;
+	updateDescription();
+}
+
+void GlobalLobbyServerSetup::onRoomTypeChanged(int value)
+{
+	Settings config = settings.write["lobby"]["roomType"];
+	config->Integer() = value;
+	updateDescription();
+}
+
+void GlobalLobbyServerSetup::onGameModeChanged(int value)
+{
+	Settings config = settings.write["lobby"]["roomMode"];
+	config->Integer() = value;
+	updateDescription();
+}
+
+void GlobalLobbyServerSetup::onCreate()
+{
+	if (toggleGameMode->getSelected() == 0)
+	{
+		CSH->resetStateForLobby(StartInfo::NEW_GAME, nullptr);
+		CSH->screenType = ESelectionScreen::newGame;
+	}
+	else
+	{
+		CSH->resetStateForLobby(StartInfo::LOAD_GAME, nullptr);
+		CSH->screenType = ESelectionScreen::loadGame;
+	}
+	CSH->loadMode = ELoadMode::MULTI;
+	CSH->startLocalServerAndConnect(true);
+}
+
+void GlobalLobbyServerSetup::onClose()
+{
+	close();
+}

+ 49 - 0
client/globalLobby/GlobalLobbyServerSetup.h

@@ -0,0 +1,49 @@
+/*
+ * GlobalLobbyServerSetup.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#pragma once
+
+#include "../windows/CWindowObject.h"
+
+class CLabel;
+class CTextBox;
+class FilledTexturePlayerColored;
+class CButton;
+class CToggleGroup;
+
+class GlobalLobbyServerSetup : public CWindowObject
+{
+	std::shared_ptr<FilledTexturePlayerColored> background;
+	std::shared_ptr<CLabel> labelTitle;
+
+	std::shared_ptr<CLabel> labelPlayerLimit;
+	std::shared_ptr<CLabel> labelRoomType;
+	std::shared_ptr<CLabel> labelGameMode;
+
+	std::shared_ptr<CToggleGroup> togglePlayerLimit; // 2-8
+	std::shared_ptr<CToggleGroup> toggleRoomType; // public or private
+	std::shared_ptr<CToggleGroup> toggleGameMode; // new game or load game
+
+	std::shared_ptr<CTextBox> labelDescription;
+	std::shared_ptr<CTextBox> labelStatus;
+
+	std::shared_ptr<CButton> buttonCreate;
+	std::shared_ptr<CButton> buttonClose;
+
+	void updateDescription();
+	void onPlayerLimitChanged(int value);
+	void onRoomTypeChanged(int value);
+	void onGameModeChanged(int value);
+
+	void onCreate();
+	void onClose();
+
+public:
+	GlobalLobbyServerSetup();
+};

+ 3 - 0
client/globalLobby/GlobalLobbyWindow.cpp

@@ -13,8 +13,10 @@
 
 #include "GlobalLobbyWidget.h"
 #include "GlobalLobbyClient.h"
+#include "GlobalLobbyServerSetup.h"
 
 #include "../gui/CGuiHandler.h"
+#include "../gui/WindowHandler.h"
 #include "../widgets/TextControls.h"
 #include "../CServerHandler.h"
 
@@ -47,6 +49,7 @@ void GlobalLobbyWindow::doSendChatMessage()
 
 void GlobalLobbyWindow::doCreateGameRoom()
 {
+	GH.windows().createAndPushWindow<GlobalLobbyServerSetup>();
 	// TODO:
 	// start local server and supply our UUID / client credentials to it
 	// server logs into lobby ( uuid = client, mode = server ). This creates 'room' in mode 'empty'

+ 6 - 5
client/mainmenu/CMainMenu.cpp

@@ -458,10 +458,11 @@ CMultiMode::CMultiMode(ESelectionScreen ScreenType)
 	playerName->setText(getPlayerName());
 	playerName->cb += std::bind(&CMultiMode::onNameChange, this, _1);
 
-	buttonHotseat = std::make_shared<CButton>(Point(373, 78), AnimationPath::builtin("MUBHOT.DEF"), CGI->generaltexth->zelp[266], std::bind(&CMultiMode::hostTCP, this));
-	buttonHost = std::make_shared<CButton>(Point(373, 78 + 57 * 1), AnimationPath::builtin("MUBHOST.DEF"), CButton::tooltip(CGI->generaltexth->translate("vcmi.mainMenu.hostTCP"), ""), std::bind(&CMultiMode::hostTCP, this));
-	buttonJoin = std::make_shared<CButton>(Point(373, 78 + 57 * 2), AnimationPath::builtin("MUBJOIN.DEF"), CButton::tooltip(CGI->generaltexth->translate("vcmi.mainMenu.joinTCP"), ""), std::bind(&CMultiMode::joinTCP, this));
-	buttonLobby = std::make_shared<CButton>(Point(373, 78 + 57 * 4), AnimationPath::builtin("MUBONL.DEF"), CGI->generaltexth->zelp[265], std::bind(&CMultiMode::openLobby, this));
+	buttonHotseat = std::make_shared<CButton>(Point(373, 78 + 57 * 0), AnimationPath::builtin("MUBHOT.DEF"), CGI->generaltexth->zelp[266], std::bind(&CMultiMode::hostTCP, this));
+	buttonLobby = std::make_shared<CButton>(Point(373, 78 + 57 * 1), AnimationPath::builtin("MUBONL.DEF"), CGI->generaltexth->zelp[265], std::bind(&CMultiMode::openLobby, this));
+
+	buttonHost = std::make_shared<CButton>(Point(373, 78 + 57 * 3), AnimationPath::builtin("MUBHOST.DEF"), CButton::tooltip(CGI->generaltexth->translate("vcmi.mainMenu.hostTCP"), ""), std::bind(&CMultiMode::hostTCP, this));
+	buttonJoin = std::make_shared<CButton>(Point(373, 78 + 57 * 4), AnimationPath::builtin("MUBJOIN.DEF"), CButton::tooltip(CGI->generaltexth->translate("vcmi.mainMenu.joinTCP"), ""), std::bind(&CMultiMode::joinTCP, this));
 
 	buttonCancel = std::make_shared<CButton>(Point(373, 424), AnimationPath::builtin("MUBCANC.DEF"), CGI->generaltexth->zelp[288], [=](){ close();}, EShortcut::GLOBAL_CANCEL);
 }
@@ -617,7 +618,7 @@ void CSimpleJoinScreen::startConnection(const std::string & addr, ui16 port)
 #endif
 
 	if(addr.empty())
-		CSH->startLocalServerAndConnect();
+		CSH->startLocalServerAndConnect(false);
 	else
 		CSH->connectToServer(addr, port);
 }

+ 16 - 1
config/schemas/settings.json

@@ -553,7 +553,7 @@
 			"type" : "object",
 			"additionalProperties" : false,
 			"default" : {},
-			"required" : [ "mapPreview", "accountID", "accountCookie", "displayName", "hostname", "port" ],
+			"required" : [ "mapPreview", "accountID", "accountCookie", "displayName", "hostname", "port", "roomPlayerLimit", "roomType", "roomMode" ],
 			"properties" : {
 				"mapPreview" : {
 					"type" : "boolean",
@@ -583,6 +583,21 @@
 					"type" : "number",
 					"default" : 30303
 				},
+				
+				"roomPlayerLimit" : {
+					"type" : "number",
+					"default" : 2
+				},
+				
+				"roomType" : {
+					"type" : "number",
+					"default" : 0
+				},
+				
+				"roomMode" : {
+					"type" : "number",
+					"default" : 0
+				},
 			}
 		},
 		"gameTweaks" : {

+ 14 - 14
config/widgets/lobbyWindow.json

@@ -58,7 +58,7 @@
 
 		{
 			"type": "areaFilled",
-			"rect": {"x": 5, "y": 210, "w": 250, "h": 310}
+			"rect": {"x": 5, "y": 210, "w": 250, "h": 340}
 		},
 		{
 			"type": "labelTitle",
@@ -117,11 +117,10 @@
 		
 		{
 			"type": "button",
-			"position": {"x": 940, "y": 10},
+			"position": {"x": 840, "y": 10},
 			"image": "settingsWindow/button80",
 			"help": "core.help.288",
 			"callback": "closeWindow",
-			"hotkey": "globalCancel",
 			"items":
 			[
 				{
@@ -129,18 +128,18 @@
 					"font": "medium",
 					"alignment": "center",
 					"color": "yellow",
-					"text": "Exit"
+					"text": "Leave"
 				}
 			]
 		},
 		
 		{
 			"type": "button",
-			"position": {"x": 828, "y": 565},
-			"image": "settingsWindow/button32",
+			"position": {"x": 940, "y": 10},
+			"image": "settingsWindow/button80",
 			"help": "core.help.288",
-			"callback": "sendMessage",
-			"hotkey": "globalAccept",
+			"callback": "closeWindow",
+			"hotkey": "globalCancel",
 			"items":
 			[
 				{
@@ -148,17 +147,18 @@
 					"font": "medium",
 					"alignment": "center",
 					"color": "yellow",
-					"text": ">"
+					"text": "Close"
 				}
 			]
 		},
 		
 		{
 			"type": "button",
-			"position": {"x": 10, "y": 520},
-			"image": "settingsWindow/button190",
+			"position": {"x": 828, "y": 565},
+			"image": "settingsWindow/button32",
 			"help": "core.help.288",
-			"callback": "createGameRoom",
+			"callback": "sendMessage",
+			"hotkey": "globalAccept",
 			"items":
 			[
 				{
@@ -166,7 +166,7 @@
 					"font": "medium",
 					"alignment": "center",
 					"color": "yellow",
-					"text": "Start Public Game"
+					"text": ">"
 				}
 			]
 		},
@@ -184,7 +184,7 @@
 					"font": "medium",
 					"alignment": "center",
 					"color": "yellow",
-					"text": "Start Private Game"
+					"text": "Create Room"
 				}
 			]
 		},

+ 4 - 15
server/CVCMIServer.cpp

@@ -266,17 +266,11 @@ void CVCMIServer::establishOutgoingConnection()
 	if(!cmdLineOptions.count("lobby"))
 		return;
 
-	uuid = cmdLineOptions["lobby-uuid"].as<std::string>();
-	auto address = cmdLineOptions["lobby"].as<std::string>();
-	int port = cmdLineOptions["lobby-port"].as<ui16>();
-	logNetwork->info("Establishing connection to remote at %s:%d with uuid %s", address, port, uuid);
+	std::string hostname = settings["lobby"]["hostname"].String();
+	int16_t port = settings["lobby"]["port"].Integer();
 
 	outgoingConnection = std::make_unique<NetworkClient>(*this);
-
-	outgoingConnection->start(address, port);//, SERVER_NAME, uuid);
-
-//	connections.insert(c);
-//	remoteConnections.insert(c);
+	outgoingConnection->start(hostname, port);
 }
 
 void CVCMIServer::prepareToRestart()
@@ -1004,12 +998,7 @@ static void handleCommandOptions(int argc, const char * argv[], boost::program_o
 	("help,h", "display help and exit")
 	("version,v", "display version information and exit")
 	("run-by-client", "indicate that server launched by client on same machine")
-	("uuid", po::value<std::string>(), "")
-	("port", po::value<ui16>(), "port at which server will listen to connections from client")
-	("lobby", po::value<std::string>(), "address to remote lobby")
-	("lobby-port", po::value<ui16>(), "port at which server connect to remote lobby")
-	("lobby-uuid", po::value<std::string>(), "")
-	("connections", po::value<ui16>(), "amount of connections to remote lobby");
+	("port", po::value<ui16>(), "port at which server will listen to connections from client");
 
 	if(argc > 1)
 	{