From df5e2c86dcf4f151e5674edd6fe3e6ed598be4c1 Mon Sep 17 00:00:00 2001 From: Sara Date: Sat, 11 Oct 2025 23:11:09 +0200 Subject: [PATCH] feat: work on client logic & integration --- .../scenes/flatscreen_root.tscn | 5 + modules/you_done_it/server_node.cpp | 29 +++++ modules/you_done_it/server_node.h | 13 ++ modules/you_done_it/ydi_client.cpp | 114 ++++++++++++++++++ modules/you_done_it/ydi_client.h | 12 ++ 5 files changed, 173 insertions(+) create mode 100644 flatscreen-project/scenes/flatscreen_root.tscn create mode 100644 modules/you_done_it/server_node.cpp create mode 100644 modules/you_done_it/server_node.h create mode 100644 modules/you_done_it/ydi_client.cpp create mode 100644 modules/you_done_it/ydi_client.h diff --git a/flatscreen-project/scenes/flatscreen_root.tscn b/flatscreen-project/scenes/flatscreen_root.tscn new file mode 100644 index 00000000..1eedae57 --- /dev/null +++ b/flatscreen-project/scenes/flatscreen_root.tscn @@ -0,0 +1,5 @@ +[gd_scene format=3 uid="uid://dosb4sb7pvss4"] + +[node name="FlatscreenRoot" type="FlatscreenRoot"] +offset_right = 40.0 +offset_bottom = 40.0 diff --git a/modules/you_done_it/server_node.cpp b/modules/you_done_it/server_node.cpp new file mode 100644 index 00000000..6866318c --- /dev/null +++ b/modules/you_done_it/server_node.cpp @@ -0,0 +1,29 @@ +#include "server_node.h" +#include "ydi_server.h" +#include + +void ServerNode::_bind_methods() {} + +void ServerNode::enter_tree() { + ydi::server::open(); +} + +void ServerNode::exit_tree() { + ydi::server::close(); +} + +void ServerNode::_notification(int what) { + if (Engine::get_singleton()->is_editor_hint()) { + return; + } + switch (what) { + case NOTIFICATION_ENTER_TREE: + enter_tree(); + return; + case NOTIFICATION_EXIT_TREE: + exit_tree(); + return; + default: + return; + } +} diff --git a/modules/you_done_it/server_node.h b/modules/you_done_it/server_node.h new file mode 100644 index 00000000..4f53de93 --- /dev/null +++ b/modules/you_done_it/server_node.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +class ServerNode : public Node { + GDCLASS(ServerNode, Node); + static void _bind_methods(); + void enter_tree(); + void exit_tree(); + +protected: + void _notification(int what); +}; diff --git a/modules/you_done_it/ydi_client.cpp b/modules/you_done_it/ydi_client.cpp new file mode 100644 index 00000000..c4b287d9 --- /dev/null +++ b/modules/you_done_it/ydi_client.cpp @@ -0,0 +1,114 @@ +#include "ydi_client.h" +#include "core/string/print_string.h" +#include "you_done_it/ydi_networking.h" +#include +#include +#include +#include +#include +#include + +namespace ydi::client { +struct Connection { + std::optional server; + std::optional context{ std::nullopt }; + std::optional socket{ std::nullopt }; + std::recursive_mutex mtx; + std::atomic status; + std::atomic stop_threads; +}; + +std::optional connection{ std::nullopt }; + +std::optional receive_thread{ std::nullopt }; + +void handle_ok(zmq::multipart_t const &message) { + MessageType type{ to_message_type(message[1]) }; + switch (type) { + default: // no need to handle every OK, just some relevant ones + return; + case CONNECT: + connection->status = AUTHENTICATED; + } +} + +void handle_message(zmq::multipart_t const &message) { + MessageType type{ to_message_type(message[0]) }; + switch (type) { + case OK: + handle_ok(message); + default: + print_error(vformat("Client: Unhandled message type received: ", type, message[0].to_string().c_str())); + return; + } +} + +void receive_thread_entry() { + zmq::multipart_t message{}; + while (!connection->stop_threads) { + using namespace std::chrono_literals; + std::this_thread::sleep_for(10ms); + std::scoped_lock lock{ connection->mtx }; + if (message.recv(*connection->socket)) { + handle_message(message); + } + } +} + +void connect(String const &url) { + connection.emplace(); + print_line("Client: Connecting to ", url); + try { + connection->context.emplace(1); + } catch (...) { + connection.reset(); + print_line("Client: Failed to create context"); + return; + } + print_line("Client: Created context"); + try { + connection->socket.emplace(*connection->context, zmq::socket_type::dealer); + } catch (...) { + connection->context->close(); + connection->context.reset(); + connection.reset(); + print_line("Client: Failed to create socket"); + return; + } + print_line("Client: Created socket"); + try { + CharStringT cstrurl{ url.ascii() }; + std::string server{ cstrurl.get_data() }; + server = "tcp://" + server + ":6667"; + connection->socket->connect(server); + connection->server = server; + } catch (...) { + connection->socket->close(); + connection->socket.reset(); + connection->context->close(); + connection->context.reset(); + connection.reset(); + print_line("Client: Failed to connect to server"); + } + print_line("Client: connected to server"); + receive_thread.emplace(receive_thread_entry); +} + +void disconnect() { + if (connection) { + std::scoped_lock lock{ connection->mtx }; + if (receive_thread && receive_thread->joinable()) { + receive_thread->join(); + } + if (connection->socket) { + connection->socket->close(); + connection->socket.reset(); + } + if (connection->context) { + connection->context->shutdown(); + connection->context.reset(); + } + } + connection.reset(); +} +} //namespace ydi::client diff --git a/modules/you_done_it/ydi_client.h b/modules/you_done_it/ydi_client.h new file mode 100644 index 00000000..f39dd92c --- /dev/null +++ b/modules/you_done_it/ydi_client.h @@ -0,0 +1,12 @@ +#pragma once + +#include "ydi_networking.h" +#include + +namespace ydi::client { +void connect(String const &url); +void disconnect(); +namespace send { +void reveal_clue(ClueID id); +} //namespace send +} //namespace ydi::client