mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Initial version of global lobby server available in client
This commit is contained in:
		| @@ -89,6 +89,10 @@ if(NOT APPLE_IOS AND NOT ANDROID) | |||||||
| 	option(ENABLE_MONOLITHIC_INSTALL "Install everything in single directory on Linux and Mac" OFF) | 	option(ENABLE_MONOLITHIC_INSTALL "Install everything in single directory on Linux and Mac" OFF) | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
|  | if(NOT APPLE_IOS AND NOT ANDROID) | ||||||
|  | 	option(ENABLE_LOBBY "Enable compilation of lobby server" ON) | ||||||
|  | endif() | ||||||
|  |  | ||||||
| option(ENABLE_CCACHE "Speed up recompilation by caching previous compilations" OFF) | option(ENABLE_CCACHE "Speed up recompilation by caching previous compilations" OFF) | ||||||
| if(ENABLE_CCACHE) | if(ENABLE_CCACHE) | ||||||
| 	find_program(CCACHE ccache REQUIRED) | 	find_program(CCACHE ccache REQUIRED) | ||||||
| @@ -475,6 +479,10 @@ if(TARGET SDL2_ttf::SDL2_ttf) | |||||||
| 	add_library(SDL2::TTF ALIAS SDL2_ttf::SDL2_ttf) | 	add_library(SDL2::TTF ALIAS SDL2_ttf::SDL2_ttf) | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
|  | if(ENABLE_LOBBY) | ||||||
|  | 	find_package(SQLite3 REQUIRED) | ||||||
|  | endif() | ||||||
|  |  | ||||||
| if(ENABLE_LAUNCHER OR ENABLE_EDITOR) | if(ENABLE_LAUNCHER OR ENABLE_EDITOR) | ||||||
| 	# Widgets finds its own dependencies (QtGui and QtCore). | 	# Widgets finds its own dependencies (QtGui and QtCore). | ||||||
| 	find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Network) | 	find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Network) | ||||||
| @@ -622,6 +630,9 @@ endif() | |||||||
| if(ENABLE_EDITOR) | if(ENABLE_EDITOR) | ||||||
| 	add_subdirectory(mapeditor) | 	add_subdirectory(mapeditor) | ||||||
| endif() | endif() | ||||||
|  | if(ENABLE_LOBBY) | ||||||
|  | 	add_subdirectory(lobby) | ||||||
|  | endif() | ||||||
| add_subdirectory(client) | add_subdirectory(client) | ||||||
| add_subdirectory(server) | add_subdirectory(server) | ||||||
| if(ENABLE_TEST) | if(ENABLE_TEST) | ||||||
|   | |||||||
| @@ -95,6 +95,8 @@ set(client_SRCS | |||||||
| 	renderSDL/ScreenHandler.cpp | 	renderSDL/ScreenHandler.cpp | ||||||
| 	renderSDL/SDL_Extensions.cpp | 	renderSDL/SDL_Extensions.cpp | ||||||
|  |  | ||||||
|  | 	serverLobby/LobbyWindow.cpp | ||||||
|  |  | ||||||
| 	widgets/Buttons.cpp | 	widgets/Buttons.cpp | ||||||
| 	widgets/CArtifactHolder.cpp | 	widgets/CArtifactHolder.cpp | ||||||
| 	widgets/CComponent.cpp | 	widgets/CComponent.cpp | ||||||
| @@ -270,6 +272,8 @@ set(client_HEADERS | |||||||
| 	renderSDL/SDL_Extensions.h | 	renderSDL/SDL_Extensions.h | ||||||
| 	renderSDL/SDL_PixelAccess.h | 	renderSDL/SDL_PixelAccess.h | ||||||
|  |  | ||||||
|  | 	serverLobby/LobbyWindow.h | ||||||
|  |  | ||||||
| 	widgets/Buttons.h | 	widgets/Buttons.h | ||||||
| 	widgets/CArtifactHolder.h | 	widgets/CArtifactHolder.h | ||||||
| 	widgets/CComponent.h | 	widgets/CComponent.h | ||||||
|   | |||||||
| @@ -129,6 +129,9 @@ void InterfaceObjectConfigurable::build(const JsonNode &config) | |||||||
| 	 | 	 | ||||||
| 	for(const auto & item : items->Vector()) | 	for(const auto & item : items->Vector()) | ||||||
| 		addWidget(item["name"].String(), buildWidget(item)); | 		addWidget(item["name"].String(), buildWidget(item)); | ||||||
|  |  | ||||||
|  | 	pos.w = config["width"].Integer(); | ||||||
|  | 	pos.h = config["height"].Integer(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void InterfaceObjectConfigurable::addConditional(const std::string & name, bool active) | void InterfaceObjectConfigurable::addConditional(const std::string & name, bool active) | ||||||
|   | |||||||
| @@ -24,6 +24,7 @@ | |||||||
| #include "../gui/Shortcut.h" | #include "../gui/Shortcut.h" | ||||||
| #include "../gui/WindowHandler.h" | #include "../gui/WindowHandler.h" | ||||||
| #include "../render/Canvas.h" | #include "../render/Canvas.h" | ||||||
|  | #include "../serverLobby/LobbyWindow.h" | ||||||
| #include "../widgets/CComponent.h" | #include "../widgets/CComponent.h" | ||||||
| #include "../widgets/Buttons.h" | #include "../widgets/Buttons.h" | ||||||
| #include "../widgets/MiscWidgets.h" | #include "../widgets/MiscWidgets.h" | ||||||
| @@ -459,9 +460,17 @@ CMultiMode::CMultiMode(ESelectionScreen ScreenType) | |||||||
| 	buttonHotseat = std::make_shared<CButton>(Point(373, 78), AnimationPath::builtin("MUBHOT.DEF"), CGI->generaltexth->zelp[266], std::bind(&CMultiMode::hostTCP, this)); | 	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)); | 	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)); | 	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)); | ||||||
|  |  | ||||||
| 	buttonCancel = std::make_shared<CButton>(Point(373, 424), AnimationPath::builtin("MUBCANC.DEF"), CGI->generaltexth->zelp[288], [=](){ close();}, EShortcut::GLOBAL_CANCEL); | 	buttonCancel = std::make_shared<CButton>(Point(373, 424), AnimationPath::builtin("MUBCANC.DEF"), CGI->generaltexth->zelp[288], [=](){ close();}, EShortcut::GLOBAL_CANCEL); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void CMultiMode::openLobby() | ||||||
|  | { | ||||||
|  | 	close(); | ||||||
|  | 	GH.windows().createAndPushWindow<LobbyWindow>(); | ||||||
|  | } | ||||||
|  |  | ||||||
| void CMultiMode::hostTCP() | void CMultiMode::hostTCP() | ||||||
| { | { | ||||||
| 	auto savedScreenType = screenType; | 	auto savedScreenType = screenType; | ||||||
|   | |||||||
| @@ -86,12 +86,14 @@ public: | |||||||
| 	std::shared_ptr<CPicture> picture; | 	std::shared_ptr<CPicture> picture; | ||||||
| 	std::shared_ptr<CTextInput> playerName; | 	std::shared_ptr<CTextInput> playerName; | ||||||
| 	std::shared_ptr<CButton> buttonHotseat; | 	std::shared_ptr<CButton> buttonHotseat; | ||||||
|  | 	std::shared_ptr<CButton> buttonLobby; | ||||||
| 	std::shared_ptr<CButton> buttonHost; | 	std::shared_ptr<CButton> buttonHost; | ||||||
| 	std::shared_ptr<CButton> buttonJoin; | 	std::shared_ptr<CButton> buttonJoin; | ||||||
| 	std::shared_ptr<CButton> buttonCancel; | 	std::shared_ptr<CButton> buttonCancel; | ||||||
| 	std::shared_ptr<CGStatusBar> statusBar; | 	std::shared_ptr<CGStatusBar> statusBar; | ||||||
|  |  | ||||||
| 	CMultiMode(ESelectionScreen ScreenType); | 	CMultiMode(ESelectionScreen ScreenType); | ||||||
|  | 	void openLobby(); | ||||||
| 	void hostTCP(); | 	void hostTCP(); | ||||||
| 	void joinTCP(); | 	void joinTCP(); | ||||||
| 	std::string getPlayerName(); | 	std::string getPlayerName(); | ||||||
|   | |||||||
							
								
								
									
										40
									
								
								client/serverLobby/LobbyWindow.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								client/serverLobby/LobbyWindow.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | /* | ||||||
|  |  * LobbyWindow.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 "LobbyWindow.h" | ||||||
|  |  | ||||||
|  | #include "../gui/CGuiHandler.h" | ||||||
|  | #include "../gui/WindowHandler.h" | ||||||
|  |  | ||||||
|  | void LobbyClient::onPacketReceived(const std::vector<uint8_t> & message) | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | LobbyWidget::LobbyWidget() | ||||||
|  | { | ||||||
|  | 	addCallback("closeWindow", [](int) { GH.windows().popWindows(1); }); | ||||||
|  |  | ||||||
|  | 	const JsonNode config(JsonPath::builtin("config/widgets/lobbyWindow.json")); | ||||||
|  | 	build(config); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | LobbyWindow::LobbyWindow(): | ||||||
|  | 	CWindowObject(BORDERED) | ||||||
|  | { | ||||||
|  | 	OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE; | ||||||
|  | 	widget = std::make_shared<LobbyWidget>(); | ||||||
|  | 	pos = widget->pos; | ||||||
|  | 	center(); | ||||||
|  | 	connection = std::make_shared<LobbyClient>(); | ||||||
|  |  | ||||||
|  | 	connection->start("127.0.0.1", 30303); | ||||||
|  | } | ||||||
							
								
								
									
										37
									
								
								client/serverLobby/LobbyWindow.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								client/serverLobby/LobbyWindow.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | |||||||
|  | /* | ||||||
|  |  * LobbyWindow.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 "../gui/InterfaceObjectConfigurable.h" | ||||||
|  | #include "../windows/CWindowObject.h" | ||||||
|  |  | ||||||
|  | #include "../../lib/network/NetworkClient.h" | ||||||
|  |  | ||||||
|  | class LobbyWidget : public InterfaceObjectConfigurable | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	LobbyWidget(); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | class LobbyClient : public NetworkClient | ||||||
|  | { | ||||||
|  | 	void onPacketReceived(const std::vector<uint8_t> & message) override; | ||||||
|  | public: | ||||||
|  | 	LobbyClient() = default; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | class LobbyWindow : public CWindowObject | ||||||
|  | { | ||||||
|  | 	std::shared_ptr<LobbyWidget> widget; | ||||||
|  | 	std::shared_ptr<LobbyClient> connection; | ||||||
|  |  | ||||||
|  | public: | ||||||
|  | 	LobbyWindow(); | ||||||
|  | }; | ||||||
| @@ -124,6 +124,10 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE) | |||||||
| 		${MAIN_LIB_DIR}/modding/IdentifierStorage.cpp | 		${MAIN_LIB_DIR}/modding/IdentifierStorage.cpp | ||||||
| 		${MAIN_LIB_DIR}/modding/ModUtility.cpp | 		${MAIN_LIB_DIR}/modding/ModUtility.cpp | ||||||
|  |  | ||||||
|  | 		${MAIN_LIB_DIR}/network/NetworkClient.cpp | ||||||
|  | 		${MAIN_LIB_DIR}/network/NetworkConnection.cpp | ||||||
|  | 		${MAIN_LIB_DIR}/network/NetworkServer.cpp | ||||||
|  |  | ||||||
| 		${MAIN_LIB_DIR}/networkPacks/NetPacksLib.cpp | 		${MAIN_LIB_DIR}/networkPacks/NetPacksLib.cpp | ||||||
|  |  | ||||||
| 		${MAIN_LIB_DIR}/pathfinder/CGPathNode.cpp | 		${MAIN_LIB_DIR}/pathfinder/CGPathNode.cpp | ||||||
| @@ -471,6 +475,11 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE) | |||||||
| 		${MAIN_LIB_DIR}/modding/ModUtility.h | 		${MAIN_LIB_DIR}/modding/ModUtility.h | ||||||
| 		${MAIN_LIB_DIR}/modding/ModVerificationInfo.h | 		${MAIN_LIB_DIR}/modding/ModVerificationInfo.h | ||||||
|  |  | ||||||
|  | 		${MAIN_LIB_DIR}/network/NetworkClient.h | ||||||
|  | 		${MAIN_LIB_DIR}/network/NetworkConnection.h | ||||||
|  | 		${MAIN_LIB_DIR}/network/NetworkDefines.h | ||||||
|  | 		${MAIN_LIB_DIR}/network/NetworkServer.h | ||||||
|  |  | ||||||
| 		${MAIN_LIB_DIR}/networkPacks/ArtifactLocation.h | 		${MAIN_LIB_DIR}/networkPacks/ArtifactLocation.h | ||||||
| 		${MAIN_LIB_DIR}/networkPacks/BattleChanges.h | 		${MAIN_LIB_DIR}/networkPacks/BattleChanges.h | ||||||
| 		${MAIN_LIB_DIR}/networkPacks/Component.h | 		${MAIN_LIB_DIR}/networkPacks/Component.h | ||||||
|   | |||||||
							
								
								
									
										186
									
								
								config/widgets/lobbyWindow.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								config/widgets/lobbyWindow.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,186 @@ | |||||||
|  | { | ||||||
|  | 	"customTypes" : { | ||||||
|  | 		"labelTitleMain" : { | ||||||
|  | 			"type": "label", | ||||||
|  | 			"font": "big", | ||||||
|  | 			"alignment": "left", | ||||||
|  | 			"color": "yellow" | ||||||
|  | 		}, | ||||||
|  | 		"labelTitle" : { | ||||||
|  | 			"type": "label", | ||||||
|  | 			"font": "small", | ||||||
|  | 			"alignment": "left", | ||||||
|  | 			"color": "yellow" | ||||||
|  | 		}, | ||||||
|  | 		"backgroundTexture" : { | ||||||
|  | 			"type": "texture", | ||||||
|  | 			"font": "tiny", | ||||||
|  | 			"color" : "blue", | ||||||
|  | 			"image": "DIBOXBCK" | ||||||
|  | 		}, | ||||||
|  | 		"areaFilled":{ | ||||||
|  | 			"type": "transparentFilledRectangle", | ||||||
|  | 			"color": [0, 0, 0, 75], | ||||||
|  | 			"colorLine": [64, 80, 128, 255] | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  | 	 | ||||||
|  | 	 | ||||||
|  | 	"width": 1024, | ||||||
|  | 	"height": 600, | ||||||
|  | 	 | ||||||
|  | 	"items": | ||||||
|  | 	[ | ||||||
|  | 		{ | ||||||
|  | 			"type": "backgroundTexture", | ||||||
|  | 			"rect": {"w": 1024, "h": 600} | ||||||
|  | 		}, | ||||||
|  | 		 | ||||||
|  | 		{ | ||||||
|  | 			"type": "areaFilled", | ||||||
|  | 			"rect": {"x": 5, "y": 5, "w": 250, "h": 40} | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"type": "labelTitleMain", | ||||||
|  | 			"position": {"x": 15, "y": 10}, | ||||||
|  | 			"text" : "Player Name" | ||||||
|  | 		}, | ||||||
|  | 		 | ||||||
|  | 		{ | ||||||
|  | 			"type": "areaFilled", | ||||||
|  | 			"rect": {"x": 5, "y": 50, "w": 250, "h": 150} | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"type": "labelTitle", | ||||||
|  | 			"position": {"x": 15, "y": 53}, | ||||||
|  | 			"text" : "Match Filter" | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		{ | ||||||
|  | 			"type": "areaFilled", | ||||||
|  | 			"rect": {"x": 5, "y": 210, "w": 250, "h": 310} | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"type": "labelTitle", | ||||||
|  | 			"position": {"x": 15, "y": 213}, | ||||||
|  | 			"text" : "Match List" | ||||||
|  | 		}, | ||||||
|  | 		 | ||||||
|  | 		{ | ||||||
|  | 			"type": "areaFilled", | ||||||
|  | 			"rect": {"x": 270, "y": 50, "w": 150, "h": 540} | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"type": "labelTitle", | ||||||
|  | 			"position": {"x": 280, "y": 53}, | ||||||
|  | 			"text" : "Channel List" | ||||||
|  | 		}, | ||||||
|  | 		 | ||||||
|  | 		{ | ||||||
|  | 			"type": "areaFilled", | ||||||
|  | 			"rect": {"x": 430, "y": 50, "w": 430, "h": 515} | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"type": "labelTitle", | ||||||
|  | 			"position": {"x": 440, "y": 53}, | ||||||
|  | 			"text" : "Game Chat" | ||||||
|  | 		}, | ||||||
|  | 		 | ||||||
|  | 		{ | ||||||
|  | 			"type": "areaFilled", | ||||||
|  | 			"rect": {"x": 430, "y": 565, "w": 395, "h": 25} | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"type": "labelTitle", | ||||||
|  | 			"position": {"x": 440, "y": 568}, | ||||||
|  | 			"text" : "Enter Message" | ||||||
|  | 		}, | ||||||
|  | 		 | ||||||
|  | 		{ | ||||||
|  | 			"type": "areaFilled", | ||||||
|  | 			"rect": {"x": 870, "y": 50, "w": 150, "h": 540} | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"type": "labelTitle", | ||||||
|  | 			"position": {"x": 880, "y": 53}, | ||||||
|  | 			"text" : "Player List" | ||||||
|  | 		}, | ||||||
|  | 		 | ||||||
|  | 		{ | ||||||
|  | 			"type": "button", | ||||||
|  | 			"position": {"x": 940, "y": 10}, | ||||||
|  | 			"image": "settingsWindow/button80", | ||||||
|  | 			"help": "core.help.288", | ||||||
|  | 			"callback": "closeWindow", | ||||||
|  | 			"hotkey": "globalReturn", | ||||||
|  | 			"items": | ||||||
|  | 			[ | ||||||
|  | 				{ | ||||||
|  | 					"type": "label", | ||||||
|  | 					"font": "medium", | ||||||
|  | 					"alignment": "center", | ||||||
|  | 					"color": "yellow", | ||||||
|  | 					"text": "Exit" | ||||||
|  | 				} | ||||||
|  | 			] | ||||||
|  | 		}, | ||||||
|  | 		 | ||||||
|  | 		{ | ||||||
|  | 			"type": "button", | ||||||
|  | 			"position": {"x": 828, "y": 565}, | ||||||
|  | 			"image": "settingsWindow/button32", | ||||||
|  | 			"help": "core.help.288", | ||||||
|  | 			"callback": "closeWindow", | ||||||
|  | 			"hotkey": "globalReturn", | ||||||
|  | 			"items": | ||||||
|  | 			[ | ||||||
|  | 				{ | ||||||
|  | 					"type": "label", | ||||||
|  | 					"font": "medium", | ||||||
|  | 					"alignment": "center", | ||||||
|  | 					"color": "yellow", | ||||||
|  | 					"text": ">" | ||||||
|  | 				} | ||||||
|  | 			] | ||||||
|  | 		}, | ||||||
|  | 		 | ||||||
|  | 		{ | ||||||
|  | 			"type": "button", | ||||||
|  | 			"position": {"x": 10, "y": 520}, | ||||||
|  | 			"image": "settingsWindow/button190", | ||||||
|  | 			"help": "core.help.288", | ||||||
|  | 			"callback": "closeWindow", | ||||||
|  | 			"hotkey": "globalReturn", | ||||||
|  | 			"items": | ||||||
|  | 			[ | ||||||
|  | 				{ | ||||||
|  | 					"type": "label", | ||||||
|  | 					"font": "medium", | ||||||
|  | 					"alignment": "center", | ||||||
|  | 					"color": "yellow", | ||||||
|  | 					"text": "Start Public Game" | ||||||
|  | 				} | ||||||
|  | 			] | ||||||
|  | 		}, | ||||||
|  | 		 | ||||||
|  | 		{ | ||||||
|  | 			"type": "button", | ||||||
|  | 			"position": {"x": 10, "y": 555}, | ||||||
|  | 			"image": "settingsWindow/button190", | ||||||
|  | 			"help": "core.help.288", | ||||||
|  | 			"callback": "closeWindow", | ||||||
|  | 			"hotkey": "globalReturn", | ||||||
|  | 			"items": | ||||||
|  | 			[ | ||||||
|  | 				{ | ||||||
|  | 					"type": "label", | ||||||
|  | 					"font": "medium", | ||||||
|  | 					"alignment": "center", | ||||||
|  | 					"color": "yellow", | ||||||
|  | 					"text": "Start Private Game" | ||||||
|  | 				} | ||||||
|  | 			] | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 	] | ||||||
|  | } | ||||||
							
								
								
									
										47
									
								
								lib/network/NetworkClient.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								lib/network/NetworkClient.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | |||||||
|  | /* | ||||||
|  |  * NetworkClient.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 "NetworkClient.h" | ||||||
|  | #include "NetworkConnection.h" | ||||||
|  |  | ||||||
|  | VCMI_LIB_NAMESPACE_BEGIN | ||||||
|  |  | ||||||
|  | NetworkClient::NetworkClient() | ||||||
|  | 	: io(new NetworkService) | ||||||
|  | 	, socket(new NetworkSocket(*io)) | ||||||
|  | //	, timer(new NetworkTimer(*io)) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void NetworkClient::start(const std::string & host, uint16_t port) | ||||||
|  | { | ||||||
|  | 	boost::asio::ip::tcp::resolver resolver(*io); | ||||||
|  | 	auto endpoints = resolver.resolve(host, std::to_string(port)); | ||||||
|  |  | ||||||
|  | 	boost::asio::async_connect(*socket, endpoints, std::bind(&NetworkClient::onConnected, this, _1)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void NetworkClient::onConnected(const boost::system::error_code & ec) | ||||||
|  | { | ||||||
|  | 	connection = std::make_shared<NetworkConnection>(socket); | ||||||
|  | 	connection->start(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void NetworkClient::run() | ||||||
|  | { | ||||||
|  | 	io->run(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void NetworkClient::sendPacket(const std::vector<uint8_t> & message) | ||||||
|  | { | ||||||
|  | 	connection->sendPacket(message); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | VCMI_LIB_NAMESPACE_END | ||||||
							
								
								
									
										37
									
								
								lib/network/NetworkClient.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								lib/network/NetworkClient.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | |||||||
|  | /* | ||||||
|  |  * NetworkClient.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 "NetworkDefines.h" | ||||||
|  |  | ||||||
|  | VCMI_LIB_NAMESPACE_BEGIN | ||||||
|  |  | ||||||
|  | class NetworkConnection; | ||||||
|  |  | ||||||
|  | class DLL_LINKAGE NetworkClient : boost::noncopyable | ||||||
|  | { | ||||||
|  | 	std::shared_ptr<NetworkService> io; | ||||||
|  | 	std::shared_ptr<NetworkSocket> socket; | ||||||
|  | 	std::shared_ptr<NetworkConnection> connection; | ||||||
|  | 	std::shared_ptr<NetworkTimer> timer; | ||||||
|  |  | ||||||
|  | 	void onConnected(const boost::system::error_code & ec); | ||||||
|  | protected: | ||||||
|  | 	virtual void onPacketReceived(const std::vector<uint8_t> & message) = 0; | ||||||
|  | public: | ||||||
|  | 	NetworkClient(); | ||||||
|  | 	virtual ~NetworkClient() = default; | ||||||
|  |  | ||||||
|  | 	void start(const std::string & host, uint16_t port); | ||||||
|  | 	void sendPacket(const std::vector<uint8_t> & message); | ||||||
|  | 	void run(); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | VCMI_LIB_NAMESPACE_END | ||||||
							
								
								
									
										97
									
								
								lib/network/NetworkConnection.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								lib/network/NetworkConnection.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | |||||||
|  | /* | ||||||
|  |  * NetworkConnection.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 "NetworkConnection.h" | ||||||
|  |  | ||||||
|  | VCMI_LIB_NAMESPACE_BEGIN | ||||||
|  |  | ||||||
|  | NetworkConnection::NetworkConnection(const std::shared_ptr<NetworkSocket> & socket) | ||||||
|  | 	: socket(socket) | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void NetworkConnection::start() | ||||||
|  | { | ||||||
|  | 	boost::asio::async_read(*socket, | ||||||
|  | 							readBuffer, | ||||||
|  | 							boost::asio::transfer_exactly(messageHeaderSize), | ||||||
|  | 							std::bind(&NetworkConnection::onHeaderReceived,this, _1)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void NetworkConnection::onHeaderReceived(const boost::system::error_code & ec) | ||||||
|  | { | ||||||
|  | 	uint32_t messageSize = readPacketSize(ec); | ||||||
|  |  | ||||||
|  | 	boost::asio::async_read(*socket, | ||||||
|  | 							readBuffer, | ||||||
|  | 							boost::asio::transfer_exactly(messageSize), | ||||||
|  | 							std::bind(&NetworkConnection::onPacketReceived,this, _1, messageSize)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | uint32_t NetworkConnection::readPacketSize(const boost::system::error_code & ec) | ||||||
|  | { | ||||||
|  | 	if (ec) | ||||||
|  | 	{ | ||||||
|  | 		throw std::runtime_error("Connection aborted!"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (readBuffer.size() < messageHeaderSize) | ||||||
|  | 	{ | ||||||
|  | 		throw std::runtime_error("Failed to read header!"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	std::istream istream(&readBuffer); | ||||||
|  |  | ||||||
|  | 	uint32_t messageSize; | ||||||
|  | 	istream.read(reinterpret_cast<char *>(&messageSize), messageHeaderSize); | ||||||
|  |  | ||||||
|  | 	if (messageSize > messageMaxSize) | ||||||
|  | 	{ | ||||||
|  | 		throw std::runtime_error("Invalid packet size!"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return messageSize; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void NetworkConnection::onPacketReceived(const boost::system::error_code & ec, uint32_t expectedPacketSize) | ||||||
|  | { | ||||||
|  | 	if (ec) | ||||||
|  | 	{ | ||||||
|  | 		throw std::runtime_error("Connection aborted!"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (readBuffer.size() < expectedPacketSize) | ||||||
|  | 	{ | ||||||
|  | 		throw std::runtime_error("Failed to read header!"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	std::vector<uint8_t> message; | ||||||
|  |  | ||||||
|  | 	message.resize(expectedPacketSize); | ||||||
|  | 	std::istream istream(&readBuffer); | ||||||
|  | 	istream.read(reinterpret_cast<char *>(message.data()), messageHeaderSize); | ||||||
|  |  | ||||||
|  | 	start(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void NetworkConnection::sendPacket(const std::vector<uint8_t> & message) | ||||||
|  | { | ||||||
|  | 	NetworkBuffer writeBuffer; | ||||||
|  |  | ||||||
|  | 	std::ostream ostream(&writeBuffer); | ||||||
|  | 	uint32_t messageSize = message.size(); | ||||||
|  | 	ostream.write(reinterpret_cast<const char *>(&messageSize), messageHeaderSize); | ||||||
|  | 	ostream.write(reinterpret_cast<const char *>(message.data()), message.size()); | ||||||
|  |  | ||||||
|  | 	boost::asio::write(*socket, writeBuffer ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | VCMI_LIB_NAMESPACE_END | ||||||
							
								
								
									
										36
									
								
								lib/network/NetworkConnection.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								lib/network/NetworkConnection.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | /* | ||||||
|  |  * NetworkConnection.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 "NetworkDefines.h" | ||||||
|  |  | ||||||
|  | VCMI_LIB_NAMESPACE_BEGIN | ||||||
|  |  | ||||||
|  | class DLL_LINKAGE NetworkConnection : boost::noncopyable | ||||||
|  | { | ||||||
|  | 	static const int messageHeaderSize = sizeof(uint32_t); | ||||||
|  | 	static const int messageMaxSize = 1024; | ||||||
|  |  | ||||||
|  | 	std::shared_ptr<NetworkSocket> socket; | ||||||
|  |  | ||||||
|  | 	NetworkBuffer readBuffer; | ||||||
|  |  | ||||||
|  | 	void onHeaderReceived(const boost::system::error_code & ec); | ||||||
|  | 	void onPacketReceived(const boost::system::error_code & ec, uint32_t expectedPacketSize); | ||||||
|  | 	uint32_t readPacketSize(const boost::system::error_code & ec); | ||||||
|  |  | ||||||
|  | public: | ||||||
|  | 	NetworkConnection(const std::shared_ptr<NetworkSocket> & socket); | ||||||
|  |  | ||||||
|  | 	void start(); | ||||||
|  | 	void sendPacket(const std::vector<uint8_t> & message); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | VCMI_LIB_NAMESPACE_END | ||||||
							
								
								
									
										22
									
								
								lib/network/NetworkDefines.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								lib/network/NetworkDefines.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | /* | ||||||
|  |  * NetworkDefines.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 <boost/asio.hpp> | ||||||
|  |  | ||||||
|  | VCMI_LIB_NAMESPACE_BEGIN | ||||||
|  |  | ||||||
|  | using NetworkService = boost::asio::io_service; | ||||||
|  | using NetworkSocket = boost::asio::basic_stream_socket<boost::asio::ip::tcp>; | ||||||
|  | using NetworkAcceptor = boost::asio::basic_socket_acceptor<boost::asio::ip::tcp>; | ||||||
|  | using NetworkBuffer = boost::asio::streambuf; | ||||||
|  | using NetworkTimer = boost::asio::steady_timer; | ||||||
|  |  | ||||||
|  | VCMI_LIB_NAMESPACE_END | ||||||
							
								
								
									
										63
									
								
								lib/network/NetworkServer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								lib/network/NetworkServer.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | |||||||
|  | /* | ||||||
|  |  * NetworkServer.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 "NetworkServer.h" | ||||||
|  | #include "NetworkConnection.h" | ||||||
|  |  | ||||||
|  | VCMI_LIB_NAMESPACE_BEGIN | ||||||
|  |  | ||||||
|  | void NetworkServer::start(uint16_t port) | ||||||
|  | { | ||||||
|  | 	io = std::make_shared<boost::asio::io_service>(); | ||||||
|  | 	acceptor = std::make_shared<NetworkAcceptor>(*io, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)); | ||||||
|  |  | ||||||
|  | 	startAsyncAccept(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void NetworkServer::startAsyncAccept() | ||||||
|  | { | ||||||
|  | 	std::shared_ptr<NetworkSocket> upcomingConnection = std::make_shared<NetworkSocket>(*io); | ||||||
|  | 	acceptor->async_accept(*upcomingConnection, std::bind(&NetworkServer::connectionAccepted, this, upcomingConnection, _1)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void NetworkServer::run() | ||||||
|  | { | ||||||
|  | 	io->run(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void NetworkServer::connectionAccepted(std::shared_ptr<NetworkSocket> upcomingConnection, const boost::system::error_code & ec) | ||||||
|  | { | ||||||
|  | 	if(ec) | ||||||
|  | 	{ | ||||||
|  | 		logNetwork->info("Something wrong during accepting: %s", ec.message()); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	try | ||||||
|  | 	{ | ||||||
|  | 		logNetwork->info("We got a new connection! :)"); | ||||||
|  | 		auto connection = std::make_shared<NetworkConnection>(upcomingConnection); | ||||||
|  | 		connections.insert(connection); | ||||||
|  | 		connection->start(); | ||||||
|  | 	} | ||||||
|  | 	catch(std::exception & e) | ||||||
|  | 	{ | ||||||
|  | 		logNetwork->error("Failure processing new connection! %s", e.what()); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	startAsyncAccept(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void NetworkServer::sendPacket(const std::shared_ptr<NetworkConnection> & connection, const std::vector<uint8_t> & message) | ||||||
|  | { | ||||||
|  | 	connection->sendPacket(message); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | VCMI_LIB_NAMESPACE_END | ||||||
							
								
								
									
										39
									
								
								lib/network/NetworkServer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								lib/network/NetworkServer.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | /* | ||||||
|  |  * NetworkServer.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 "NetworkDefines.h" | ||||||
|  |  | ||||||
|  | VCMI_LIB_NAMESPACE_BEGIN | ||||||
|  |  | ||||||
|  | class NetworkConnection; | ||||||
|  |  | ||||||
|  | class DLL_LINKAGE NetworkServer : boost::noncopyable | ||||||
|  | { | ||||||
|  | 	std::shared_ptr<NetworkService> io; | ||||||
|  | 	std::shared_ptr<NetworkAcceptor> acceptor; | ||||||
|  | 	std::set<std::shared_ptr<NetworkConnection>> connections; | ||||||
|  |  | ||||||
|  | 	void connectionAccepted(std::shared_ptr<NetworkSocket>, const boost::system::error_code & ec); | ||||||
|  | 	void startAsyncAccept(); | ||||||
|  | protected: | ||||||
|  | 	virtual void onNewConnection(std::shared_ptr<NetworkConnection>) = 0; | ||||||
|  | 	virtual void onPacketReceived(std::shared_ptr<NetworkConnection>, const std::vector<uint8_t> & message) = 0; | ||||||
|  |  | ||||||
|  | 	void sendPacket(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message); | ||||||
|  |  | ||||||
|  | public: | ||||||
|  | 	virtual ~NetworkServer() = default; | ||||||
|  |  | ||||||
|  | 	void start(uint16_t port); | ||||||
|  | 	void run(); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | VCMI_LIB_NAMESPACE_END | ||||||
							
								
								
									
										39
									
								
								lobby/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								lobby/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | set(lobby_SRCS | ||||||
|  | 		StdInc.cpp | ||||||
|  | 		LobbyServer.cpp | ||||||
|  | 		SQLiteConnection.cpp | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | set(lobby_HEADERS | ||||||
|  | 		StdInc.h | ||||||
|  | 		LobbyServer.h | ||||||
|  | 		SQLiteConnection.h | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | assign_source_group(${lobby_SRCS} ${lobby_HEADERS}) | ||||||
|  |  | ||||||
|  | add_executable(vcmilobby ${lobby_SRCS} ${lobby_HEADERS}) | ||||||
|  | set(lobby_LIBS vcmi) | ||||||
|  |  | ||||||
|  | if(CMAKE_SYSTEM_NAME MATCHES FreeBSD OR HAIKU) | ||||||
|  | 	set(lobby_LIBS execinfo ${lobby_LIBS}) | ||||||
|  | endif() | ||||||
|  |  | ||||||
|  | target_link_libraries(vcmilobby PRIVATE ${lobby_LIBS} ${SQLite3_LIBRARIES}) | ||||||
|  |  | ||||||
|  | target_include_directories(vcmilobby PRIVATE ${SQLite3_INCLUDE_DIRS}) | ||||||
|  | target_include_directories(vcmilobby PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) | ||||||
|  |  | ||||||
|  | if(WIN32) | ||||||
|  | 	set_target_properties(vcmilobby | ||||||
|  | 		PROPERTIES | ||||||
|  | 			OUTPUT_NAME "VCMI_lobby" | ||||||
|  | 			PROJECT_LABEL "VCMI_lobby" | ||||||
|  | 	) | ||||||
|  | endif() | ||||||
|  |  | ||||||
|  | vcmi_set_output_dir(vcmilobby "") | ||||||
|  | enable_pch(vcmilobby) | ||||||
|  |  | ||||||
|  | install(TARGETS vcmilobby DESTINATION ${BIN_DIR}) | ||||||
|  |  | ||||||
							
								
								
									
										45
									
								
								lobby/LobbyServer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								lobby/LobbyServer.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | |||||||
|  | /* | ||||||
|  |  * LobbyServer.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 "LobbyServer.h" | ||||||
|  |  | ||||||
|  | #include "SQLiteConnection.h" | ||||||
|  |  | ||||||
|  | #include <boost/uuid/uuid_generators.hpp> | ||||||
|  | #include <boost/uuid/uuid_io.hpp> | ||||||
|  |  | ||||||
|  | static const std::string DATABASE_PATH = "~/vcmi.db"; | ||||||
|  | static const int LISTENING_PORT = 30303; | ||||||
|  | //static const std::string SERVER_NAME = GameConstants::VCMI_VERSION + " (server)"; | ||||||
|  | //static const std::string SERVER_UUID = boost::uuids::to_string(boost::uuids::random_generator()()); | ||||||
|  |  | ||||||
|  | void LobbyServer::onNewConnection(std::shared_ptr<NetworkConnection>) | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void LobbyServer::onPacketReceived(std::shared_ptr<NetworkConnection>, const std::vector<uint8_t> & message) | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | LobbyServer::LobbyServer() | ||||||
|  | { | ||||||
|  | 	database = SQLiteInstance::open(DATABASE_PATH, true); | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int main(int argc, const char * argv[]) | ||||||
|  | { | ||||||
|  | 	LobbyServer server; | ||||||
|  |  | ||||||
|  | 	server.start(LISTENING_PORT); | ||||||
|  | 	server.run(); | ||||||
|  | } | ||||||
							
								
								
									
										24
									
								
								lobby/LobbyServer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								lobby/LobbyServer.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | /* | ||||||
|  |  * LobbyServer.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 "../lib/network/NetworkServer.h" | ||||||
|  |  | ||||||
|  | class SQLiteInstance; | ||||||
|  |  | ||||||
|  | class LobbyServer : public NetworkServer | ||||||
|  | { | ||||||
|  | 	std::unique_ptr<SQLiteInstance> database; | ||||||
|  |  | ||||||
|  | 	void onNewConnection(std::shared_ptr<NetworkConnection>) override; | ||||||
|  | 	void onPacketReceived(std::shared_ptr<NetworkConnection>, const std::vector<uint8_t> & message) override; | ||||||
|  | public: | ||||||
|  | 	LobbyServer(); | ||||||
|  | }; | ||||||
							
								
								
									
										197
									
								
								lobby/SQLiteConnection.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								lobby/SQLiteConnection.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,197 @@ | |||||||
|  | /* | ||||||
|  |  * SQLiteConnection.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 "SQLiteConnection.h" | ||||||
|  |  | ||||||
|  | #include <sqlite3.h> | ||||||
|  |  | ||||||
|  | static void on_sqlite_error( sqlite3 * connection, [[maybe_unused]] int result ) | ||||||
|  | { | ||||||
|  | 	if ( result != SQLITE_OK ) | ||||||
|  | 	{ | ||||||
|  | 		printf( "sqlite error: %s\n", sqlite3_errmsg( connection ) ); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	assert( result == SQLITE_OK ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | SQLiteStatement::SQLiteStatement( SQLiteInstance & instance, sqlite3_stmt * statement ): | ||||||
|  | 	m_instance( instance ), | ||||||
|  | 	m_statement( statement ) | ||||||
|  | { } | ||||||
|  |  | ||||||
|  | SQLiteStatement::~SQLiteStatement( ) | ||||||
|  | {  | ||||||
|  | 	int result = sqlite3_finalize( m_statement ); | ||||||
|  | 	on_sqlite_error( m_instance.m_connection, result ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool SQLiteStatement::execute( ) | ||||||
|  | {  | ||||||
|  | 	int result = sqlite3_step( m_statement ); | ||||||
|  |  | ||||||
|  | 	switch ( result ) | ||||||
|  | 	{ | ||||||
|  | 		case SQLITE_DONE: | ||||||
|  | 			return false; | ||||||
|  | 		case SQLITE_ROW: | ||||||
|  | 			return true; | ||||||
|  | 		default: | ||||||
|  | 			on_sqlite_error( m_instance.m_connection, result ); | ||||||
|  | 			return false; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SQLiteStatement::reset( ) | ||||||
|  | { | ||||||
|  | 	int result = sqlite3_reset( m_statement ); | ||||||
|  | 	on_sqlite_error( m_instance.m_connection, result ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SQLiteStatement::clear() | ||||||
|  | { | ||||||
|  | 	int result = sqlite3_clear_bindings(m_statement); | ||||||
|  | 	on_sqlite_error(m_instance.m_connection, result); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SQLiteStatement::setBindSingle( size_t index, double const & value ) | ||||||
|  | { | ||||||
|  | 	int result = sqlite3_bind_double( m_statement, static_cast<int>(index), value ); | ||||||
|  | 	on_sqlite_error( m_instance.m_connection, result ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SQLiteStatement::setBindSingle(size_t index, uint8_t const & value) | ||||||
|  | { | ||||||
|  | 	int result = sqlite3_bind_int(m_statement, static_cast<int>(index), value); | ||||||
|  | 	on_sqlite_error(m_instance.m_connection, result); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SQLiteStatement::setBindSingle(size_t index, uint16_t const & value) | ||||||
|  | { | ||||||
|  | 	int result = sqlite3_bind_int(m_statement, static_cast<int>(index), value); | ||||||
|  | 	on_sqlite_error(m_instance.m_connection, result); | ||||||
|  | } | ||||||
|  | void SQLiteStatement::setBindSingle(size_t index, uint32_t const & value) | ||||||
|  | { | ||||||
|  | 	int result = sqlite3_bind_int(m_statement, static_cast<int>(index), value); | ||||||
|  | 	on_sqlite_error(m_instance.m_connection, result); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SQLiteStatement::setBindSingle( size_t index, int32_t const & value ) | ||||||
|  | { | ||||||
|  | 	int result = sqlite3_bind_int( m_statement, static_cast<int>( index ), value ); | ||||||
|  | 	on_sqlite_error( m_instance.m_connection, result ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SQLiteStatement::setBindSingle( size_t index, int64_t const & value ) | ||||||
|  | { | ||||||
|  | 	int result = sqlite3_bind_int64( m_statement, static_cast<int>( index ), value ); | ||||||
|  | 	on_sqlite_error( m_instance.m_connection, result ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SQLiteStatement::setBindSingle( size_t index, std::string const & value ) | ||||||
|  | { | ||||||
|  | 	int result = sqlite3_bind_text( m_statement, static_cast<int>( index ), value.data(), static_cast<int>( value.size() ), SQLITE_STATIC ); | ||||||
|  | 	on_sqlite_error( m_instance.m_connection, result ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SQLiteStatement::setBindSingle( size_t index, char const * value ) | ||||||
|  | { | ||||||
|  | 	int result = sqlite3_bind_text( m_statement, static_cast<int>( index ), value, -1, SQLITE_STATIC ); | ||||||
|  | 	on_sqlite_error( m_instance.m_connection, result ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SQLiteStatement::getColumnSingle( size_t index, double & value ) | ||||||
|  | { | ||||||
|  | 	value = sqlite3_column_double( m_statement, static_cast<int>( index ) ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SQLiteStatement::getColumnSingle( size_t index, uint8_t & value ) | ||||||
|  | { | ||||||
|  | 	value = static_cast<uint8_t>(sqlite3_column_int( m_statement, static_cast<int>( index ) )); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SQLiteStatement::getColumnSingle(size_t index, uint16_t & value) | ||||||
|  | { | ||||||
|  | 	value = static_cast<uint16_t>(sqlite3_column_int(m_statement, static_cast<int>(index))); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SQLiteStatement::getColumnSingle( size_t index, int32_t & value ) | ||||||
|  | { | ||||||
|  | 	value = sqlite3_column_int( m_statement, static_cast<int>( index ) ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SQLiteStatement::getColumnSingle(size_t index, uint32_t & value) | ||||||
|  | { | ||||||
|  | 	value = sqlite3_column_int(m_statement, static_cast<int>(index)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SQLiteStatement::getColumnSingle( size_t index, int64_t & value ) | ||||||
|  | { | ||||||
|  | 	value = sqlite3_column_int64( m_statement, static_cast<int>( index ) ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SQLiteStatement::getColumnSingle( size_t index, std::string & value ) | ||||||
|  | { | ||||||
|  | 	auto value_raw = sqlite3_column_text(m_statement, static_cast<int>(index)); | ||||||
|  | 	value = reinterpret_cast<char const*>( value_raw ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SQLiteStatement::getColumnBlob(size_t index, std::byte * value, [[maybe_unused]] size_t capacity) | ||||||
|  | { | ||||||
|  | 	auto * blob_data = sqlite3_column_blob(m_statement, static_cast<int>(index)); | ||||||
|  | 	size_t blob_size = sqlite3_column_bytes(m_statement, static_cast<int>(index)); | ||||||
|  |  | ||||||
|  | 	assert(blob_size < capacity); | ||||||
|  |  | ||||||
|  | 	std::copy_n(static_cast<std::byte const*>(blob_data), blob_size, value); | ||||||
|  | 	value[blob_size] = std::byte(0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | SQLiteInstancePtr SQLiteInstance::open( std::string const & db_path, bool allow_write) | ||||||
|  | { | ||||||
|  | 	int flags = allow_write ? (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE) : SQLITE_OPEN_READONLY; | ||||||
|  |  | ||||||
|  | 	sqlite3 * connection; | ||||||
|  | 	int result = sqlite3_open_v2( db_path.c_str( ), &connection, flags, nullptr ); | ||||||
|  |  | ||||||
|  | 	on_sqlite_error( connection, result ); | ||||||
|  |  | ||||||
|  | 	assert(result == SQLITE_OK); | ||||||
|  |  | ||||||
|  | 	if ( result == SQLITE_OK ) | ||||||
|  | 		return SQLiteInstancePtr( new SQLiteInstance( connection ) ); | ||||||
|  |  | ||||||
|  | 	sqlite3_close( connection ); | ||||||
|  | 	return SQLiteInstancePtr( ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | SQLiteInstance::SQLiteInstance( sqlite3 * connection ): | ||||||
|  | 	m_connection( connection ) | ||||||
|  | { } | ||||||
|  |  | ||||||
|  | SQLiteInstance::~SQLiteInstance( ) | ||||||
|  | { | ||||||
|  | 	int result = sqlite3_close( m_connection ); | ||||||
|  | 	on_sqlite_error( m_connection, result ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | SQLiteStatementPtr SQLiteInstance::prepare( std::string const & sql_text ) | ||||||
|  | { | ||||||
|  | 	sqlite3_stmt * statement; | ||||||
|  | 	int result = sqlite3_prepare_v2( m_connection, sql_text.data(), static_cast<int>( sql_text.size()), &statement, nullptr ); | ||||||
|  | 	 | ||||||
|  | 	on_sqlite_error( m_connection, result ); | ||||||
|  |  | ||||||
|  | 	if ( result == SQLITE_OK ) | ||||||
|  | 		return SQLiteStatementPtr( new SQLiteStatement( *this, statement ) ); | ||||||
|  | 	sqlite3_finalize( statement ); | ||||||
|  | 	return SQLiteStatementPtr( ); | ||||||
|  | } | ||||||
							
								
								
									
										99
									
								
								lobby/SQLiteConnection.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								lobby/SQLiteConnection.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | |||||||
|  | /* | ||||||
|  |  * SQLiteConnection.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 | ||||||
|  |  | ||||||
|  | typedef struct sqlite3 sqlite3; | ||||||
|  | typedef struct sqlite3_stmt sqlite3_stmt; | ||||||
|  |  | ||||||
|  | class SQLiteInstance; | ||||||
|  | class SQLiteStatement; | ||||||
|  |  | ||||||
|  | using SQLiteInstancePtr = std::unique_ptr< SQLiteInstance >; | ||||||
|  | using SQLiteStatementPtr = std::unique_ptr< SQLiteStatement >; | ||||||
|  |  | ||||||
|  | class SQLiteStatement : boost::noncopyable | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	friend class SQLiteInstance; | ||||||
|  |  | ||||||
|  | 	bool execute( ); | ||||||
|  | 	void reset( ); | ||||||
|  | 	void clear( ); | ||||||
|  |  | ||||||
|  | 	~SQLiteStatement(); | ||||||
|  |  | ||||||
|  | 	template<typename ... Args > | ||||||
|  | 	void setBinds( Args const & ... args ) | ||||||
|  | 	{ | ||||||
|  | 		setBindSingle( 1, args... ); // The leftmost SQL parameter has an index of 1 | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	template<typename ... Args > | ||||||
|  | 	void getColumns( Args & ... args ) | ||||||
|  | 	{ | ||||||
|  | 		getColumnSingle( 0, args... ); // The leftmost column of the result set has the index 0 | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | private: | ||||||
|  | 	void setBindSingle( size_t index, double const & value ); | ||||||
|  | 	void setBindSingle( size_t index, uint8_t const & value ); | ||||||
|  | 	void setBindSingle( size_t index, uint16_t const & value ); | ||||||
|  | 	void setBindSingle( size_t index, uint32_t const & value ); | ||||||
|  | 	void setBindSingle( size_t index, int32_t const & value ); | ||||||
|  | 	void setBindSingle( size_t index, int64_t const & value ); | ||||||
|  | 	void setBindSingle( size_t index, std::string const & value ); | ||||||
|  | 	void setBindSingle( size_t index, char const * value ); | ||||||
|  |  | ||||||
|  | 	void getColumnSingle( size_t index, double & value ); | ||||||
|  | 	void getColumnSingle( size_t index, uint8_t & value ); | ||||||
|  | 	void getColumnSingle( size_t index, uint16_t & value ); | ||||||
|  | 	void getColumnSingle( size_t index, uint32_t & value ); | ||||||
|  | 	void getColumnSingle( size_t index, int32_t & value ); | ||||||
|  | 	void getColumnSingle( size_t index, int64_t & value ); | ||||||
|  | 	void getColumnSingle( size_t index, std::string & value ); | ||||||
|  |  | ||||||
|  | 	SQLiteStatement( SQLiteInstance & instance, sqlite3_stmt * statement ); | ||||||
|  |  | ||||||
|  | 	template<typename T, typename ... Args > | ||||||
|  | 	void setBindSingle( size_t index, T const & arg, Args const & ... args ) | ||||||
|  | 	{ | ||||||
|  | 		setBindSingle( index, arg ); | ||||||
|  | 		setBindSingle( index + 1, args... ); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	template<typename T, typename ... Args > | ||||||
|  | 	void getColumnSingle( size_t index, T & arg, Args & ... args ) | ||||||
|  | 	{ | ||||||
|  | 		getColumnSingle( index, arg ); | ||||||
|  | 		getColumnSingle( index + 1, args... ); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void getColumnBlob(size_t index, std::byte * value, size_t capacity); | ||||||
|  |  | ||||||
|  | 	SQLiteInstance & m_instance; | ||||||
|  | 	sqlite3_stmt * m_statement; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | class SQLiteInstance : boost::noncopyable | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	friend class SQLiteStatement; | ||||||
|  |  | ||||||
|  | 	static SQLiteInstancePtr open(std::string const & db_path, bool allow_write ); | ||||||
|  |  | ||||||
|  | 	~SQLiteInstance( ); | ||||||
|  |  | ||||||
|  | 	SQLiteStatementPtr prepare( std::string const & statement ); | ||||||
|  |  | ||||||
|  | private: | ||||||
|  | 	SQLiteInstance( sqlite3 * connection ); | ||||||
|  |  | ||||||
|  | 	sqlite3 * m_connection; | ||||||
|  | }; | ||||||
							
								
								
									
										2
									
								
								lobby/StdInc.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								lobby/StdInc.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | |||||||
|  | // Creates the precompiled header | ||||||
|  | #include "StdInc.h" | ||||||
							
								
								
									
										14
									
								
								lobby/StdInc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								lobby/StdInc.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | /* | ||||||
|  |  * StdInc.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 "../Global.h" | ||||||
|  |  | ||||||
|  | VCMI_LIB_USING_NAMESPACE | ||||||
		Reference in New Issue
	
	Block a user