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
|
||||
|