2023-11-11 16:43:58 +02:00
|
|
|
/*
|
2023-12-27 19:07:49 +02:00
|
|
|
* GlobalLobbyClient.cpp, part of VCMI engine
|
2023-11-11 16:43:58 +02:00
|
|
|
*
|
|
|
|
* 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"
|
2023-12-27 19:07:49 +02:00
|
|
|
#include "GlobalLobbyClient.h"
|
|
|
|
|
|
|
|
#include "GlobalLobbyWindow.h"
|
2023-12-28 21:27:21 +02:00
|
|
|
#include "GlobalLobbyLoginWindow.h"
|
2023-11-11 16:43:58 +02:00
|
|
|
|
|
|
|
#include "../gui/CGuiHandler.h"
|
|
|
|
#include "../gui/WindowHandler.h"
|
2023-11-12 13:27:22 +02:00
|
|
|
#include "../windows/InfoWindows.h"
|
|
|
|
|
2023-11-12 16:35:53 +02:00
|
|
|
#include "../../lib/MetaString.h"
|
2023-11-12 21:23:42 +02:00
|
|
|
#include "../../lib/CConfigHandler.h"
|
2023-11-18 16:34:18 +02:00
|
|
|
#include "../../lib/network/NetworkClient.h"
|
2023-11-12 16:35:53 +02:00
|
|
|
|
2023-12-28 21:27:21 +02:00
|
|
|
GlobalLobbyClient::~GlobalLobbyClient()
|
|
|
|
{
|
|
|
|
networkClient->stop();
|
|
|
|
networkThread->join();
|
|
|
|
}
|
2023-12-27 19:07:49 +02:00
|
|
|
|
2023-12-28 21:27:21 +02:00
|
|
|
GlobalLobbyClient::GlobalLobbyClient()
|
2023-11-18 16:34:18 +02:00
|
|
|
: networkClient(std::make_unique<NetworkClient>(*this))
|
2023-12-28 21:27:21 +02:00
|
|
|
{
|
|
|
|
networkThread = std::make_unique<boost::thread>([this](){
|
|
|
|
networkClient->run();
|
|
|
|
});
|
|
|
|
}
|
2023-11-12 15:32:54 +02:00
|
|
|
|
2023-11-12 21:23:42 +02:00
|
|
|
static std::string getCurrentTimeFormatted(int timeOffsetSeconds = 0)
|
|
|
|
{
|
|
|
|
// FIXME: better/unified way to format date
|
|
|
|
auto timeNowChrono = std::chrono::system_clock::now();
|
|
|
|
timeNowChrono += std::chrono::seconds(timeOffsetSeconds);
|
|
|
|
|
|
|
|
std::time_t timeNowC = std::chrono::system_clock::to_time_t(timeNowChrono);
|
|
|
|
std::tm timeNowTm = *std::localtime(&timeNowC);
|
|
|
|
|
|
|
|
MetaString timeFormatted;
|
|
|
|
timeFormatted.appendRawString("%d:%d");
|
|
|
|
timeFormatted.replaceNumber(timeNowTm.tm_hour);
|
|
|
|
timeFormatted.replaceNumber(timeNowTm.tm_min);
|
|
|
|
|
|
|
|
return timeFormatted.toString();
|
|
|
|
}
|
|
|
|
|
2023-12-27 17:07:44 +02:00
|
|
|
void GlobalLobbyClient::onPacketReceived(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message)
|
2023-11-11 16:43:58 +02:00
|
|
|
{
|
2023-12-28 21:27:21 +02:00
|
|
|
boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex);
|
|
|
|
|
2023-11-12 16:35:53 +02:00
|
|
|
// FIXME: find better approach
|
|
|
|
const char * payloadBegin = reinterpret_cast<const char*>(message.data());
|
|
|
|
JsonNode json(payloadBegin, message.size());
|
|
|
|
|
2023-12-28 21:27:21 +02:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2023-11-12 16:35:53 +02:00
|
|
|
if (json["type"].String() == "chatHistory")
|
|
|
|
{
|
|
|
|
for (auto const & entry : json["messages"].Vector())
|
|
|
|
{
|
|
|
|
std::string senderName = entry["senderName"].String();
|
|
|
|
std::string messageText = entry["messageText"].String();
|
|
|
|
int ageSeconds = entry["ageSeconds"].Integer();
|
2023-11-12 21:23:42 +02:00
|
|
|
std::string timeFormatted = getCurrentTimeFormatted(-ageSeconds);
|
2023-12-28 21:27:21 +02:00
|
|
|
|
|
|
|
auto lobbyWindowPtr = lobbyWindow.lock();
|
|
|
|
if(lobbyWindowPtr)
|
|
|
|
lobbyWindowPtr->onGameChatMessage(senderName, messageText, timeFormatted);
|
2023-11-12 21:23:42 +02:00
|
|
|
}
|
|
|
|
}
|
2023-11-12 16:35:53 +02:00
|
|
|
|
2023-11-12 21:23:42 +02:00
|
|
|
if (json["type"].String() == "chatMessage")
|
|
|
|
{
|
|
|
|
std::string senderName = json["senderName"].String();
|
|
|
|
std::string messageText = json["messageText"].String();
|
|
|
|
std::string timeFormatted = getCurrentTimeFormatted();
|
2023-12-28 21:27:21 +02:00
|
|
|
auto lobbyWindowPtr = lobbyWindow.lock();
|
|
|
|
if(lobbyWindowPtr)
|
|
|
|
lobbyWindowPtr->onGameChatMessage(senderName, messageText, timeFormatted);
|
2023-11-12 21:23:42 +02:00
|
|
|
}
|
|
|
|
}
|
2023-11-12 16:35:53 +02:00
|
|
|
|
2023-12-27 17:07:44 +02:00
|
|
|
void GlobalLobbyClient::onConnectionEstablished(const std::shared_ptr<NetworkConnection> &)
|
2023-11-12 21:23:42 +02:00
|
|
|
{
|
|
|
|
JsonNode toSend;
|
|
|
|
toSend["type"].String() = "authentication";
|
|
|
|
toSend["accountName"].String() = settings["general"]["playerName"].String();
|
2023-11-12 16:35:53 +02:00
|
|
|
|
2023-11-12 21:23:42 +02:00
|
|
|
sendMessage(toSend);
|
2023-11-11 16:43:58 +02:00
|
|
|
}
|
|
|
|
|
2023-12-27 17:07:44 +02:00
|
|
|
void GlobalLobbyClient::onConnectionFailed(const std::string & errorMessage)
|
2023-11-12 13:27:22 +02:00
|
|
|
{
|
2023-12-28 21:27:21 +02:00
|
|
|
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);
|
2023-11-12 13:27:22 +02:00
|
|
|
}
|
|
|
|
|
2023-12-27 17:07:44 +02:00
|
|
|
void GlobalLobbyClient::onDisconnected(const std::shared_ptr<NetworkConnection> &)
|
2023-11-12 13:27:22 +02:00
|
|
|
{
|
|
|
|
GH.windows().popWindows(1);
|
|
|
|
CInfoWindow::showInfoDialog("Connection to game lobby was lost!", {});
|
|
|
|
}
|
|
|
|
|
2023-12-27 17:07:44 +02:00
|
|
|
void GlobalLobbyClient::onTimer()
|
2023-12-26 18:30:37 +02:00
|
|
|
{
|
|
|
|
// no-op
|
|
|
|
}
|
|
|
|
|
2023-12-27 17:07:44 +02:00
|
|
|
void GlobalLobbyClient::sendMessage(const JsonNode & data)
|
2023-11-12 15:32:54 +02:00
|
|
|
{
|
|
|
|
std::string payloadString = data.toJson(true);
|
|
|
|
|
|
|
|
// FIXME: find better approach
|
|
|
|
uint8_t * payloadBegin = reinterpret_cast<uint8_t*>(payloadString.data());
|
|
|
|
uint8_t * payloadEnd = payloadBegin + payloadString.size();
|
|
|
|
|
|
|
|
std::vector<uint8_t> payloadBuffer(payloadBegin, payloadEnd);
|
|
|
|
|
2023-11-18 16:34:18 +02:00
|
|
|
networkClient->sendPacket(payloadBuffer);
|
|
|
|
}
|
|
|
|
|
2023-12-28 21:27:21 +02:00
|
|
|
void GlobalLobbyClient::connect()
|
|
|
|
{
|
|
|
|
networkClient->start("127.0.0.1", 30303);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GlobalLobbyClient::isConnected()
|
2023-11-18 16:34:18 +02:00
|
|
|
{
|
2023-12-28 21:27:21 +02:00
|
|
|
return networkClient->isConnected();
|
2023-11-18 16:34:18 +02:00
|
|
|
}
|
|
|
|
|
2023-12-28 21:27:21 +02:00
|
|
|
std::shared_ptr<GlobalLobbyLoginWindow> GlobalLobbyClient::createLoginWindow()
|
2023-11-18 16:34:18 +02:00
|
|
|
{
|
2023-12-28 21:27:21 +02:00
|
|
|
auto loginWindowPtr = loginWindow.lock();
|
|
|
|
if (loginWindowPtr)
|
|
|
|
return loginWindowPtr;
|
|
|
|
|
|
|
|
auto loginWindowNew = std::make_shared<GlobalLobbyLoginWindow>();
|
|
|
|
loginWindow = loginWindowNew;
|
|
|
|
|
|
|
|
return loginWindowNew;
|
2023-11-18 16:34:18 +02:00
|
|
|
}
|
|
|
|
|
2023-12-28 21:27:21 +02:00
|
|
|
std::shared_ptr<GlobalLobbyWindow> GlobalLobbyClient::createLobbyWindow()
|
2023-11-18 16:34:18 +02:00
|
|
|
{
|
2023-12-28 21:27:21 +02:00
|
|
|
auto lobbyWindowPtr = lobbyWindow.lock();
|
|
|
|
if (lobbyWindowPtr)
|
|
|
|
return lobbyWindowPtr;
|
|
|
|
|
|
|
|
lobbyWindowPtr = std::make_shared<GlobalLobbyWindow>();
|
|
|
|
lobbyWindow = lobbyWindowPtr;
|
|
|
|
lobbyWindowLock = lobbyWindowPtr;
|
|
|
|
return lobbyWindowPtr;
|
2023-11-12 15:32:54 +02:00
|
|
|
}
|
2023-12-28 21:27:21 +02:00
|
|
|
|