Added support for configuring which language channels are visible to
player in lobby
							
								
								
									
										
											BIN
										
									
								
								Mods/vcmi/Content/Sprites/lobby/addChannel.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 131 B | 
							
								
								
									
										
											BIN
										
									
								
								Mods/vcmi/Content/Sprites/lobby/closeChannel.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 165 B | 
							
								
								
									
										
											BIN
										
									
								
								Mods/vcmi/Content/Sprites2x/lobby/addChannel.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 139 B | 
							
								
								
									
										
											BIN
										
									
								
								Mods/vcmi/Content/Sprites2x/lobby/closeChannel.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 219 B | 
							
								
								
									
										
											BIN
										
									
								
								Mods/vcmi/Content/Sprites2x/lobby/iconPlayer.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 356 B | 
							
								
								
									
										
											BIN
										
									
								
								Mods/vcmi/Content/Sprites3x/lobby/addChannel.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 146 B | 
							
								
								
									
										
											BIN
										
									
								
								Mods/vcmi/Content/Sprites3x/lobby/closeChannel.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 290 B | 
							
								
								
									
										
											BIN
										
									
								
								Mods/vcmi/Content/Sprites3x/lobby/iconPlayer.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 481 B | 
							
								
								
									
										
											BIN
										
									
								
								Mods/vcmi/Content/Sprites4x/lobby/addChannel.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 147 B | 
							
								
								
									
										
											BIN
										
									
								
								Mods/vcmi/Content/Sprites4x/lobby/closeChannel.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 303 B | 
							
								
								
									
										
											BIN
										
									
								
								Mods/vcmi/Content/Sprites4x/lobby/iconPlayer.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 592 B | 
