mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Implemented message receiving / broadcasting
This commit is contained in:
parent
07fb313765
commit
de5227142b
@ -17,6 +17,7 @@
|
||||
#include "../windows/InfoWindows.h"
|
||||
|
||||
#include "../../lib/MetaString.h"
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
|
||||
LobbyClient::LobbyClient(LobbyWindow * window)
|
||||
: window(window)
|
||||
@ -24,6 +25,23 @@ LobbyClient::LobbyClient(LobbyWindow * window)
|
||||
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
void LobbyClient::onPacketReceived(const std::vector<uint8_t> & message)
|
||||
{
|
||||
// FIXME: find better approach
|
||||
@ -37,22 +55,27 @@ void LobbyClient::onPacketReceived(const std::vector<uint8_t> & message)
|
||||
std::string senderName = entry["senderName"].String();
|
||||
std::string messageText = entry["messageText"].String();
|
||||
int ageSeconds = entry["ageSeconds"].Integer();
|
||||
|
||||
// FIXME: better/unified way to format date
|
||||
auto timeNowChrono = std::chrono::system_clock::now();
|
||||
timeNowChrono -= std::chrono::seconds(ageSeconds);
|
||||
|
||||
std::time_t timeNowC = std::chrono::system_clock::to_time_t(timeNowChrono);
|
||||
std::tm timeNowTm = *std::localtime(&timeNowC);
|
||||
|
||||
MetaString dateFormatted;
|
||||
dateFormatted.appendRawString("%d:%d");
|
||||
dateFormatted.replaceNumber(timeNowTm.tm_hour);
|
||||
dateFormatted.replaceNumber(timeNowTm.tm_min);
|
||||
|
||||
window->onGameChatMessage(senderName, messageText, dateFormatted.toString());
|
||||
std::string timeFormatted = getCurrentTimeFormatted(-ageSeconds);
|
||||
window->onGameChatMessage(senderName, messageText, timeFormatted);
|
||||
}
|
||||
}
|
||||
|
||||
if (json["type"].String() == "chatMessage")
|
||||
{
|
||||
std::string senderName = json["senderName"].String();
|
||||
std::string messageText = json["messageText"].String();
|
||||
std::string timeFormatted = getCurrentTimeFormatted();
|
||||
window->onGameChatMessage(senderName, messageText, timeFormatted);
|
||||
}
|
||||
}
|
||||
|
||||
void LobbyClient::onConnectionEstablished()
|
||||
{
|
||||
JsonNode toSend;
|
||||
toSend["type"].String() = "authentication";
|
||||
toSend["accountName"].String() = settings["general"]["playerName"].String();
|
||||
|
||||
sendMessage(toSend);
|
||||
}
|
||||
|
||||
void LobbyClient::onConnectionFailed(const std::string & errorMessage)
|
||||
@ -90,6 +113,11 @@ LobbyWidget::LobbyWidget(LobbyWindow * window)
|
||||
build(config);
|
||||
}
|
||||
|
||||
std::shared_ptr<CLabel> LobbyWidget::getAccountNameLabel()
|
||||
{
|
||||
return widget<CLabel>("accountNameLabel");
|
||||
}
|
||||
|
||||
std::shared_ptr<CTextInput> LobbyWidget::getMessageInput()
|
||||
{
|
||||
return widget<CTextInput>("messageInput");
|
||||
@ -110,6 +138,7 @@ LobbyWindow::LobbyWindow():
|
||||
connection = std::make_shared<LobbyClient>(this);
|
||||
|
||||
connection->start("127.0.0.1", 30303);
|
||||
widget->getAccountNameLabel()->setText(settings["general"]["playerName"].String());
|
||||
|
||||
addUsedEvents(TIME);
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ class LobbyWidget : public InterfaceObjectConfigurable
|
||||
public:
|
||||
LobbyWidget(LobbyWindow * window);
|
||||
|
||||
std::shared_ptr<CLabel> getAccountNameLabel();
|
||||
std::shared_ptr<CTextInput> getMessageInput();
|
||||
std::shared_ptr<CTextBox> getGameChat();
|
||||
};
|
||||
@ -32,6 +33,7 @@ class LobbyClient : public NetworkClient
|
||||
|
||||
void onPacketReceived(const std::vector<uint8_t> & message) override;
|
||||
void onConnectionFailed(const std::string & errorMessage) override;
|
||||
void onConnectionEstablished() override;
|
||||
void onDisconnected() override;
|
||||
|
||||
public:
|
||||
|
@ -41,9 +41,9 @@
|
||||
"rect": {"x": 5, "y": 5, "w": 250, "h": 40}
|
||||
},
|
||||
{
|
||||
"name" : "accountNameLabel",
|
||||
"type": "labelTitleMain",
|
||||
"position": {"x": 15, "y": 10},
|
||||
"text" : "Player Name"
|
||||
"position": {"x": 15, "y": 10}
|
||||
},
|
||||
|
||||
{
|
||||
@ -91,8 +91,7 @@
|
||||
"font": "small",
|
||||
"alignment": "left",
|
||||
"color": "white",
|
||||
"text": "[00:00]{Player 1}: Hello\n[00:01]{Player 2}: HI!",
|
||||
"rect": {"x": 430, "y": 70, "w": 430, "h": 495}
|
||||
"rect": {"x": 440, "y": 70, "w": 430, "h": 495}
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -38,6 +38,8 @@ void NetworkClient::onConnected(const boost::system::error_code & ec)
|
||||
|
||||
connection = std::make_shared<NetworkConnection>(socket, *this);
|
||||
connection->start();
|
||||
|
||||
onConnectionEstablished();
|
||||
}
|
||||
|
||||
void NetworkClient::run()
|
||||
|
@ -30,6 +30,7 @@ class DLL_LINKAGE NetworkClient : boost::noncopyable, public INetworkConnectionL
|
||||
protected:
|
||||
virtual void onPacketReceived(const std::vector<uint8_t> & message) = 0;
|
||||
virtual void onConnectionFailed(const std::string & errorMessage) = 0;
|
||||
virtual void onConnectionEstablished() = 0;
|
||||
virtual void onDisconnected() = 0;
|
||||
|
||||
void sendPacket(const std::vector<uint8_t> & message);
|
||||
|
@ -16,7 +16,7 @@ VCMI_LIB_NAMESPACE_BEGIN
|
||||
class DLL_LINKAGE NetworkConnection :public std::enable_shared_from_this<NetworkConnection>, boost::noncopyable
|
||||
{
|
||||
static const int messageHeaderSize = sizeof(uint32_t);
|
||||
static const int messageMaxSize = 1024;
|
||||
static const int messageMaxSize = 65536; // arbitrary size to prevent potential massive allocation if we receive garbage input
|
||||
|
||||
std::shared_ptr<NetworkSocket> socket;
|
||||
|
||||
|
@ -56,6 +56,7 @@ void NetworkServer::onDisconnected(const std::shared_ptr<NetworkConnection> & co
|
||||
{
|
||||
assert(connections.count(connection));
|
||||
connections.erase(connection);
|
||||
onConnectionLost(connection);
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -27,6 +27,7 @@ class DLL_LINKAGE NetworkServer : boost::noncopyable, public INetworkConnectionL
|
||||
void onDisconnected(const std::shared_ptr<NetworkConnection> & connection) override;
|
||||
protected:
|
||||
virtual void onNewConnection(const std::shared_ptr<NetworkConnection> &) = 0;
|
||||
virtual void onConnectionLost(const std::shared_ptr<NetworkConnection> &) = 0;
|
||||
|
||||
void sendPacket(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message);
|
||||
|
||||
|
@ -109,27 +109,14 @@ void LobbyServer::sendMessage(const std::shared_ptr<NetworkConnection> & target,
|
||||
|
||||
void LobbyServer::onNewConnection(const std::shared_ptr<NetworkConnection> & connection)
|
||||
{
|
||||
// FIXME: move to authorization message reply
|
||||
auto history = database->getRecentMessageHistory();
|
||||
|
||||
JsonNode json;
|
||||
json["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;
|
||||
|
||||
json["messages"].Vector().push_back(jsonEntry);
|
||||
}
|
||||
|
||||
sendMessage(connection, json);
|
||||
}
|
||||
|
||||
void LobbyServer::onPacketReceived(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message)
|
||||
void LobbyServer::onConnectionLost(const std::shared_ptr<NetworkConnection> & connection)
|
||||
{
|
||||
activeAccounts.erase(connection);
|
||||
}
|
||||
|
||||
void LobbyServer::onPacketReceived(const std::shared_ptr<NetworkConnection> & connection, const std::vector<uint8_t> & message)
|
||||
{
|
||||
// FIXME: find better approach
|
||||
const char * payloadBegin = reinterpret_cast<const char*>(message.data());
|
||||
@ -137,7 +124,46 @@ void LobbyServer::onPacketReceived(const std::shared_ptr<NetworkConnection> &, c
|
||||
|
||||
if (json["type"].String() == "sendChatMessage")
|
||||
{
|
||||
database->insertChatMessage("Unknown", json["messageText"].String());
|
||||
if (activeAccounts.count(connection) == 0)
|
||||
return; // unauthenticated
|
||||
|
||||
std::string senderName = activeAccounts[connection].accountName;
|
||||
std::string messageText = json["messageText"].String();
|
||||
|
||||
database->insertChatMessage(senderName, messageText);
|
||||
|
||||
JsonNode reply;
|
||||
reply["type"].String() = "chatMessage";
|
||||
reply["messageText"].String() = messageText;
|
||||
reply["senderName"].String() = senderName;
|
||||
|
||||
for (auto const & connection : activeAccounts)
|
||||
sendMessage(connection.first, reply);
|
||||
}
|
||||
|
||||
if (json["type"].String() == "authentication")
|
||||
{
|
||||
std::string accountName = json["accountName"].String();
|
||||
|
||||
activeAccounts[connection].accountName = accountName;
|
||||
|
||||
auto history = database->getRecentMessageHistory();
|
||||
|
||||
JsonNode json;
|
||||
json["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;
|
||||
|
||||
json["messages"].Vector().push_back(jsonEntry);
|
||||
}
|
||||
|
||||
sendMessage(connection, json);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,9 +43,17 @@ public:
|
||||
|
||||
class LobbyServer : public NetworkServer
|
||||
{
|
||||
struct AccountState
|
||||
{
|
||||
std::string accountName;
|
||||
};
|
||||
|
||||
std::map<std::shared_ptr<NetworkConnection>, AccountState> activeAccounts;
|
||||
|
||||
std::unique_ptr<LobbyDatabase> database;
|
||||
|
||||
void onNewConnection(const std::shared_ptr<NetworkConnection> &) override;
|
||||
void onConnectionLost(const std::shared_ptr<NetworkConnection> &) override;
|
||||
void onPacketReceived(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message) override;
|
||||
|
||||
void sendMessage(const std::shared_ptr<NetworkConnection> & target, const JsonNode & json);
|
||||
|
Loading…
Reference in New Issue
Block a user