1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +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/WindowHandler.h"
#include "../widgets/TextControls.h"
#include "../windows/InfoWindows.h"
LobbyClient::LobbyClient(LobbyWindow * window)
: window(window)
{
}
void LobbyClient::onPacketReceived(const std::vector<uint8_t> & message)
{
@ -33,22 +40,42 @@ void LobbyClient::onDisconnected()
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("sendMessage", [this](int) { this->window->doSendChatMessage(); });
const JsonNode config(JsonPath::builtin("config/widgets/lobbyWindow.json"));
build(config);
}
std::shared_ptr<CTextInput> LobbyWidget::getMessageInput()
{
return widget<CTextInput>("messageInput");
}
LobbyWindow::LobbyWindow():
CWindowObject(BORDERED)
{
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
widget = std::make_shared<LobbyWidget>();
widget = std::make_shared<LobbyWidget>(this);
pos = widget->pos;
center();
connection = std::make_shared<LobbyClient>();
connection = std::make_shared<LobbyClient>(this);
connection->start("127.0.0.1", 30303);
@ -59,3 +86,16 @@ void LobbyWindow::tick(uint32_t msPassed)
{
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"
class LobbyWindow;
class LobbyWidget : public InterfaceObjectConfigurable
{
LobbyWindow * window;
public:
LobbyWidget();
LobbyWidget(LobbyWindow * window);
std::shared_ptr<CTextInput> getMessageInput();
};
class LobbyClient : public NetworkClient
{
LobbyWindow * window;
void onPacketReceived(const std::vector<uint8_t> & message) override;
void onConnectionFailed(const std::string & errorMessage) override;
void onDisconnected() override;
public:
LobbyClient() = default;
explicit LobbyClient(LobbyWindow * window);
void sendMessage(const JsonNode & data);
};
class LobbyWindow : public CWindowObject
@ -38,4 +48,8 @@ class LobbyWindow : public CWindowObject
public:
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},
"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",
"rect": {"x": 430, "y": 565, "w": 395, "h": 25}
},
{
"type": "labelTitle",
"position": {"x": 440, "y": 568},
"text" : "Enter Message"
"name" : "messageInput",
"type": "textInput",
"alignment" : "left",
"rect": {"x": 440, "y": 568, "w": 375, "h": 20}
},
{
@ -112,7 +122,7 @@
"image": "settingsWindow/button80",
"help": "core.help.288",
"callback": "closeWindow",
"hotkey": "globalReturn",
"hotkey": "globalCancel",
"items":
[
{
@ -130,8 +140,8 @@
"position": {"x": 828, "y": 565},
"image": "settingsWindow/button32",
"help": "core.help.288",
"callback": "closeWindow",
"hotkey": "globalReturn",
"callback": "sendMessage",
"hotkey": "globalAccept",
"items":
[
{
@ -149,8 +159,6 @@
"position": {"x": 10, "y": 520},
"image": "settingsWindow/button190",
"help": "core.help.288",
"callback": "closeWindow",
"hotkey": "globalReturn",
"items":
[
{
@ -168,8 +176,6 @@
"position": {"x": 10, "y": 555},
"image": "settingsWindow/button190",
"help": "core.help.288",
"callback": "closeWindow",
"hotkey": "globalReturn",
"items":
[
{

View File

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

View File

@ -77,7 +77,7 @@ void NetworkConnection::onPacketReceived(const boost::system::error_code & ec, u
message.resize(expectedPacketSize);
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);

View File

@ -12,6 +12,8 @@
#include "SQLiteConnection.h"
#include "../lib/JsonNode.h"
#include <boost/uuid/uuid_generators.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_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> &)
{
@ -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)
{
// 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()
: database(new LobbyDatabase())
{
database = SQLiteInstance::open(DATABASE_PATH, true);
}
int main(int argc, const char * argv[])

View File

@ -12,10 +12,25 @@
#include "../lib/network/NetworkServer.h"
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
{
std::unique_ptr<SQLiteInstance> database;
std::unique_ptr<LobbyDatabase> database;
void onNewConnection(const std::shared_ptr<NetworkConnection> &) 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 )
{
printf( "sqlite error: %s\n", sqlite3_errmsg( connection ) );
const char * message = sqlite3_errmsg( connection );
printf( "sqlite error: %s\n", message );
}
assert( result == SQLITE_OK );