1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-26 03:52:01 +02:00

Implemented messages sending and storing in database

This commit is contained in:
Ivan Savenko 2023-11-12 15:32:54 +02:00
parent dff9cf39c0
commit f10b6df989
8 changed files with 152 additions and 20 deletions

View File

@ -13,9 +13,16 @@
#include "../gui/CGuiHandler.h" #include "../gui/CGuiHandler.h"
#include "../gui/WindowHandler.h" #include "../gui/WindowHandler.h"
#include "../widgets/TextControls.h"
#include "../windows/InfoWindows.h" #include "../windows/InfoWindows.h"
LobbyClient::LobbyClient(LobbyWindow * window)
: window(window)
{
}
void LobbyClient::onPacketReceived(const std::vector<uint8_t> & message) void LobbyClient::onPacketReceived(const std::vector<uint8_t> & message)
{ {
@ -33,22 +40,42 @@ void LobbyClient::onDisconnected()
CInfoWindow::showInfoDialog("Connection to game lobby was lost!", {}); CInfoWindow::showInfoDialog("Connection to game lobby was lost!", {});
} }
LobbyWidget::LobbyWidget() void LobbyClient::sendMessage(const JsonNode & data)
{
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);
sendPacket(payloadBuffer);
}
LobbyWidget::LobbyWidget(LobbyWindow * window)
: window(window)
{ {
addCallback("closeWindow", [](int) { GH.windows().popWindows(1); }); addCallback("closeWindow", [](int) { GH.windows().popWindows(1); });
addCallback("sendMessage", [this](int) { this->window->doSendChatMessage(); });
const JsonNode config(JsonPath::builtin("config/widgets/lobbyWindow.json")); const JsonNode config(JsonPath::builtin("config/widgets/lobbyWindow.json"));
build(config); build(config);
} }
std::shared_ptr<CTextInput> LobbyWidget::getMessageInput()
{
return widget<CTextInput>("messageInput");
}
LobbyWindow::LobbyWindow(): LobbyWindow::LobbyWindow():
CWindowObject(BORDERED) CWindowObject(BORDERED)
{ {
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE; OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
widget = std::make_shared<LobbyWidget>(); widget = std::make_shared<LobbyWidget>(this);
pos = widget->pos; pos = widget->pos;
center(); center();
connection = std::make_shared<LobbyClient>(); connection = std::make_shared<LobbyClient>(this);
connection->start("127.0.0.1", 30303); connection->start("127.0.0.1", 30303);
@ -59,3 +86,16 @@ void LobbyWindow::tick(uint32_t msPassed)
{ {
connection->poll(); connection->poll();
} }
void LobbyWindow::doSendChatMessage()
{
std::string messageText = widget->getMessageInput()->getText();
JsonNode toSend;
toSend["type"].String() = "sendChatMessage";
toSend["messageText"].String() = messageText;
connection->sendMessage(toSend);
widget->getMessageInput()->setText("");
}

View File

@ -14,19 +14,29 @@
#include "../../lib/network/NetworkClient.h" #include "../../lib/network/NetworkClient.h"
class LobbyWindow;
class LobbyWidget : public InterfaceObjectConfigurable class LobbyWidget : public InterfaceObjectConfigurable
{ {
LobbyWindow * window;
public: public:
LobbyWidget(); LobbyWidget(LobbyWindow * window);
std::shared_ptr<CTextInput> getMessageInput();
}; };
class LobbyClient : public NetworkClient class LobbyClient : public NetworkClient
{ {
LobbyWindow * window;
void onPacketReceived(const std::vector<uint8_t> & message) override; void onPacketReceived(const std::vector<uint8_t> & message) override;
void onConnectionFailed(const std::string & errorMessage) override; void onConnectionFailed(const std::string & errorMessage) override;
void onDisconnected() override; void onDisconnected() override;
public: public:
LobbyClient() = default; explicit LobbyClient(LobbyWindow * window);
void sendMessage(const JsonNode & data);
}; };
class LobbyWindow : public CWindowObject class LobbyWindow : public CWindowObject
@ -38,4 +48,8 @@ class LobbyWindow : public CWindowObject
public: public:
LobbyWindow(); LobbyWindow();
void doSendChatMessage();
void onGameChatMessage(std::string sender, std::string message, std::string when);
}; };