| @@ -199,6 +199,7 @@ | ||||
| 	"vcmi.lobby.preview.error.invite" : "You were not invited to this room.", | ||||
| 	"vcmi.lobby.preview.error.mods" : "You are using different set of mods.", | ||||
| 	"vcmi.lobby.preview.error.version" : "You are using different version of VCMI.", | ||||
| 	"vcmi.lobby.channel.add" : "Add Channel", | ||||
| 	"vcmi.lobby.room.new" : "New Game", | ||||
| 	"vcmi.lobby.room.load" : "Load Game", | ||||
| 	"vcmi.lobby.room.type" : "Room Type", | ||||
|   | ||||
| @@ -199,6 +199,7 @@ | ||||
| 	"vcmi.lobby.preview.error.invite" : "Ви не були запрошені до цієї кімнати.", | ||||
| 	"vcmi.lobby.preview.error.mods" : "Ви використовуєте інший набір модифікацій.", | ||||
| 	"vcmi.lobby.preview.error.version" : "Ви використовуєте іншу версію VCMI.", | ||||
| 	"vcmi.lobby.channel.add" : "Додати канал чату", | ||||
| 	"vcmi.lobby.room.new" : "Нова гра", | ||||
| 	"vcmi.lobby.room.load" : "Завантажити гру", | ||||
| 	"vcmi.lobby.room.type" : "Тип кімнати", | ||||
|   | ||||
| @@ -109,6 +109,7 @@ set(vcmiclientcommon_SRCS | ||||
| 	renderSDL/ScreenHandler.cpp | ||||
| 	renderSDL/SDL_Extensions.cpp | ||||
|  | ||||
| 	globalLobby/GlobalLobbyAddChannelWindow.cpp | ||||
| 	globalLobby/GlobalLobbyClient.cpp | ||||
| 	globalLobby/GlobalLobbyInviteWindow.cpp | ||||
| 	globalLobby/GlobalLobbyLoginWindow.cpp | ||||
| @@ -322,6 +323,7 @@ set(vcmiclientcommon_HEADERS | ||||
|  | ||||
| 	globalLobby/GlobalLobbyClient.h | ||||
| 	globalLobby/GlobalLobbyDefines.h | ||||
| 	globalLobby/GlobalLobbyAddChannelWindow.h | ||||
| 	globalLobby/GlobalLobbyInviteWindow.h | ||||
| 	globalLobby/GlobalLobbyLoginWindow.h | ||||
| 	globalLobby/GlobalLobbyRoomWindow.h | ||||
|   | ||||
							
								
								
									
										86
									
								
								client/globalLobby/GlobalLobbyAddChannelWindow.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,86 @@ | ||||
| /* | ||||
|  * GlobalLobbyAddChannelWindow.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 "GlobalLobbyAddChannelWindow.h" | ||||
|  | ||||
| #include "GlobalLobbyClient.h" | ||||
|  | ||||
| #include "../CServerHandler.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../gui/WindowHandler.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/GraphicalPrimitiveCanvas.h" | ||||
| #include "../widgets/Images.h" | ||||
| #include "../widgets/ObjectLists.h" | ||||
| #include "../widgets/TextControls.h" | ||||
|  | ||||
| #include "../../lib/texts/MetaString.h" | ||||
| #include "../../lib/texts/Languages.h" | ||||
|  | ||||
| GlobalLobbyAddChannelWindowCard::GlobalLobbyAddChannelWindowCard(const std::string & languageID) | ||||
| 	: languageID(languageID) | ||||
| { | ||||
| 	pos.w = 200; | ||||
| 	pos.h = 40; | ||||
| 	addUsedEvents(LCLICK); | ||||
|  | ||||
| 	OBJECT_CONSTRUCTION; | ||||
| 	const auto & language = Languages::getLanguageOptions(languageID); | ||||
|  | ||||
| 	backgroundOverlay = std::make_shared<TransparentFilledRectangle>(Rect(0, 0, pos.w, pos.h), ColorRGBA(0, 0, 0, 128), ColorRGBA(64, 64, 64, 64), 1); | ||||
| 	labelNameNative = std::make_shared<CLabel>(5, 10, FONT_SMALL, ETextAlignment::CENTERLEFT, Colors::WHITE, language.nameNative); | ||||
|  | ||||
| 	if (language.nameNative != language.nameEnglish) | ||||
| 		labelNameTranslated = std::make_shared<CLabel>(5, 30, FONT_SMALL, ETextAlignment::CENTERLEFT, Colors::WHITE, language.nameEnglish); | ||||
| } | ||||
|  | ||||
| void GlobalLobbyAddChannelWindowCard::clickPressed(const Point & cursorPosition) | ||||
| { | ||||
| 	CSH->getGlobalLobby().addChannel(languageID); | ||||
| 	GH.windows().popWindows(1); | ||||
| } | ||||
|  | ||||
| GlobalLobbyAddChannelWindow::GlobalLobbyAddChannelWindow() | ||||
| 	: CWindowObject(BORDERED) | ||||
| { | ||||
| 	OBJECT_CONSTRUCTION; | ||||
|  | ||||
| 	pos.w = 236; | ||||
| 	pos.h = 420; | ||||
|  | ||||
| 	filledBackground = std::make_shared<FilledTexturePlayerColored>(Rect(0, 0, pos.w, pos.h)); | ||||
| 	filledBackground->setPlayerColor(PlayerColor(1)); | ||||
| 	labelTitle = std::make_shared<CLabel>( | ||||
| 		pos.w / 2, 20, FONT_BIG, ETextAlignment::CENTER, Colors::YELLOW, MetaString::createFromTextID("vcmi.lobby.channel.add").toString() | ||||
| 		); | ||||
|  | ||||
| 	const auto & allLanguages = Languages::getLanguageList(); | ||||
| 	std::vector<std::string> newLanguages; | ||||
| 	for (const auto & language : allLanguages) | ||||
| 		if (!vstd::contains(CSH->getGlobalLobby().getActiveChannels(), language.identifier)) | ||||
| 			newLanguages.push_back(language.identifier); | ||||
|  | ||||
| 	const auto & createChannelCardCallback = [newLanguages](size_t index) -> std::shared_ptr<CIntObject> | ||||
| 	{ | ||||
| 		if(index < newLanguages.size()) | ||||
| 			return std::make_shared<GlobalLobbyAddChannelWindowCard>(newLanguages[index]); | ||||
| 		return std::make_shared<CIntObject>(); | ||||
| 	}; | ||||
|  | ||||
| 	listBackground = std::make_shared<TransparentFilledRectangle>(Rect(8, 48, 220, 324), ColorRGBA(0, 0, 0, 64), ColorRGBA(64, 80, 128, 255), 1); | ||||
| 	languageList = std::make_shared<CListBox>(createChannelCardCallback, Point(10, 50), Point(0, 40), 8, newLanguages.size(), 0, 1 | 4, Rect(200, 0, 320, 320)); | ||||
| 	languageList->setRedrawParent(true); | ||||
|  | ||||
| 	buttonClose = std::make_shared<CButton>(Point(86, 384), AnimationPath::builtin("MuBcanc"), CButton::tooltip(), [this]() { close(); }, EShortcut::GLOBAL_RETURN ); | ||||
|  | ||||
| 	center(); | ||||
| } | ||||
							
								
								
									
										46
									
								
								client/globalLobby/GlobalLobbyAddChannelWindow.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,46 @@ | ||||
| /* | ||||
|  * GlobalLobbyInviteWindow.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 "GlobalLobbyObserver.h" | ||||
|  | ||||
| #include "../windows/CWindowObject.h" | ||||
|  | ||||
| class CLabel; | ||||
| class FilledTexturePlayerColored; | ||||
| class TransparentFilledRectangle; | ||||
| class CListBox; | ||||
| class CButton; | ||||
| struct GlobalLobbyAccount; | ||||
|  | ||||
| class GlobalLobbyAddChannelWindow final : public CWindowObject | ||||
| { | ||||
| 	std::shared_ptr<FilledTexturePlayerColored> filledBackground; | ||||
| 	std::shared_ptr<CLabel> labelTitle; | ||||
| 	std::shared_ptr<CListBox> languageList; | ||||
| 	std::shared_ptr<TransparentFilledRectangle> listBackground; | ||||
| 	std::shared_ptr<CButton> buttonClose; | ||||
|  | ||||
| public: | ||||
| 	GlobalLobbyAddChannelWindow(); | ||||
| }; | ||||
|  | ||||
| class GlobalLobbyAddChannelWindowCard : public CIntObject | ||||
| { | ||||
| 	std::string languageID; | ||||
|  | ||||
| 	std::shared_ptr<TransparentFilledRectangle> backgroundOverlay; | ||||
| 	std::shared_ptr<CLabel> labelNameNative; | ||||
| 	std::shared_ptr<CLabel> labelNameTranslated; | ||||
|  | ||||
| 	void clickPressed(const Point & cursorPosition) override; | ||||
| public: | ||||
| 	GlobalLobbyAddChannelWindowCard(const std::string & languageID); | ||||
| }; | ||||
| @@ -32,9 +32,54 @@ | ||||
|  | ||||
| GlobalLobbyClient::GlobalLobbyClient() | ||||
| { | ||||
| 	activeChannels.emplace_back("english"); | ||||
| 	if (CGI->generaltexth->getPreferredLanguage() != "english") | ||||
| 		activeChannels.emplace_back(CGI->generaltexth->getPreferredLanguage()); | ||||
| 	auto customChannels = settings["lobby"]["languageRooms"].convertTo<std::vector<std::string>>(); | ||||
|  | ||||
| 	if (customChannels.empty()) | ||||
| 	{ | ||||
| 		activeChannels.emplace_back("english"); | ||||
| 		if (CGI->generaltexth->getPreferredLanguage() != "english") | ||||
| 			activeChannels.emplace_back(CGI->generaltexth->getPreferredLanguage()); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		activeChannels = customChannels; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void GlobalLobbyClient::addChannel(const std::string & channel) | ||||
| { | ||||
| 	activeChannels.emplace_back(channel); | ||||
|  | ||||
| 	auto lobbyWindowPtr = lobbyWindow.lock(); | ||||
| 	if(lobbyWindowPtr) | ||||
| 		lobbyWindowPtr->refreshActiveChannels(); | ||||
|  | ||||
| 	JsonNode toSend; | ||||
| 	toSend["type"].String() = "requestChatHistory"; | ||||
| 	toSend["channelType"].String() = "global"; | ||||
| 	toSend["channelName"].String() = channel; | ||||
| 	CSH->getGlobalLobby().sendMessage(toSend); | ||||
|  | ||||
| 	Settings languageRooms = settings.write["lobby"]["languageRooms"]; | ||||
|  | ||||
| 	languageRooms->Vector().clear(); | ||||
| 	for (const auto & lang : activeChannels) | ||||
| 		languageRooms->Vector().push_back(JsonNode(lang)); | ||||
| } | ||||
|  | ||||
| void GlobalLobbyClient::closeChannel(const std::string & channel) | ||||
| { | ||||
| 	vstd::erase(activeChannels, channel); | ||||
|  | ||||
| 	auto lobbyWindowPtr = lobbyWindow.lock(); | ||||
| 	if(lobbyWindowPtr) | ||||
| 		lobbyWindowPtr->refreshActiveChannels(); | ||||
|  | ||||
| 	Settings languageRooms = settings.write["lobby"]["languageRooms"]; | ||||
|  | ||||
| 	languageRooms->Vector().clear(); | ||||
| 	for (const auto & lang : activeChannels) | ||||
| 		languageRooms->Vector().push_back(JsonNode(lang)); | ||||
| } | ||||
|  | ||||
| GlobalLobbyClient::~GlobalLobbyClient() = default; | ||||
| @@ -347,6 +392,10 @@ void GlobalLobbyClient::sendClientLogin() | ||||
| 	toSend["accountCookie"].String() = getAccountCookie(); | ||||
| 	toSend["language"].String() = CGI->generaltexth->getPreferredLanguage(); | ||||
| 	toSend["version"].String() = VCMI_VERSION_STRING; | ||||
|  | ||||
| 	for (const auto & language : activeChannels) | ||||
| 		toSend["languageRooms"].Vector().push_back(JsonNode(language)); | ||||
|  | ||||
| 	sendMessage(toSend); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -92,6 +92,8 @@ public: | ||||
| 	void sendClientRegister(const std::string & accountName); | ||||
| 	void sendClientLogin(); | ||||
| 	void sendOpenRoom(const std::string & mode, int playerLimit); | ||||
| 	void addChannel(const std::string & channel); | ||||
| 	void closeChannel(const std::string & channel); | ||||
|  | ||||
| 	void sendProxyConnectionLogin(const NetworkConnectionPtr & netConnection); | ||||
| 	void resetMatchState(); | ||||
|   | ||||
| @@ -11,9 +11,10 @@ | ||||
| #include "StdInc.h" | ||||
| #include "GlobalLobbyWidget.h" | ||||
|  | ||||
| #include "GlobalLobbyAddChannelWindow.h" | ||||
| #include "GlobalLobbyClient.h" | ||||
| #include "GlobalLobbyWindow.h" | ||||
| #include "GlobalLobbyRoomWindow.h" | ||||
| #include "GlobalLobbyWindow.h" | ||||
|  | ||||
| #include "../CGameInfo.h" | ||||
| #include "../CServerHandler.h" | ||||
| @@ -72,6 +73,18 @@ GlobalLobbyWidget::CreateFunc GlobalLobbyWidget::getItemListConstructorFunc(cons | ||||
|  | ||||
| 		if(index < channels.size()) | ||||
| 			return std::make_shared<GlobalLobbyChannelCard>(this->window, channels[index]); | ||||
|  | ||||
| 		if(index == channels.size()) | ||||
| 		{ | ||||
| 			const auto buttonCallback = [](){ | ||||
| 				GH.windows().createAndPushWindow<GlobalLobbyAddChannelWindow>(); | ||||
| 			}; | ||||
|  | ||||
| 			auto result = std::make_shared<CButton>(Point(0,0), AnimationPath::builtin("lobbyAddChannel"), CButton::tooltip(), buttonCallback); | ||||
| 			result->setOverlay(std::make_shared<CPicture>(ImagePath::builtin("lobby/addChannel"))); | ||||
| 			return result; | ||||
| 		} | ||||
|  | ||||
| 		return std::make_shared<CIntObject>(); | ||||
| 	}; | ||||
|  | ||||
| @@ -255,6 +268,13 @@ GlobalLobbyChannelCard::GlobalLobbyChannelCard(GlobalLobbyWindow * window, const | ||||
| { | ||||
| 	OBJECT_CONSTRUCTION; | ||||
| 	labelName = std::make_shared<CLabel>(5, 20, FONT_SMALL, ETextAlignment::CENTERLEFT, Colors::WHITE, Languages::getLanguageOptions(channelName).nameNative); | ||||
|  | ||||
| 	if (CSH->getGlobalLobby().getActiveChannels().size() > 1) | ||||
| 	{ | ||||
| 		pos.w = 110; | ||||
| 		buttonClose = std::make_shared<CButton>(Point(113, 7), AnimationPath::builtin("lobbyCloseChannel"), CButton::tooltip(), [channelName](){CSH->getGlobalLobby().closeChannel(channelName);}); | ||||
| 		buttonClose->setOverlay(std::make_shared<CPicture>(ImagePath::builtin("lobby/closeChannel"))); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| GlobalLobbyMatchCard::GlobalLobbyMatchCard(GlobalLobbyWindow * window, const GlobalLobbyRoom & matchDescription) | ||||
|   | ||||
| @@ -77,7 +77,6 @@ class GlobalLobbyRoomCard : public CIntObject | ||||
| 	std::shared_ptr<CLabel> labelRoomSize; | ||||
| 	std::shared_ptr<CLabel> labelRoomStatus; | ||||
| 	std::shared_ptr<CLabel> labelDescription; | ||||
| 	std::shared_ptr<CButton> buttonJoin; | ||||
| 	std::shared_ptr<CPicture> iconRoomSize; | ||||
|  | ||||
| 	void clickPressed(const Point & cursorPosition) override; | ||||
| @@ -88,6 +87,7 @@ public: | ||||
| class GlobalLobbyChannelCard : public GlobalLobbyChannelCardBase | ||||
| { | ||||
| 	std::shared_ptr<CLabel> labelName; | ||||
| 	std::shared_ptr<CButton> buttonClose; | ||||
|  | ||||
| public: | ||||
| 	GlobalLobbyChannelCard(GlobalLobbyWindow * window, const std::string & channelName); | ||||
|   | ||||
| @@ -39,6 +39,7 @@ GlobalLobbyWindow::GlobalLobbyWindow() | ||||
| 	doOpenChannel("global", "english", Languages::getLanguageOptions("english").nameNative); | ||||
|  | ||||
| 	widget->getChannelListHeader()->setText(MetaString::createFromTextID("vcmi.lobby.header.channels").toString()); | ||||
| 	widget->getChannelList()->resize(CSH->getGlobalLobby().getActiveChannels().size()+1); | ||||
| } | ||||
|  | ||||
| bool GlobalLobbyWindow::isChannelOpen(const std::string & testChannelType, const std::string & testChannelName) const | ||||
| @@ -182,6 +183,21 @@ void GlobalLobbyWindow::onMatchesHistory(const std::vector<GlobalLobbyRoom> & hi | ||||
| 	widget->getMatchListHeader()->setText(text.toString()); | ||||
| } | ||||
|  | ||||
| void GlobalLobbyWindow::refreshActiveChannels() | ||||
| { | ||||
| 	const auto & activeChannels = CSH->getGlobalLobby().getActiveChannels(); | ||||
|  | ||||
| 	if (activeChannels.size()+1 == widget->getChannelList()->size()) | ||||
| 		widget->getChannelList()->reset(); | ||||
| 	else | ||||
| 		widget->getChannelList()->resize(activeChannels.size()+1); | ||||
|  | ||||
| 	if (currentChannelType == "global" && !vstd::contains(activeChannels, currentChannelName) && !activeChannels.empty()) | ||||
| 	{ | ||||
| 		doOpenChannel("global", activeChannels.front(), Languages::getLanguageOptions(activeChannels.front()).nameNative); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void GlobalLobbyWindow::onInviteReceived(const std::string & invitedRoomID) | ||||
| { | ||||
| 	widget->getRoomList()->reset(); | ||||
|   | ||||
| @@ -45,6 +45,7 @@ public: | ||||
|  | ||||
| 	void onGameChatMessage(const std::string & sender, const std::string & message, const std::string & when, const std::string & channelType, const std::string & channelName); | ||||
| 	void refreshChatText(); | ||||
| 	void refreshActiveChannels(); | ||||
| 	void onActiveAccounts(const std::vector<GlobalLobbyAccount> & accounts) override; | ||||
| 	void onActiveGameRooms(const std::vector<GlobalLobbyRoom> & rooms) override; | ||||
| 	void onMatchesHistory(const std::vector<GlobalLobbyRoom> & history); | ||||
|   | ||||
| @@ -127,27 +127,29 @@ size_t CTrueTypeFont::getStringWidthScaled(const std::string & text) const | ||||
|  | ||||
| void CTrueTypeFont::renderText(SDL_Surface * surface, const std::string & data, const ColorRGBA & color, const Point & pos) const | ||||
| { | ||||
| 	if (color.r != 0 && color.g != 0 && color.b != 0) // not black - add shadow | ||||
| 	{ | ||||
| 		if (outline) | ||||
| 			renderText(surface, data, Colors::BLACK, pos - Point(1,1) * getScalingFactor()); | ||||
| 	if (data.empty()) | ||||
| 		return; | ||||
|  | ||||
| 		if (dropShadow || outline) | ||||
| 			renderText(surface, data, Colors::BLACK, pos + Point(1,1) * getScalingFactor()); | ||||
| 	} | ||||
| 	if (outline) | ||||
| 		renderTextImpl(surface, data, Colors::BLACK, pos - Point(1,1) * getScalingFactor()); | ||||
|  | ||||
| 	if (!data.empty()) | ||||
| 	{ | ||||
| 		SDL_Surface * rendered; | ||||
| 		if (blended) | ||||
| 			rendered = TTF_RenderUTF8_Blended(font.get(), data.c_str(), CSDL_Ext::toSDL(color)); | ||||
| 		else | ||||
| 			rendered = TTF_RenderUTF8_Solid(font.get(), data.c_str(), CSDL_Ext::toSDL(color)); | ||||
| 	if (dropShadow || outline) | ||||
| 		renderTextImpl(surface, data, Colors::BLACK, pos + Point(1,1) * getScalingFactor()); | ||||
|  | ||||
| 		assert(rendered); | ||||
|  | ||||
| 		CSDL_Ext::blitSurface(rendered, surface, pos); | ||||
| 		SDL_FreeSurface(rendered); | ||||
| 	} | ||||
| 	renderTextImpl(surface, data, color, pos); | ||||
| } | ||||
|  | ||||
| void CTrueTypeFont::renderTextImpl(SDL_Surface * surface, const std::string & data, const ColorRGBA & color, const Point & pos) const | ||||
| { | ||||
| 	SDL_Surface * rendered; | ||||
| 	if (blended) | ||||
| 		rendered = TTF_RenderUTF8_Blended(font.get(), data.c_str(), CSDL_Ext::toSDL(color)); | ||||
| 	else | ||||
| 		rendered = TTF_RenderUTF8_Solid(font.get(), data.c_str(), CSDL_Ext::toSDL(color)); | ||||
|  | ||||
| 	assert(rendered); | ||||
|  | ||||
| 	CSDL_Ext::blitSurface(rendered, surface, pos); | ||||
| 	SDL_FreeSurface(rendered); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -34,6 +34,7 @@ class CTrueTypeFont final : public IFont | ||||
| 	int getFontStyle(const JsonNode & config) const; | ||||
|  | ||||
| 	void renderText(SDL_Surface * surface, const std::string & data, const ColorRGBA & color, const Point & pos) const override; | ||||
| 	void renderTextImpl(SDL_Surface * surface, const std::string & data, const ColorRGBA & color, const Point & pos) const; | ||||
| 	size_t getFontAscentScaled() const override; | ||||
| public: | ||||
| 	CTrueTypeFont(const JsonNode & fontConfig); | ||||
|   | ||||
| @@ -113,24 +113,32 @@ size_t FontChain::getGlyphWidthScaled(const char * data) const | ||||
|  | ||||
| std::vector<FontChain::TextChunk> FontChain::splitTextToChunks(const std::string & data) const | ||||
| { | ||||
| 	// U+FFFD - replacement character (question mark in rhombus) | ||||
| 	static const std::string replacementCharacter = u8"�"; | ||||
|  | ||||
| 	std::vector<TextChunk> chunks; | ||||
|  | ||||
| 	const auto & selectFont = [this](const char * characterPtr) -> const IFont * | ||||
| 	{ | ||||
| 		for(const auto & font : chain) | ||||
| 			if (font->canRepresentCharacter(characterPtr)) | ||||
| 				return font.get(); | ||||
| 		return nullptr; | ||||
| 	}; | ||||
|  | ||||
| 	for (size_t i = 0; i < data.size(); i += TextOperations::getUnicodeCharacterSize(data[i])) | ||||
| 	{ | ||||
| 		const IFont * currentFont = nullptr; | ||||
| 		for(const auto & font : chain) | ||||
| 		std::string symbol = data.substr(i, TextOperations::getUnicodeCharacterSize(data[i])); | ||||
| 		const IFont * currentFont = selectFont(symbol.data()); | ||||
|  | ||||
| 		if (currentFont == nullptr) | ||||
| 		{ | ||||
| 			if (font->canRepresentCharacter(data.data() + i)) | ||||
| 			{ | ||||
| 				currentFont = font.get(); | ||||
| 				break; | ||||
| 			} | ||||
| 			symbol = replacementCharacter; | ||||
| 			currentFont = selectFont(symbol.data()); | ||||
| 		} | ||||
|  | ||||
| 		if (currentFont == nullptr) | ||||
| 			continue; // not representable | ||||
|  | ||||
| 		std::string symbol = data.substr(i, TextOperations::getUnicodeCharacterSize(data[i])); | ||||
| 			continue; // Still nothing - neither desired character nor fallback can be rendered | ||||
|  | ||||
| 		if (chunks.empty() || chunks.back().font != currentFont) | ||||
| 			chunks.push_back({currentFont, symbol}); | ||||
|   | ||||
| @@ -32,6 +32,12 @@ | ||||
| 		{ | ||||
| 			"type" : "string", | ||||
| 			"description" : "Version of client, e.g. 1.5.0" | ||||
| 		}, | ||||
| 		"languageRooms" : | ||||
| 		{ | ||||
| 			"type" : "array", | ||||
| 			"items" : { "type" : "string" }, | ||||
| 			"description" : "(since 1.6.4) List of language rooms for which player wants to receive chat history" | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -673,7 +673,7 @@ | ||||
| 			"type" : "object", | ||||
| 			"additionalProperties" : false, | ||||
| 			"default" : {}, | ||||
| 			"required" : [ "mapPreview", "hostname", "port", "roomPlayerLimit", "roomType", "roomMode" ], | ||||
| 			"required" : [ "mapPreview", "hostname", "port", "roomPlayerLimit", "roomType", "roomMode", "languageRooms" ], | ||||
| 			"properties" : { | ||||
| 				"mapPreview" : { | ||||
| 					"type" : "boolean", | ||||
| @@ -698,6 +698,10 @@ | ||||
| 				"roomMode" : { | ||||
| 					"type" : "number", | ||||
| 					"default" : 0 | ||||
| 				}, | ||||
| 				"languageRooms" : { | ||||
| 					"type" : "array", | ||||
| 					"default" : [] | ||||
| 				} | ||||
| 			} | ||||
| 		}, | ||||
|   | ||||
							
								
								
									
										118
									
								
								config/widgets/buttons/lobbyAddChannel.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,118 @@ | ||||
| { | ||||
| 	"normal" : { | ||||
| 		"width": 146, | ||||
| 		"height": 40, | ||||
| 		"items" : [ | ||||
| 			{ | ||||
| 				"type": "texture", | ||||
| 				"image": "DiBoxBck", | ||||
| 				"color" : "blue", | ||||
| 				"rect": {"x": 0, "y": 0, "w": 146, "h": 40} | ||||
| 			}, | ||||
| 			{ | ||||
| 				"type": "graphicalPrimitive", | ||||
| 				"rect": {"x": 0, "y": 0, "w": 146, "h": 40}, | ||||
| 				"primitives" : [ | ||||
| 					{ "type" : "filledBox", "a" : { "x" : 2, "y" : 2}, "b" : { "x" : -3, "y" : -3}, "color" : [ 0, 0, 0, 128 ] }, | ||||
| 				 | ||||
| 					{ "type" : "line", "a" : { "x" : 0, "y" : 0}, "b" : { "x" : 0, "y" : -1}, "color" : [ 255, 255, 255, 64 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : 0, "y" : 0}, "b" : { "x" : -1, "y" : 0}, "color" : [ 255, 255, 255, 128 ] }, | ||||
|  | ||||
| 					{ "type" : "line", "a" : { "x" : 1, "y" : 1}, "b" : { "x" : 1, "y" : -2}, "color" : [ 255, 255, 255, 80 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : 1, "y" : 1}, "b" : { "x" : -2, "y" : 1}, "color" : [ 255, 255, 255, 160 ] }, | ||||
|  | ||||
| 					{ "type" : "line", "a" : { "x" : 1, "y" : -2}, "b" : { "x" : -2, "y" : -2}, "color" : [ 0, 0, 0, 192 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : -2, "y" : 1}, "b" : { "x" : -2, "y" : -2}, "color" : [ 0, 0, 0, 192 ] }, | ||||
| 					 | ||||
| 					{ "type" : "line", "a" : { "x" : 0, "y" : -1}, "b" : { "x" : -1, "y" : -1}, "color" : [ 0, 0, 0, 255 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : -1, "y" : 0}, "b" : { "x" : -1, "y" : -1}, "color" : [ 0, 0, 0, 255 ] }, | ||||
| 				] | ||||
| 			} | ||||
| 		] | ||||
| 	}, | ||||
| 	"pressed" : { | ||||
| 		"width": 146, | ||||
| 		"height": 40, | ||||
| 		"items" : [ | ||||
| 			{ | ||||
| 				"type": "texture", | ||||
| 				"image": "DiBoxBck", | ||||
| 				"color" : "blue", | ||||
| 				"rect": {"x": 1, "y": 1, "w": 145, "h": 39} | ||||
| 			}, | ||||
| 			{ | ||||
| 				"type": "graphicalPrimitive", | ||||
| 				"rect": {"x": 0, "y": 0, "w": 146, "h": 40}, | ||||
| 				"primitives" : [ | ||||
| 					{ "type" : "filledBox", "a" : { "x" : 3, "y" : 3}, "b" : { "x" : -3, "y" : -3}, "color" : [ 0, 0, 0, 160 ] }, | ||||
| 				 | ||||
| 					{ "type" : "rectangle", "a" : { "x" : 0, "y" : 0}, "b" : { "x" : -1, "y" : -1}, "color" : [ 0, 0, 0, 255 ] }, | ||||
| 					 | ||||
| 					{ "type" : "line", "a" : { "x" : 1, "y" : 1}, "b" : { "x" : 1, "y" : -2}, "color" : [ 255, 255, 255, 48 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : 1, "y" : 1}, "b" : { "x" : -2, "y" : 1}, "color" : [ 255, 255, 255, 96 ] }, | ||||
|  | ||||
| 					{ "type" : "line", "a" : { "x" : 2, "y" : 2}, "b" : { "x" : 2, "y" : -3}, "color" : [ 255, 255, 255, 64 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : 2, "y" : 2}, "b" : { "x" : -3, "y" : 2}, "color" : [ 255, 255, 255, 128 ] }, | ||||
| 				] | ||||
| 			} | ||||
| 		] | ||||
| 	}, | ||||
| 	"blocked" : { | ||||
| 		"width": 146, | ||||
| 		"height": 40, | ||||
| 		"items" : [ | ||||
| 			{ | ||||
| 				"type": "texture", | ||||
| 				"image": "DiBoxBck", | ||||
| 				"color" : "blue", | ||||
| 				"rect": {"x": 0, "y": 0, "w": 146, "h": 40} | ||||
| 			}, | ||||
| 			{ | ||||
| 				"type": "graphicalPrimitive", | ||||
| 				"rect": {"x": 0, "y": 0, "w": 146, "h": 40}, | ||||
| 				"primitives" : [ | ||||
| 					{ "type" : "filledBox", "a" : { "x" : 2, "y" : 2}, "b" : { "x" : -3, "y" : -3}, "color" : [ 0, 0, 0, 128 ] }, | ||||
| 				 | ||||
| 					{ "type" : "line", "a" : { "x" : 0, "y" : 0}, "b" : { "x" : 0, "y" : -1}, "color" : [ 255, 255, 255, 64 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : 0, "y" : 0}, "b" : { "x" : -1, "y" : 0}, "color" : [ 255, 255, 255, 128 ] }, | ||||
|  | ||||
| 					{ "type" : "line", "a" : { "x" : 1, "y" : 1}, "b" : { "x" : 1, "y" : -2}, "color" : [ 255, 255, 255, 80 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : 1, "y" : 1}, "b" : { "x" : -2, "y" : 1}, "color" : [ 255, 255, 255, 160 ] }, | ||||
|  | ||||
| 					{ "type" : "line", "a" : { "x" : 1, "y" : -2}, "b" : { "x" : -2, "y" : -2}, "color" : [ 0, 0, 0, 192 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : -2, "y" : 1}, "b" : { "x" : -2, "y" : -2}, "color" : [ 0, 0, 0, 192 ] }, | ||||
| 					 | ||||
| 					{ "type" : "line", "a" : { "x" : 0, "y" : -1}, "b" : { "x" : -1, "y" : -1}, "color" : [ 0, 0, 0, 255 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : -1, "y" : 0}, "b" : { "x" : -1, "y" : -1}, "color" : [ 0, 0, 0, 255 ] }, | ||||
| 				] | ||||
| 			} | ||||
| 		] | ||||
| 	}, | ||||
| 	"highlighted" : { | ||||
| 		"width": 146, | ||||
| 		"height": 40, | ||||
| 		"items" : [ | ||||
| 			{ | ||||
| 				"type": "texture", | ||||
| 				"image": "DiBoxBck", | ||||
| 				"color" : "blue", | ||||
| 				"rect": {"x": 0, "y": 0, "w": 146, "h": 40} | ||||
| 			}, | ||||
| 			{ | ||||
| 				"type": "graphicalPrimitive", | ||||
| 				"rect": {"x": 0, "y": 0, "w": 146, "h": 40}, | ||||
| 				"primitives" : [ | ||||
| 					{ "type" : "filledBox", "a" : { "x" : 2, "y" : 2}, "b" : { "x" : -3, "y" : -3}, "color" : [ 0, 0, 0, 128 ] }, | ||||
| 				 | ||||
| 					{ "type" : "rectangle", "a" : { "x" : 2, "y" : 2}, "b" : { "x" : -3, "y" : -3}, "color" : [ 255, 255, 255, 255 ] }, | ||||
| 					 | ||||
| 					{ "type" : "line", "a" : { "x" : 1, "y" : -2}, "b" : { "x" : -2, "y" : -2}, "color" : [ 255, 255, 255, 255 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : -2, "y" : 1}, "b" : { "x" : -2, "y" : -2}, "color" : [ 255, 255, 255, 255 ] }, | ||||
| 					 | ||||
| 					{ "type" : "line", "a" : { "x" : 1, "y" : 1}, "b" : { "x" : 1, "y" : -2}, "color" : [ 255, 255, 255, 160 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : 1, "y" : 1}, "b" : { "x" : -2, "y" : 1}, "color" : [ 255, 255, 255, 160 ] }, | ||||
| 				] | ||||
| 			} | ||||
| 		] | ||||
| 	}, | ||||
| } | ||||
							
								
								
									
										118
									
								
								config/widgets/buttons/lobbyCloseChannel.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,118 @@ | ||||
| { | ||||
| 	"normal" : { | ||||
| 		"width": 25, | ||||
| 		"height": 25, | ||||
| 		"items" : [ | ||||
| 			{ | ||||
| 				"type": "texture", | ||||
| 				"image": "DiBoxBck", | ||||
| 				"color" : "blue", | ||||
| 				"rect": {"x": 0, "y": 0, "w": 25, "h": 25} | ||||
| 			}, | ||||
| 			{ | ||||
| 				"type": "graphicalPrimitive", | ||||
| 				"rect": {"x": 0, "y": 0, "w": 25, "h": 25}, | ||||
| 				"primitives" : [ | ||||
| 					{ "type" : "filledBox", "a" : { "x" : 2, "y" : 2}, "b" : { "x" : -3, "y" : -3}, "color" : [ 0, 0, 0, 128 ] }, | ||||
| 				 | ||||
| 					{ "type" : "line", "a" : { "x" : 0, "y" : 0}, "b" : { "x" : 0, "y" : -1}, "color" : [ 255, 255, 255, 64 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : 0, "y" : 0}, "b" : { "x" : -1, "y" : 0}, "color" : [ 255, 255, 255, 128 ] }, | ||||
|  | ||||
| 					{ "type" : "line", "a" : { "x" : 1, "y" : 1}, "b" : { "x" : 1, "y" : -2}, "color" : [ 255, 255, 255, 80 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : 1, "y" : 1}, "b" : { "x" : -2, "y" : 1}, "color" : [ 255, 255, 255, 160 ] }, | ||||
|  | ||||
| 					{ "type" : "line", "a" : { "x" : 1, "y" : -2}, "b" : { "x" : -2, "y" : -2}, "color" : [ 0, 0, 0, 192 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : -2, "y" : 1}, "b" : { "x" : -2, "y" : -2}, "color" : [ 0, 0, 0, 192 ] }, | ||||
| 					 | ||||
| 					{ "type" : "line", "a" : { "x" : 0, "y" : -1}, "b" : { "x" : -1, "y" : -1}, "color" : [ 0, 0, 0, 255 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : -1, "y" : 0}, "b" : { "x" : -1, "y" : -1}, "color" : [ 0, 0, 0, 255 ] }, | ||||
| 				] | ||||
| 			} | ||||
| 		] | ||||
| 	}, | ||||
| 	"pressed" : { | ||||
| 		"width": 25, | ||||
| 		"height": 25, | ||||
| 		"items" : [ | ||||
| 			{ | ||||
| 				"type": "texture", | ||||
| 				"image": "DiBoxBck", | ||||
| 				"color" : "blue", | ||||
| 				"rect": {"x": 1, "y": 1, "w": 24, "h": 24} | ||||
| 			}, | ||||
| 			{ | ||||
| 				"type": "graphicalPrimitive", | ||||
| 				"rect": {"x": 0, "y": 0, "w": 25, "h": 25}, | ||||
| 				"primitives" : [ | ||||
| 					{ "type" : "filledBox", "a" : { "x" : 3, "y" : 3}, "b" : { "x" : -3, "y" : -3}, "color" : [ 0, 0, 0, 160 ] }, | ||||
| 				 | ||||
| 					{ "type" : "rectangle", "a" : { "x" : 0, "y" : 0}, "b" : { "x" : -1, "y" : -1}, "color" : [ 0, 0, 0, 255 ] }, | ||||
| 					 | ||||
| 					{ "type" : "line", "a" : { "x" : 1, "y" : 1}, "b" : { "x" : 1, "y" : -2}, "color" : [ 255, 255, 255, 48 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : 1, "y" : 1}, "b" : { "x" : -2, "y" : 1}, "color" : [ 255, 255, 255, 96 ] }, | ||||
|  | ||||
| 					{ "type" : "line", "a" : { "x" : 2, "y" : 2}, "b" : { "x" : 2, "y" : -3}, "color" : [ 255, 255, 255, 64 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : 2, "y" : 2}, "b" : { "x" : -3, "y" : 2}, "color" : [ 255, 255, 255, 128 ] }, | ||||
| 				] | ||||
| 			} | ||||
| 		] | ||||
| 	}, | ||||
| 	"blocked" : { | ||||
| 		"width": 25, | ||||
| 		"height": 25, | ||||
| 		"items" : [ | ||||
| 			{ | ||||
| 				"type": "texture", | ||||
| 				"image": "DiBoxBck", | ||||
| 				"color" : "blue", | ||||
| 				"rect": {"x": 0, "y": 0, "w": 25, "h": 25} | ||||
| 			}, | ||||
| 			{ | ||||
| 				"type": "graphicalPrimitive", | ||||
| 				"rect": {"x": 0, "y": 0, "w": 25, "h": 25}, | ||||
| 				"primitives" : [ | ||||
| 					{ "type" : "filledBox", "a" : { "x" : 2, "y" : 2}, "b" : { "x" : -3, "y" : -3}, "color" : [ 0, 0, 0, 128 ] }, | ||||
| 				 | ||||
| 					{ "type" : "line", "a" : { "x" : 0, "y" : 0}, "b" : { "x" : 0, "y" : -1}, "color" : [ 255, 255, 255, 64 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : 0, "y" : 0}, "b" : { "x" : -1, "y" : 0}, "color" : [ 255, 255, 255, 128 ] }, | ||||
|  | ||||
| 					{ "type" : "line", "a" : { "x" : 1, "y" : 1}, "b" : { "x" : 1, "y" : -2}, "color" : [ 255, 255, 255, 80 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : 1, "y" : 1}, "b" : { "x" : -2, "y" : 1}, "color" : [ 255, 255, 255, 160 ] }, | ||||
|  | ||||
| 					{ "type" : "line", "a" : { "x" : 1, "y" : -2}, "b" : { "x" : -2, "y" : -2}, "color" : [ 0, 0, 0, 192 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : -2, "y" : 1}, "b" : { "x" : -2, "y" : -2}, "color" : [ 0, 0, 0, 192 ] }, | ||||
| 					 | ||||
| 					{ "type" : "line", "a" : { "x" : 0, "y" : -1}, "b" : { "x" : -1, "y" : -1}, "color" : [ 0, 0, 0, 255 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : -1, "y" : 0}, "b" : { "x" : -1, "y" : -1}, "color" : [ 0, 0, 0, 255 ] }, | ||||
| 				] | ||||
| 			} | ||||
| 		] | ||||
| 	}, | ||||
| 	"highlighted" : { | ||||
| 		"width": 25, | ||||
| 		"height": 25, | ||||
| 		"items" : [ | ||||
| 			{ | ||||
| 				"type": "texture", | ||||
| 				"image": "DiBoxBck", | ||||
| 				"color" : "blue", | ||||
| 				"rect": {"x": 0, "y": 0, "w": 25, "h": 25} | ||||
| 			}, | ||||
| 			{ | ||||
| 				"type": "graphicalPrimitive", | ||||
| 				"rect": {"x": 0, "y": 0, "w": 25, "h": 25}, | ||||
| 				"primitives" : [ | ||||
| 					{ "type" : "filledBox", "a" : { "x" : 2, "y" : 2}, "b" : { "x" : -3, "y" : -3}, "color" : [ 0, 0, 0, 128 ] }, | ||||
| 				 | ||||
| 					{ "type" : "rectangle", "a" : { "x" : 2, "y" : 2}, "b" : { "x" : -3, "y" : -3}, "color" : [ 255, 255, 255, 255 ] }, | ||||
| 					 | ||||
| 					{ "type" : "line", "a" : { "x" : 1, "y" : -2}, "b" : { "x" : -2, "y" : -2}, "color" : [ 255, 255, 255, 255 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : -2, "y" : 1}, "b" : { "x" : -2, "y" : -2}, "color" : [ 255, 255, 255, 255 ] }, | ||||
| 					 | ||||
| 					{ "type" : "line", "a" : { "x" : 1, "y" : 1}, "b" : { "x" : 1, "y" : -2}, "color" : [ 255, 255, 255, 160 ] }, | ||||
| 					{ "type" : "line", "a" : { "x" : 1, "y" : 1}, "b" : { "x" : -2, "y" : 1}, "color" : [ 255, 255, 255, 160 ] }, | ||||
| 				] | ||||
| 			} | ||||
| 		] | ||||
| 	}, | ||||
| } | ||||
| @@ -69,7 +69,7 @@ | ||||
| 		 | ||||
| 		{ | ||||
| 			"type": "areaFilled", | ||||
| 			"rect": {"x": 270, "y": 50, "w": 150, "h": 140} | ||||
| 			"rect": {"x": 270, "y": 50, "w": 150, "h": 180} | ||||
| 		}, | ||||
| 		{ | ||||
| 			"name" : "headerChannelList", | ||||
| @@ -82,27 +82,27 @@ | ||||
| 			"itemType" : "channel", | ||||
| 			"position" : { "x" : 272, "y" : 68 }, | ||||
| 			"itemOffset" : { "x" : 0, "y" : 40 }, | ||||
| 			"visibleAmount" : 3 | ||||
| 			"visibleAmount" : 4 | ||||
| 		}, | ||||
| 		 | ||||
| 		{ | ||||
| 			"type": "areaFilled", | ||||
| 			"rect": {"x": 270, "y": 210, "w": 150, "h": 380} | ||||
| 			"rect": {"x": 270, "y": 250, "w": 150, "h": 340} | ||||
| 		}, | ||||
| 		{ | ||||
| 			"name" : "headerMatchList", | ||||
| 			"type": "labelTitle", | ||||
| 			"position": {"x": 280, "y": 213} | ||||
| 			"position": {"x": 280, "y": 253} | ||||
| 		}, | ||||
| 		{ | ||||
| 			"type" : "lobbyItemList", | ||||
| 			"name" : "matchList", | ||||
| 			"itemType" : "match", | ||||
| 			"position" : { "x" : 272, "y" : 228 }, | ||||
| 			"position" : { "x" : 272, "y" : 268 }, | ||||
| 			"itemOffset" : { "x" : 0, "y" : 40 }, | ||||
| 			"sliderPosition" : { "x" : 130, "y" : 0 }, | ||||
| 			"sliderSize" : { "x" : 360, "y" : 360 }, | ||||
| 			"visibleAmount" : 9 | ||||
| 			"sliderSize" : { "x" : 320, "y" : 320 }, | ||||
| 			"visibleAmount" : 8 | ||||
| 		}, | ||||
|  | ||||
| 		{ | ||||
|   | ||||
| @@ -81,9 +81,11 @@ namespace RandomGeneratorUtil | ||||
|  | ||||
| 		for (size_t i = 0; i < container.size(); ++i) | ||||
| 		{ | ||||
| 			roll -= container[i]; | ||||
| 			if(roll < 0) | ||||
| 			int chance = container[i]; | ||||
| 			if(roll < chance) | ||||
| 				return i; | ||||
|  | ||||
| 			roll -= chance; | ||||
| 		} | ||||
| 		return container.size() - 1; | ||||
| 	} | ||||
|   | ||||
| @@ -467,8 +467,7 @@ void LobbyServer::receiveRequestChatHistory(const NetworkConnectionPtr & connect | ||||
|  | ||||
| 	if (channelType == "global") | ||||
| 	{ | ||||
| 		// can only be sent on connection, initiated by server | ||||
| 		sendOperationFailed(connection, "Operation not supported!"); | ||||
| 		sendRecentChatHistory(connection, channelType, channelName); | ||||
| 	} | ||||
|  | ||||
| 	if (channelType == "match") | ||||
| @@ -588,6 +587,7 @@ void LobbyServer::receiveClientLogin(const NetworkConnectionPtr & connection, co | ||||
| 	std::string accountCookie = json["accountCookie"].String(); | ||||
| 	std::string language = json["language"].String(); | ||||
| 	std::string version = json["version"].String(); | ||||
| 	const auto & languageRooms = json["languageRooms"].Vector(); | ||||
|  | ||||
| 	if(!database->isAccountIDExists(accountID)) | ||||
| 		return sendOperationFailed(connection, "Account not found"); | ||||
| @@ -606,9 +606,18 @@ void LobbyServer::receiveClientLogin(const NetworkConnectionPtr & connection, co | ||||
|  | ||||
| 	logGlobal->info("%s: Logged in as %s", accountID, displayName); | ||||
| 	sendClientLoginSuccess(connection, accountCookie, displayName); | ||||
| 	sendRecentChatHistory(connection, "global", "english"); | ||||
| 	if (language != "english") | ||||
| 		sendRecentChatHistory(connection, "global", language); | ||||
|  | ||||
| 	if (!languageRooms.empty()) | ||||
| 	{ | ||||
| 		for (const auto & entry : languageRooms) | ||||
| 			sendRecentChatHistory(connection, "global", entry.String()); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		sendRecentChatHistory(connection, "global", "english"); | ||||
| 		if (language != "english") | ||||
| 			sendRecentChatHistory(connection, "global", language); | ||||
| 	} | ||||
|  | ||||
| 	// send active game rooms list to new account | ||||
| 	// and update account list to everybody else including new account | ||||
|   | ||||