mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-28 08:48:48 +02:00
Implemented basic version of login window and persistent connection on
client
This commit is contained in:
parent
78833a1015
commit
55b504792e
@ -71,6 +71,11 @@
|
||||
"vcmi.lobby.noPreview" : "no preview",
|
||||
"vcmi.lobby.noUnderground" : "no underground",
|
||||
"vcmi.lobby.sortDate" : "Sorts maps by change date",
|
||||
|
||||
"vcmi.lobby.login.title" : "VCMI Lobby",
|
||||
"vcmi.lobby.login.username" : "Username:",
|
||||
"vcmi.lobby.login.connecting" : "Connecting...",
|
||||
// "vcmi.lobby.login.connectionFailed" : "Connection failed: %s",
|
||||
|
||||
"vcmi.client.errors.missingCampaigns" : "{Missing data files}\n\nCampaigns data files were not found! You may be using incomplete or corrupted Heroes 3 data files. Please reinstall game data.",
|
||||
"vcmi.server.errors.existingProcess" : "Another VCMI server process is running. Please terminate it before starting a new game.",
|
||||
|
@ -96,6 +96,7 @@ set(client_SRCS
|
||||
renderSDL/SDL_Extensions.cpp
|
||||
|
||||
globalLobby/GlobalLobbyClient.cpp
|
||||
globalLobby/GlobalLobbyLoginWindow.cpp
|
||||
globalLobby/GlobalLobbyWidget.cpp
|
||||
globalLobby/GlobalLobbyWindow.cpp
|
||||
|
||||
@ -275,6 +276,7 @@ set(client_HEADERS
|
||||
renderSDL/SDL_PixelAccess.h
|
||||
|
||||
globalLobby/GlobalLobbyClient.h
|
||||
globalLobby/GlobalLobbyLoginWindow.h
|
||||
globalLobby/GlobalLobbyWidget.h
|
||||
globalLobby/GlobalLobbyWindow.h
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "gui/WindowHandler.h"
|
||||
|
||||
#include "globalLobby/GlobalLobbyClient.h"
|
||||
#include "lobby/CSelectionBase.h"
|
||||
#include "lobby/CLobbyScreen.h"
|
||||
#include "windows/InfoWindows.h"
|
||||
@ -139,6 +140,7 @@ CServerHandler::CServerHandler()
|
||||
: state(EClientState::NONE)
|
||||
, networkClient(std::make_unique<NetworkClient>(*this))
|
||||
, applier(std::make_unique<CApplier<CBaseForLobbyApply>>())
|
||||
, lobbyClient(std::make_unique<GlobalLobbyClient>())
|
||||
, client(nullptr)
|
||||
, loadMode(0)
|
||||
, campaignStateToSend(nullptr)
|
||||
@ -175,6 +177,11 @@ void CServerHandler::resetStateForLobby(const StartInfo::EMode mode, const std::
|
||||
myNames.push_back(settings["general"]["playerName"].String());
|
||||
}
|
||||
|
||||
GlobalLobbyClient & CServerHandler::getGlobalLobby()
|
||||
{
|
||||
return *lobbyClient;
|
||||
}
|
||||
|
||||
void CServerHandler::startLocalServerAndConnect()
|
||||
{
|
||||
if(threadRunLocalServer)
|
||||
|
@ -35,6 +35,7 @@ VCMI_LIB_NAMESPACE_END
|
||||
|
||||
class CClient;
|
||||
class CBaseForLobbyApply;
|
||||
class GlobalLobbyClient;
|
||||
|
||||
class HighScoreCalculation;
|
||||
class HighScoreParameter;
|
||||
@ -86,6 +87,7 @@ class CServerHandler : public IServerAPI, public LobbyInfo, public INetworkClien
|
||||
friend class ApplyOnLobbyHandlerNetPackVisitor;
|
||||
|
||||
std::unique_ptr<NetworkClient> networkClient;
|
||||
std::unique_ptr<GlobalLobbyClient> lobbyClient;
|
||||
std::unique_ptr<CApplier<CBaseForLobbyApply>> applier;
|
||||
std::shared_ptr<CMapInfo> mapToStart;
|
||||
std::vector<std::string> myNames;
|
||||
@ -138,6 +140,8 @@ public:
|
||||
void startLocalServerAndConnect();
|
||||
void connectToServer(const std::string & addr, const ui16 port);
|
||||
|
||||
GlobalLobbyClient & getGlobalLobby();
|
||||
|
||||
// Helpers for lobby state access
|
||||
std::set<PlayerColor> getHumanColors();
|
||||
PlayerColor myFirstColor() const;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "GlobalLobbyClient.h"
|
||||
|
||||
#include "GlobalLobbyWindow.h"
|
||||
#include "GlobalLobbyLoginWindow.h"
|
||||
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/WindowHandler.h"
|
||||
@ -21,12 +22,19 @@
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/network/NetworkClient.h"
|
||||
|
||||
GlobalLobbyClient::~GlobalLobbyClient() = default;
|
||||
GlobalLobbyClient::~GlobalLobbyClient()
|
||||
{
|
||||
networkClient->stop();
|
||||
networkThread->join();
|
||||
}
|
||||
|
||||
GlobalLobbyClient::GlobalLobbyClient(GlobalLobbyWindow * window)
|
||||
GlobalLobbyClient::GlobalLobbyClient()
|
||||
: networkClient(std::make_unique<NetworkClient>(*this))
|
||||
, window(window)
|
||||
{}
|
||||
{
|
||||
networkThread = std::make_unique<boost::thread>([this](){
|
||||
networkClient->run();
|
||||
});
|
||||
}
|
||||
|
||||
static std::string getCurrentTimeFormatted(int timeOffsetSeconds = 0)
|
||||
{
|
||||
@ -47,10 +55,22 @@ static std::string getCurrentTimeFormatted(int timeOffsetSeconds = 0)
|
||||
|
||||
void GlobalLobbyClient::onPacketReceived(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message)
|
||||
{
|
||||
boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex);
|
||||
|
||||
// FIXME: find better approach
|
||||
const char * payloadBegin = reinterpret_cast<const char*>(message.data());
|
||||
JsonNode json(payloadBegin, message.size());
|
||||
|
||||
if (json["type"].String() == "authentication")
|
||||
{
|
||||
auto loginWindowPtr = loginWindow.lock();
|
||||
|
||||
if (!loginWindowPtr || !GH.windows().topWindow<GlobalLobbyLoginWindow>())
|
||||
throw std::runtime_error("lobby connection finished without active login window!");
|
||||
|
||||
loginWindowPtr->onConnectionSuccess();
|
||||
}
|
||||
|
||||
if (json["type"].String() == "chatHistory")
|
||||
{
|
||||
for (auto const & entry : json["messages"].Vector())
|
||||
@ -59,7 +79,10 @@ void GlobalLobbyClient::onPacketReceived(const std::shared_ptr<NetworkConnection
|
||||
std::string messageText = entry["messageText"].String();
|
||||
int ageSeconds = entry["ageSeconds"].Integer();
|
||||
std::string timeFormatted = getCurrentTimeFormatted(-ageSeconds);
|
||||
window->onGameChatMessage(senderName, messageText, timeFormatted);
|
||||
|
||||
auto lobbyWindowPtr = lobbyWindow.lock();
|
||||
if(lobbyWindowPtr)
|
||||
lobbyWindowPtr->onGameChatMessage(senderName, messageText, timeFormatted);
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,7 +91,9 @@ void GlobalLobbyClient::onPacketReceived(const std::shared_ptr<NetworkConnection
|
||||
std::string senderName = json["senderName"].String();
|
||||
std::string messageText = json["messageText"].String();
|
||||
std::string timeFormatted = getCurrentTimeFormatted();
|
||||
window->onGameChatMessage(senderName, messageText, timeFormatted);
|
||||
auto lobbyWindowPtr = lobbyWindow.lock();
|
||||
if(lobbyWindowPtr)
|
||||
lobbyWindowPtr->onGameChatMessage(senderName, messageText, timeFormatted);
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,8 +108,13 @@ void GlobalLobbyClient::onConnectionEstablished(const std::shared_ptr<NetworkCon
|
||||
|
||||
void GlobalLobbyClient::onConnectionFailed(const std::string & errorMessage)
|
||||
{
|
||||
GH.windows().popWindows(1);
|
||||
CInfoWindow::showInfoDialog("Failed to connect to game lobby!\n" + errorMessage, {});
|
||||
auto loginWindowPtr = loginWindow.lock();
|
||||
|
||||
if (!loginWindowPtr || !GH.windows().topWindow<GlobalLobbyLoginWindow>())
|
||||
throw std::runtime_error("lobby connection failed without active login window!");
|
||||
|
||||
logGlobal->warn("Connection to game lobby failed! Reason: %s", errorMessage);
|
||||
loginWindowPtr->onConnectionFailed(errorMessage);
|
||||
}
|
||||
|
||||
void GlobalLobbyClient::onDisconnected(const std::shared_ptr<NetworkConnection> &)
|
||||
@ -111,17 +141,37 @@ void GlobalLobbyClient::sendMessage(const JsonNode & data)
|
||||
networkClient->sendPacket(payloadBuffer);
|
||||
}
|
||||
|
||||
void GlobalLobbyClient::start(const std::string & host, uint16_t port)
|
||||
void GlobalLobbyClient::connect()
|
||||
{
|
||||
networkClient->start(host, port);
|
||||
networkClient->start("127.0.0.1", 30303);
|
||||
}
|
||||
|
||||
void GlobalLobbyClient::run()
|
||||
bool GlobalLobbyClient::isConnected()
|
||||
{
|
||||
networkClient->run();
|
||||
return networkClient->isConnected();
|
||||
}
|
||||
|
||||
void GlobalLobbyClient::poll()
|
||||
std::shared_ptr<GlobalLobbyLoginWindow> GlobalLobbyClient::createLoginWindow()
|
||||
{
|
||||
networkClient->poll();
|
||||
auto loginWindowPtr = loginWindow.lock();
|
||||
if (loginWindowPtr)
|
||||
return loginWindowPtr;
|
||||
|
||||
auto loginWindowNew = std::make_shared<GlobalLobbyLoginWindow>();
|
||||
loginWindow = loginWindowNew;
|
||||
|
||||
return loginWindowNew;
|
||||
}
|
||||
|
||||
std::shared_ptr<GlobalLobbyWindow> GlobalLobbyClient::createLobbyWindow()
|
||||
{
|
||||
auto lobbyWindowPtr = lobbyWindow.lock();
|
||||
if (lobbyWindowPtr)
|
||||
return lobbyWindowPtr;
|
||||
|
||||
lobbyWindowPtr = std::make_shared<GlobalLobbyWindow>();
|
||||
lobbyWindow = lobbyWindowPtr;
|
||||
lobbyWindowLock = lobbyWindowPtr;
|
||||
return lobbyWindowPtr;
|
||||
}
|
||||
|
||||
|
@ -15,12 +15,17 @@ VCMI_LIB_NAMESPACE_BEGIN
|
||||
class JsonNode;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
class GlobalLobbyLoginWindow;
|
||||
class GlobalLobbyWindow;
|
||||
|
||||
class GlobalLobbyClient : public INetworkClientListener
|
||||
class GlobalLobbyClient : public INetworkClientListener, boost::noncopyable
|
||||
{
|
||||
std::unique_ptr<boost::thread> networkThread;
|
||||
std::unique_ptr<NetworkClient> networkClient;
|
||||
GlobalLobbyWindow * window;
|
||||
|
||||
std::weak_ptr<GlobalLobbyLoginWindow> loginWindow;
|
||||
std::weak_ptr<GlobalLobbyWindow> lobbyWindow;
|
||||
std::shared_ptr<GlobalLobbyWindow> lobbyWindowLock; // helper strong reference to prevent window destruction on closing
|
||||
|
||||
void onPacketReceived(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message) override;
|
||||
void onConnectionFailed(const std::string & errorMessage) override;
|
||||
@ -29,12 +34,12 @@ class GlobalLobbyClient : public INetworkClientListener
|
||||
void onTimer() override;
|
||||
|
||||
public:
|
||||
explicit GlobalLobbyClient(GlobalLobbyWindow * window);
|
||||
explicit GlobalLobbyClient();
|
||||
~GlobalLobbyClient();
|
||||
|
||||
void sendMessage(const JsonNode & data);
|
||||
void start(const std::string & host, uint16_t port);
|
||||
void run();
|
||||
void poll();
|
||||
|
||||
void connect();
|
||||
bool isConnected();
|
||||
std::shared_ptr<GlobalLobbyLoginWindow> createLoginWindow();
|
||||
std::shared_ptr<GlobalLobbyWindow> createLobbyWindow();
|
||||
};
|
||||
|
76
client/globalLobby/GlobalLobbyLoginWindow.cpp
Normal file
76
client/globalLobby/GlobalLobbyLoginWindow.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* GlobalLobbyLoginWindow.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 "GlobalLobbyLoginWindow.h"
|
||||
|
||||
#include "GlobalLobbyClient.h"
|
||||
#include "GlobalLobbyWindow.h"
|
||||
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/WindowHandler.h"
|
||||
#include "../widgets/TextControls.h"
|
||||
#include "../widgets/Images.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
#include "../widgets/MiscWidgets.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CServerHandler.h"
|
||||
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
#include "../../lib/MetaString.h"
|
||||
|
||||
GlobalLobbyLoginWindow::GlobalLobbyLoginWindow()
|
||||
: CWindowObject(BORDERED)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||
|
||||
pos.w = 200;
|
||||
pos.h = 200;
|
||||
|
||||
background = std::make_shared<FilledTexturePlayerColored>(ImagePath::builtin("DiBoxBck"), Rect(0, 0, pos.w, pos.h));
|
||||
labelTitle = std::make_shared<CLabel>( pos.w / 2, 20, FONT_BIG, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->translate("vcmi.lobby.login.title"));
|
||||
labelUsername = std::make_shared<CLabel>( 10, 45, FONT_MEDIUM, ETextAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->translate("vcmi.lobby.login.username"));
|
||||
backgroundUsername = std::make_shared<TransparentFilledRectangle>(Rect(10, 70, 180, 20), ColorRGBA(0,0,0,128), ColorRGBA(64,64,64,64));
|
||||
inputUsername = std::make_shared<CTextInput>(Rect(15, 73, 176, 16), FONT_SMALL, nullptr, ETextAlignment::TOPLEFT, true);
|
||||
buttonLogin = std::make_shared<CButton>(Point(10, 160), AnimationPath::builtin("MuBchck"), CButton::tooltip(), [this](){ onLogin(); });
|
||||
buttonClose = std::make_shared<CButton>(Point(126, 160), AnimationPath::builtin("MuBcanc"), CButton::tooltip(), [this](){ onClose(); });
|
||||
labelStatus = std::make_shared<CTextBox>( "", Rect(15, 95, 175, 60), 1, FONT_MEDIUM, ETextAlignment::TOPLEFT, Colors::WHITE);
|
||||
|
||||
background->playerColored(PlayerColor(1));
|
||||
|
||||
center();
|
||||
}
|
||||
|
||||
void GlobalLobbyLoginWindow::onClose()
|
||||
{
|
||||
close();
|
||||
// TODO: abort ongoing connection attempt, if any
|
||||
}
|
||||
|
||||
void GlobalLobbyLoginWindow::onLogin()
|
||||
{
|
||||
labelStatus->setText(CGI->generaltexth->translate("vcmi.lobby.login.connecting"));
|
||||
CSH->getGlobalLobby().connect();
|
||||
}
|
||||
|
||||
void GlobalLobbyLoginWindow::onConnectionSuccess()
|
||||
{
|
||||
close();
|
||||
GH.windows().pushWindow(CSH->getGlobalLobby().createLobbyWindow());
|
||||
}
|
||||
|
||||
void GlobalLobbyLoginWindow::onConnectionFailed(const std::string & reason)
|
||||
{
|
||||
MetaString formatter;
|
||||
formatter.appendTextID("vcmi.lobby.login.error");
|
||||
formatter.replaceRawString(reason);
|
||||
|
||||
labelStatus->setText(formatter.toString());
|
||||
}
|
41
client/globalLobby/GlobalLobbyLoginWindow.h
Normal file
41
client/globalLobby/GlobalLobbyLoginWindow.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* GlobalLobbyLoginWindow.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../windows/CWindowObject.h"
|
||||
|
||||
class CLabel;
|
||||
class CTextBox;
|
||||
class CTextInput;
|
||||
class FilledTexturePlayerColored;
|
||||
class TransparentFilledRectangle;
|
||||
class CButton;
|
||||
|
||||
class GlobalLobbyLoginWindow : public CWindowObject
|
||||
{
|
||||
std::shared_ptr<FilledTexturePlayerColored> background;
|
||||
std::shared_ptr<CLabel> labelTitle;
|
||||
std::shared_ptr<CLabel> labelUsername;
|
||||
std::shared_ptr<CTextBox> labelStatus;
|
||||
std::shared_ptr<TransparentFilledRectangle> backgroundUsername;
|
||||
std::shared_ptr<CTextInput> inputUsername;
|
||||
|
||||
std::shared_ptr<CButton> buttonLogin;
|
||||
std::shared_ptr<CButton> buttonClose;
|
||||
|
||||
void onClose();
|
||||
void onLogin();
|
||||
|
||||
public:
|
||||
GlobalLobbyLoginWindow();
|
||||
|
||||
void onConnectionSuccess();
|
||||
void onConnectionFailed(const std::string & reason);
|
||||
};
|
@ -21,6 +21,7 @@ GlobalLobbyWidget::GlobalLobbyWidget(GlobalLobbyWindow * window)
|
||||
{
|
||||
addCallback("closeWindow", [](int) { GH.windows().popWindows(1); });
|
||||
addCallback("sendMessage", [this](int) { this->window->doSendChatMessage(); });
|
||||
addCallback("createGameRoom", [this](int) { this->window->doCreateGameRoom(); });
|
||||
|
||||
const JsonNode config(JsonPath::builtin("config/widgets/lobbyWindow.json"));
|
||||
build(config);
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../widgets/TextControls.h"
|
||||
#include "../CServerHandler.h"
|
||||
|
||||
#include "../../lib/MetaString.h"
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
@ -27,17 +28,8 @@ GlobalLobbyWindow::GlobalLobbyWindow():
|
||||
widget = std::make_shared<GlobalLobbyWidget>(this);
|
||||
pos = widget->pos;
|
||||
center();
|
||||
connection = std::make_shared<GlobalLobbyClient>(this);
|
||||
|
||||
connection->start("127.0.0.1", 30303);
|
||||
widget->getAccountNameLabel()->setText(settings["general"]["playerName"].String());
|
||||
|
||||
addUsedEvents(TIME);
|
||||
}
|
||||
|
||||
void GlobalLobbyWindow::tick(uint32_t msPassed)
|
||||
{
|
||||
connection->poll();
|
||||
}
|
||||
|
||||
void GlobalLobbyWindow::doSendChatMessage()
|
||||
@ -48,11 +40,22 @@ void GlobalLobbyWindow::doSendChatMessage()
|
||||
toSend["type"].String() = "sendChatMessage";
|
||||
toSend["messageText"].String() = messageText;
|
||||
|
||||
connection->sendMessage(toSend);
|
||||
CSH->getGlobalLobby().sendMessage(toSend);
|
||||
|
||||
widget->getMessageInput()->setText("");
|
||||
}
|
||||
|
||||
void GlobalLobbyWindow::doCreateGameRoom()
|
||||
{
|
||||
// TODO:
|
||||
// start local server and supply our UUID / client credentials to it
|
||||
// server logs into lobby ( uuid = client, mode = server ). This creates 'room' in mode 'empty'
|
||||
// server starts accepting connections from players (including host)
|
||||
// client connects to local server
|
||||
// client sends createGameRoom query to lobby with own / server UUID and mode 'direct' (non-proxy)
|
||||
// client requests to change room status to private or public
|
||||
}
|
||||
|
||||
void GlobalLobbyWindow::onGameChatMessage(const std::string & sender, const std::string & message, const std::string & when)
|
||||
{
|
||||
MetaString chatMessageFormatted;
|
||||
|
@ -12,21 +12,19 @@
|
||||
#include "../windows/CWindowObject.h"
|
||||
|
||||
class GlobalLobbyWidget;
|
||||
class GlobalLobbyClient;
|
||||
|
||||
class GlobalLobbyWindow : public CWindowObject
|
||||
{
|
||||
std::string chatHistory;
|
||||
|
||||
std::shared_ptr<GlobalLobbyWidget> widget;
|
||||
std::shared_ptr<GlobalLobbyClient> connection;
|
||||
|
||||
void tick(uint32_t msPassed);
|
||||
|
||||
public:
|
||||
GlobalLobbyWindow();
|
||||
|
||||
void doSendChatMessage();
|
||||
void doCreateGameRoom();
|
||||
|
||||
void onGameChatMessage(const std::string & sender, const std::string & message, const std::string & when);
|
||||
|
||||
};
|
||||
|
@ -335,7 +335,7 @@ CChatBox::CChatBox(const Rect & rect)
|
||||
Rect textInputArea(1, rect.h - height, rect.w - 1, height);
|
||||
Rect chatHistoryArea(3, 1, rect.w - 3, rect.h - height - 1);
|
||||
inputBackground = std::make_shared<TransparentFilledRectangle>(textInputArea, ColorRGBA(0,0,0,192));
|
||||
inputBox = std::make_shared<CTextInput>(textInputArea, EFonts::FONT_SMALL, 0);
|
||||
inputBox = std::make_shared<CTextInput>(textInputArea, EFonts::FONT_SMALL, nullptr, ETextAlignment::TOPLEFT, true);
|
||||
inputBox->removeUsedEvents(KEYBOARD);
|
||||
chatHistory = std::make_shared<CTextBox>("", chatHistoryArea, 1);
|
||||
|
||||
|
@ -892,7 +892,7 @@ OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry(const PlayerSettings & S, con
|
||||
labelPlayerName = std::make_shared<CLabel>(55, 10, EFonts::FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, name, 95);
|
||||
else
|
||||
{
|
||||
labelPlayerNameEdit = std::make_shared<CTextInput>(Rect(6, 3, 95, 15), EFonts::FONT_SMALL, nullptr, false);
|
||||
labelPlayerNameEdit = std::make_shared<CTextInput>(Rect(6, 3, 95, 15), EFonts::FONT_SMALL, nullptr, ETextAlignment::CENTER, false);
|
||||
labelPlayerNameEdit->setText(name);
|
||||
}
|
||||
labelWhoCanPlay = std::make_shared<CMultiLineLabel>(Rect(6, 23, 45, (int)graphics->fonts[EFonts::FONT_TINY]->getLineHeight()*2), EFonts::FONT_TINY, ETextAlignment::CENTER, Colors::WHITE, CGI->generaltexth->arraytxt[206 + whoCanPlay]);
|
||||
|
@ -372,7 +372,7 @@ CHighScoreInput::CHighScoreInput(std::string playerName, std::function<void(std:
|
||||
buttonOk = std::make_shared<CButton>(Point(26, 142), AnimationPath::builtin("MUBCHCK.DEF"), CGI->generaltexth->zelp[560], std::bind(&CHighScoreInput::okay, this), EShortcut::GLOBAL_ACCEPT);
|
||||
buttonCancel = std::make_shared<CButton>(Point(142, 142), AnimationPath::builtin("MUBCANC.DEF"), CGI->generaltexth->zelp[561], std::bind(&CHighScoreInput::abort, this), EShortcut::GLOBAL_CANCEL);
|
||||
statusBar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), Rect(7, 186, 218, 18), 7, 186));
|
||||
textInput = std::make_shared<CTextInput>(Rect(18, 104, 200, 25), FONT_SMALL, 0);
|
||||
textInput = std::make_shared<CTextInput>(Rect(18, 104, 200, 25), FONT_SMALL, nullptr, ETextAlignment::CENTER, true);
|
||||
textInput->setText(playerName);
|
||||
}
|
||||
|
||||
@ -384,4 +384,4 @@ void CHighScoreInput::okay()
|
||||
void CHighScoreInput::abort()
|
||||
{
|
||||
ready("");
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include "../gui/Shortcut.h"
|
||||
#include "../gui/WindowHandler.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../globalLobby/GlobalLobbyLoginWindow.h"
|
||||
#include "../globalLobby/GlobalLobbyClient.h"
|
||||
#include "../globalLobby/GlobalLobbyWindow.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
@ -467,7 +469,10 @@ CMultiMode::CMultiMode(ESelectionScreen ScreenType)
|
||||
void CMultiMode::openLobby()
|
||||
{
|
||||
close();
|
||||
GH.windows().createAndPushWindow<GlobalLobbyWindow>();
|
||||
if (CSH->getGlobalLobby().isConnected())
|
||||
GH.windows().pushWindow(CSH->getGlobalLobby().createLobbyWindow());
|
||||
else
|
||||
GH.windows().pushWindow(CSH->getGlobalLobby().createLoginWindow());
|
||||
}
|
||||
|
||||
void CMultiMode::hostTCP()
|
||||
|
@ -551,8 +551,8 @@ Point CGStatusBar::getBorderSize()
|
||||
return Point();
|
||||
}
|
||||
|
||||
CTextInput::CTextInput(const Rect & Pos, EFonts font, const CFunctionList<void(const std::string &)> & CB, bool giveFocusToInput)
|
||||
: CLabel(Pos.x, Pos.y, font, ETextAlignment::CENTER),
|
||||
CTextInput::CTextInput(const Rect & Pos, EFonts font, const CFunctionList<void(const std::string &)> & CB, ETextAlignment alignment, bool giveFocusToInput)
|
||||
: CLabel(Pos.x, Pos.y, font, alignment),
|
||||
cb(CB),
|
||||
CFocusable(std::make_shared<CKeyboardFocusListener>(this))
|
||||
{
|
||||
|
@ -228,7 +228,7 @@ public:
|
||||
void setText(const std::string & nText, bool callCb);
|
||||
void setHelpText(const std::string &);
|
||||
|
||||
CTextInput(const Rect & Pos, EFonts font, const CFunctionList<void(const std::string &)> & CB, bool giveFocusToInput = true);
|
||||
CTextInput(const Rect & Pos, EFonts font, const CFunctionList<void(const std::string &)> & CB, ETextAlignment alignment, bool giveFocusToInput);
|
||||
CTextInput(const Rect & Pos, const Point & bgOffset, const ImagePath & bgName, const CFunctionList<void(const std::string &)> & CB);
|
||||
CTextInput(const Rect & Pos, std::shared_ptr<IImage> srf);
|
||||
|
||||
|
@ -136,7 +136,7 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m
|
||||
searchBoxRectangle = std::make_shared<TransparentFilledRectangle>(r.resize(1), rectangleColor, borderColor);
|
||||
searchBoxDescription = std::make_shared<CLabel>(r.center().x, r.center().y, FONT_SMALL, ETextAlignment::CENTER, grayedColor, CGI->generaltexth->translate("vcmi.spellBook.search"));
|
||||
|
||||
searchBox = std::make_shared<CTextInput>(r, FONT_SMALL, std::bind(&CSpellWindow::searchInput, this));
|
||||
searchBox = std::make_shared<CTextInput>(r, FONT_SMALL, std::bind(&CSpellWindow::searchInput, this), ETextAlignment::CENTER, true);
|
||||
}
|
||||
|
||||
processSpells();
|
||||
|
@ -324,8 +324,8 @@ CSplitWindow::CSplitWindow(const CCreature * creature, std::function<void(int, i
|
||||
|
||||
int sliderPosition = total - leftMin - rightMin;
|
||||
|
||||
leftInput = std::make_shared<CTextInput>(Rect(20, 218, 100, 36), FONT_BIG, std::bind(&CSplitWindow::setAmountText, this, _1, true));
|
||||
rightInput = std::make_shared<CTextInput>(Rect(176, 218, 100, 36), FONT_BIG, std::bind(&CSplitWindow::setAmountText, this, _1, false));
|
||||
leftInput = std::make_shared<CTextInput>(Rect(20, 218, 100, 36), FONT_BIG, std::bind(&CSplitWindow::setAmountText, this, _1, true), ETextAlignment::CENTER, true);
|
||||
rightInput = std::make_shared<CTextInput>(Rect(176, 218, 100, 36), FONT_BIG, std::bind(&CSplitWindow::setAmountText, this, _1, false), ETextAlignment::CENTER, true);
|
||||
|
||||
//add filters to allow only number input
|
||||
leftInput->filters += std::bind(&CTextInput::numberFilter, _1, _2, leftMin, leftMax);
|
||||
|
@ -158,6 +158,7 @@
|
||||
"position": {"x": 10, "y": 520},
|
||||
"image": "settingsWindow/button190",
|
||||
"help": "core.help.288",
|
||||
"callback": "createGameRoom",
|
||||
"items":
|
||||
[
|
||||
{
|
||||
@ -175,6 +176,7 @@
|
||||
"position": {"x": 10, "y": 555},
|
||||
"image": "settingsWindow/button190",
|
||||
"help": "core.help.288",
|
||||
"callback": "createGameRoom",
|
||||
"items":
|
||||
[
|
||||
{
|
||||
|
@ -22,6 +22,9 @@ NetworkClient::NetworkClient(INetworkClientListener & listener)
|
||||
|
||||
void NetworkClient::start(const std::string & host, uint16_t port)
|
||||
{
|
||||
if (isConnected())
|
||||
throw std::runtime_error("Attempting to connect while already connected!");
|
||||
|
||||
boost::asio::ip::tcp::resolver resolver(*io);
|
||||
auto endpoints = resolver.resolve(host, std::to_string(port));
|
||||
|
||||
@ -58,6 +61,11 @@ void NetworkClient::stop()
|
||||
io->stop();
|
||||
}
|
||||
|
||||
bool NetworkClient::isConnected() const
|
||||
{
|
||||
return connection != nullptr;
|
||||
}
|
||||
|
||||
void NetworkClient::setTimer(std::chrono::milliseconds duration)
|
||||
{
|
||||
auto timer = std::make_shared<NetworkTimer>(*io, duration);
|
||||
@ -74,6 +82,7 @@ void NetworkClient::sendPacket(const std::vector<uint8_t> & message)
|
||||
|
||||
void NetworkClient::onDisconnected(const std::shared_ptr<NetworkConnection> & connection)
|
||||
{
|
||||
this->connection.reset();
|
||||
listener.onDisconnected(connection);
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,8 @@ public:
|
||||
NetworkClient(INetworkClientListener & listener);
|
||||
virtual ~NetworkClient() = default;
|
||||
|
||||
bool isConnected() const;
|
||||
|
||||
void setTimer(std::chrono::milliseconds duration);
|
||||
void sendPacket(const std::vector<uint8_t> & message);
|
||||
|
||||
|
@ -173,23 +173,32 @@ void LobbyServer::receiveAuthentication(const std::shared_ptr<NetworkConnection>
|
||||
|
||||
activeAccounts[connection].accountName = accountName;
|
||||
|
||||
auto history = database->getRecentMessageHistory();
|
||||
|
||||
JsonNode reply;
|
||||
reply["type"].String() = "chatHistory";
|
||||
|
||||
for (auto const & message : boost::adaptors::reverse(history))
|
||||
{
|
||||
JsonNode jsonEntry;
|
||||
JsonNode reply;
|
||||
reply["type"].String() = "authentication";
|
||||
|
||||
jsonEntry["messageText"].String() = message.messageText;
|
||||
jsonEntry["senderName"].String() = message.sender;
|
||||
jsonEntry["ageSeconds"].Integer() = message.messageAgeSeconds;
|
||||
|
||||
reply["messages"].Vector().push_back(jsonEntry);
|
||||
sendMessage(connection, reply);
|
||||
}
|
||||
|
||||
sendMessage(connection, reply);
|
||||
auto history = database->getRecentMessageHistory();
|
||||
|
||||
{
|
||||
JsonNode reply;
|
||||
reply["type"].String() = "chatHistory";
|
||||
|
||||
for (auto const & message : boost::adaptors::reverse(history))
|
||||
{
|
||||
JsonNode jsonEntry;
|
||||
|
||||
jsonEntry["messageText"].String() = message.messageText;
|
||||
jsonEntry["senderName"].String() = message.sender;
|
||||
jsonEntry["ageSeconds"].Integer() = message.messageAgeSeconds;
|
||||
|
||||
reply["messages"].Vector().push_back(jsonEntry);
|
||||
}
|
||||
|
||||
sendMessage(connection, reply);
|
||||
}
|
||||
}
|
||||
|
||||
void LobbyServer::receiveJoinGameRoom(const std::shared_ptr<NetworkConnection> & connection, const JsonNode & json)
|
||||
|
Loading…
Reference in New Issue
Block a user