View File

@ -85,15 +85,25 @@
"position": {"x": 440, "y": 53}, "position": {"x": 440, "y": 53},
"text" : "Game Chat" "text" : "Game Chat"
}, },
{
"type": "textBox",
"name": "gameChat",
"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}
},
{ {
"type": "areaFilled", "type": "areaFilled",
"rect": {"x": 430, "y": 565, "w": 395, "h": 25} "rect": {"x": 430, "y": 565, "w": 395, "h": 25}
}, },
{ {
"type": "labelTitle", "name" : "messageInput",
"position": {"x": 440, "y": 568}, "type": "textInput",
"text" : "Enter Message" "alignment" : "left",
"rect": {"x": 440, "y": 568, "w": 375, "h": 20}
}, },
{ {
@ -112,7 +122,7 @@
"image": "settingsWindow/button80", "image": "settingsWindow/button80",
"help": "core.help.288", "help": "core.help.288",
"callback": "closeWindow", "callback": "closeWindow",
"hotkey": "globalReturn", "hotkey": "globalCancel",
"items": "items":
[ [
{ {
@ -130,8 +140,8 @@
"position": {"x": 828, "y": 565}, "position": {"x": 828, "y": 565},
"image": "settingsWindow/button32", "image": "settingsWindow/button32",
"help": "core.help.288", "help": "core.help.288",
"callback": "closeWindow", "callback": "sendMessage",
"hotkey": "globalReturn", "hotkey": "globalAccept",
"items": "items":
[ [
{ {
@ -149,8 +159,6 @@
"position": {"x": 10, "y": 520}, "position": {"x": 10, "y": 520},
"image": "settingsWindow/button190", "image": "settingsWindow/button190",
"help": "core.help.288", "help": "core.help.288",
"callback": "closeWindow",
"hotkey": "globalReturn",
"items": "items":
[ [
{ {
@ -168,8 +176,6 @@
"position": {"x": 10, "y": 555}, "position": {"x": 10, "y": 555},
"image": "settingsWindow/button190", "image": "settingsWindow/button190",
"help": "core.help.288", "help": "core.help.288",
"callback": "closeWindow",
"hotkey": "globalReturn",
"items": "items":
[ [
{ {

View File

@ -32,12 +32,12 @@ protected:
virtual void onConnectionFailed(const std::string & errorMessage) = 0; virtual void onConnectionFailed(const std::string & errorMessage) = 0;
virtual void onDisconnected() = 0; virtual void onDisconnected() = 0;
void sendPacket(const std::vector<uint8_t> & message);
public: public:
NetworkClient(); NetworkClient();
virtual ~NetworkClient() = default; virtual ~NetworkClient() = default;
void start(const std::string & host, uint16_t port); void start(const std::string & host, uint16_t port);
void sendPacket(const std::vector<uint8_t> & message);
void run(); void run();
void poll(); void poll();
}; };

View File

@ -77,7 +77,7 @@ void NetworkConnection::onPacketReceived(const boost::system::error_code & ec, u
message.resize(expectedPacketSize); message.resize(expectedPacketSize);
std::istream istream(&readBuffer); std::istream istream(&readBuffer);
istream.read(reinterpret_cast<char *>(message.data()), messageHeaderSize); istream.read(reinterpret_cast<char *>(message.data()), expectedPacketSize);
listener.onPacketReceived(shared_from_this(), message); listener.onPacketReceived(shared_from_this(), message);

View File

@ -12,6 +12,8 @@
#include "SQLiteConnection.h" #include "SQLiteConnection.h"
#include "../lib/JsonNode.h"
#include <boost/uuid/uuid_generators.hpp> #include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp> #include <boost/uuid/uuid_io.hpp>
@ -20,6 +22,53 @@ static const int LISTENING_PORT = 30303;
//static const std::string SERVER_NAME = GameConstants::VCMI_VERSION + " (server)"; //static const std::string SERVER_NAME = GameConstants::VCMI_VERSION + " (server)";
//static const std::string SERVER_UUID = boost::uuids::to_string(boost::uuids::random_generator()()); //static const std::string SERVER_UUID = boost::uuids::to_string(boost::uuids::random_generator()());
void LobbyDatabase::prepareStatements()
{
static const std::string insertChatMessageText = R"(
INSERT INTO chatMessages(senderName, messageText) VALUES( ?, ?);
)";
insertChatMessageStatement = database->prepare(insertChatMessageText);
}
void LobbyDatabase::createTableChatMessages()
{
static const std::string statementText = R"(
CREATE TABLE IF NOT EXISTS chatMessages (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
senderName TEXT,
messageText TEXT,
sendTime TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
);
)";
auto statement = database->prepare(statementText);
statement->execute();
}
void LobbyDatabase::initializeDatabase()
{
createTableChatMessages();
}
LobbyDatabase::LobbyDatabase()
{
database = SQLiteInstance::open(DATABASE_PATH, true);
if (!database)
throw std::runtime_error("Failed to open SQLite database!");
initializeDatabase();
prepareStatements();
}
void LobbyDatabase::insertChatMessage(const std::string & sender, const std::string & messageText)
{
insertChatMessageStatement->setBinds(sender, messageText);
insertChatMessageStatement->execute();
insertChatMessageStatement->reset();
}
void LobbyServer::onNewConnection(const std::shared_ptr<NetworkConnection> &) void LobbyServer::onNewConnection(const std::shared_ptr<NetworkConnection> &)
{ {
@ -27,12 +76,19 @@ void LobbyServer::onNewConnection(const std::shared_ptr<NetworkConnection> &)
void LobbyServer::onPacketReceived(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message) void LobbyServer::onPacketReceived(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message)
{ {
// FIXME: find better approach
const char * payloadBegin = reinterpret_cast<const char*>(message.data());
JsonNode json(payloadBegin, message.size());
if (json["type"].String() == "sendChatMessage")
{
database->insertChatMessage("Unknown", json["messageText"].String());
}
} }
LobbyServer::LobbyServer() LobbyServer::LobbyServer()
: database(new LobbyDatabase())
{ {
database = SQLiteInstance::open(DATABASE_PATH, true);
} }
int main(int argc, const char * argv[]) int main(int argc, const char * argv[])

View File

@ -12,10 +12,25 @@
#include "../lib/network/NetworkServer.h" #include "../lib/network/NetworkServer.h"
class SQLiteInstance; class SQLiteInstance;
class SQLiteStatement;
class LobbyDatabase
{
std::unique_ptr<SQLiteInstance> database;
std::unique_ptr<SQLiteStatement> insertChatMessageStatement;
void initializeDatabase();
void prepareStatements();
void createTableChatMessages();
public:
LobbyDatabase();
void insertChatMessage(const std::string & sender, const std::string & messageText);
};
class LobbyServer : public NetworkServer class LobbyServer : public NetworkServer
{ {
std::unique_ptr<SQLiteInstance> database; std::unique_ptr<LobbyDatabase> database;
void onNewConnection(const std::shared_ptr<NetworkConnection> &) override; void onNewConnection(const std::shared_ptr<NetworkConnection> &) override;
void onPacketReceived(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message) override; void onPacketReceived(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message) override;

View File

@ -16,7 +16,8 @@ static void on_sqlite_error( sqlite3 * connection, [[maybe_unused]] int result )
{ {
if ( result != SQLITE_OK ) if ( result != SQLITE_OK )
{ {
printf( "sqlite error: %s\n", sqlite3_errmsg( connection ) ); const char * message = sqlite3_errmsg( connection );
printf( "sqlite error: %s\n", message );
} }
assert( result == SQLITE_OK ); assert( result == SQLITE_OK );