29 PRETTY_INFO <<
"UDP Socket initialized on port " << _port << std::endl;
31 catch (
const std::exception &e) {
32 PRETTY_CRITICAL <<
"Error initializing UDP socket: " << e.what() << std::endl;
39 std::vector<uint8_t> buffer(1024);
40 asio::ip::udp::endpoint senderEndpoint;
42 size_t bytesReceived = _socket.receive_from(asio::buffer(buffer), senderEndpoint);
43 if (bytesReceived > 0) {
44 std::vector<uint8_t> receivedData(buffer.begin(), buffer.begin() + bytesReceived);
47 std::cerr << packet.
print() << std::endl;
51 catch (
const std::exception &e) {
52 PRETTY_ERROR <<
"Error handling messages: " << e.what() << std::endl;
59 std::cerr <<
"Cannot send message: No active connection." << std::endl;
68 std::string serializedMessage = convertMessageToString(message);
71 asio::ip::udp::endpoint remoteEndpoint(asio::ip::make_address(_ip), _port);
72 std::vector<uint8_t> data(serializedMessage.begin(), serializedMessage.end());
74 _socket.send_to(asio::buffer(data), remoteEndpoint);
75 PRETTY_DEBUG <<
"Message : " << std::hex << serializedMessage <<
" sent to " << _ip <<
":" << _port << std::endl;
77 catch (
const std::exception &e) {
97 return _socket.is_open();
103 std::memcpy(&value, bytes,
sizeof(
float));
109 std::ostringstream oss;
110 for (uint8_t
byte : bytes) {
111 oss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(
byte) <<
" ";
125 switch (result.
type) {
127 std::memcpy(result.
info.
username, message.data() + 1, 8);
133 std::memcpy(&
id, &message[1],
sizeof(std::size_t));
134 PRECISE_DEBUG <<
"DISCONNECT Message\nEntity ID: " <<
id <<
"\n";
141 std::memcpy(&
id, &message[1],
sizeof(std::size_t));
142 x = bytesToFloat(&message[1 +
sizeof(std::size_t)]);
143 y = bytesToFloat(&message[1 +
sizeof(std::size_t) +
sizeof(
float)]);
144 PRETTY_DEBUG <<
"MOVE Message\nEntity ID: " <<
id <<
"\nPosition: (" << x <<
", " << y <<
")\n";
153 std::memcpy(&
id, &message[1],
sizeof(std::size_t));
154 PRETTY_DEBUG <<
"SHOOT Message\nEntity ID: " <<
id <<
"\n";
163 std::memcpy(&
id, &message[1],
sizeof(std::size_t));
164 std::memcpy(&asset, &message[1 +
sizeof(std::size_t)],
sizeof(
int));
165 x = bytesToFloat(&message[1 +
sizeof(std::size_t) +
sizeof(
int)]);
166 y = bytesToFloat(&message[1 +
sizeof(std::size_t) +
sizeof(
int) +
sizeof(
float)]);
167 PRETTY_CRITICAL <<
"SPAWN Message\nEntity ID: " <<
id <<
"\nAsset ID: " << asset <<
"\nPosition: (" << x <<
", " << y <<
")\n";
177 std::memcpy(&
id, &message[1],
sizeof(std::size_t));
178 PRETTY_DEBUG <<
"KILL Message\nEntity ID: " <<
id <<
"\n";
185 PRETTY_DEBUG <<
"DAMAGE Message\nEntity ID: " <<
id <<
"\n";
186 std::memcpy(&
id, &message[1],
sizeof(std::size_t));
192 uint8_t status = message[1];
194 if (status == 0x00) {
196 }
else if (status == 0x01) {
198 }
else if (status == 0xFF) {
211 uint8_t errorCode = message[1];
228 std::vector<uint8_t> serializedMessage(1);
229 serializedMessage[0] =
static_cast<uint8_t
>(message.
type);
231 switch (message.
type) {
234 serializedMessage.resize(10);
235 std::memcpy(serializedMessage.data() + 1, message.
info.
username, 8);
236 serializedMessage[9] = 0;
241 serializedMessage.resize(1 +
sizeof(std::size_t));
242 std::memcpy(serializedMessage.data() + 1, &message.
id,
sizeof(std::size_t));
247 serializedMessage.resize(1 +
sizeof(std::size_t) +
sizeof(
float) * 2);
248 std::memcpy(serializedMessage.data() + 1, &message.
id,
sizeof(std::size_t));
249 std::memcpy(serializedMessage.data() + 1 +
sizeof(std::size_t), &message.
info.
coords.first,
sizeof(
float));
250 std::memcpy(serializedMessage.data() + 1 +
sizeof(std::size_t) +
sizeof(
float), &message.
info.
coords.second,
sizeof(
float));
255 serializedMessage.resize(1 +
sizeof(std::size_t));
256 std::memcpy(serializedMessage.data() + 1, &message.
id,
sizeof(std::size_t));
264 std::string result(serializedMessage.begin(), serializedMessage.end());
292 if (_playerName == playerName) {
296 _playerName = playerName;
301 if (_ip == ip && _port == port) {
318 std::array<char, 2048> recvBuffer;
319 asio::ip::udp::endpoint remoteEndpoint;
321 while (_continueListening) {
323 size_t bytesRecv = _socket.receive_from(
324 asio::buffer(recvBuffer), remoteEndpoint, 0, ec
328 PRETTY_ERROR <<
"[Client] Receive error: " << ec.message() <<
"\n";
333 std::vector<uint8_t> message(recvBuffer.begin(), recvBuffer.begin() + bytesRecv);
335 _bufferedMessages.push_back(translatedMessage);
341 catch (
const std::exception &e) {
342 PRETTY_CRITICAL <<
"[Client] Exception in receiveMessage: " << e.what() <<
"\n";
348 _continueListening =
true;
353 _continueListening =
false;
358 std::vector<GUI::Network::MessageNode> list = this->_bufferedMessages;
359 _bufferedMessages.clear();
363void GUI::Network::NetworkManager::_connect()
372 if (_ip.empty() || _port <= 0 || _port > 65535) {
373 throw std::invalid_argument(
"Invalid IP or port for connection.");
376 asio::ip::udp::endpoint remoteEndpoint(asio::ip::make_address(_ip), _port);
379 _socket.open(asio::ip::udp::v4(), ec);
381 std::cerr <<
"[CLIENT] can't open socket bc: " << ec.message() << std::endl;
383 asio::ip::udp::endpoint localEndpoint(asio::ip::udp::v4(), 0);
384 _socket.bind(localEndpoint);
386 PRETTY_SUCCESS <<
"Connected to server at " << _ip <<
":" << _port << std::endl;
392 asio::ip::udp::endpoint remoteEndpoint(asio::ip::make_address(_ip), _port);
393 _socket.send_to(asio::buffer(serializedData), remoteEndpoint);
394 _connectionActive =
true;
396 catch (
const std::exception &e) {
397 PRETTY_ERROR <<
"Error sending CONNECT packet: " << e.what() << std::endl;
400 catch (
const std::exception &e) {
401 PRETTY_CRITICAL <<
"Error connecting to server: " << e.what() << std::endl;
402 _connectionActive =
false;
406void GUI::Network::NetworkManager::_disconnect()
409 if (_socket.is_open()) {
411 PRECISE_DEBUG <<
"Disconnected from server at " << _ip <<
":" << _port << std::endl;
413 PRETTY_ERROR <<
"Socket is already closed." << std::endl;
415 _connectionActive =
false;
417 catch (
const std::exception &e) {
418 PRETTY_CRITICAL <<
"Error disconnecting from server: " << e.what() << std::endl;
#define PRETTY_ERROR
Error log with details and colour.
#define PRECISE_DEBUG
Debug log with precise details.
#define PRETTY_DEBUG
Debug log with details and colour.
#define PRETTY_INFO
Info log with details and colour.
#define PRETTY_CRITICAL
Critical log with details and colour.
#define PRETTY_SUCCESS
Success log with details and colour.
This file defines the NetworkManager class, which handles UDP socket communication for sending and re...
const bool isConnected() const
Checks if the connection is active.
void setAddress(const std::string &ip, const unsigned int port)
Sets both the IP address and port for communication.
~NetworkManager()
Destroy the Network Manager object.
std::vector< GUI::Network::MessageNode > getBufferedMessages()
NetworkManager(const std::uint32_t entityId=0)
Constructs a NetworkManager instance with an optional entity ID.
void startGame()
starts a game by sending CONNECT TO server.
void sendMessage(const MessageNode &message)
Sends a message to the server.
void initialize()
Initializes the UDP socket and binds it to a local endpoint. This function opens the socket and binds...
std::string bytesToHex(const std::vector< uint8_t > &bytes)
Converts a byte array to a hexadecimal string representation.
void setPlayerName(const std::string &name)
Sets the player's name for identification.
void handleMessages()
Handles incoming messages on the UDP socket.
void startReceivingMessages()
void setIp(const std::string &ip)
Sets the IP address for communication.
void receiveMessage()
Receives messages continuously from the server.
std::string convertMessageToString(const MessageNode &message)
Translates a MessageNode into a string.
void setPort(const unsigned int port)
Sets the port for communication.
MessageNode translateMessage(const std::vector< uint8_t > &message)
Translates a message into a MessageNode.
float bytesToFloat(const uint8_t *bytes)
Converts a byte array to a floating-point value.
void stopReceivingMessages()
Represents a packet for the custom binary UDP protocol.
const std::string print() const
Prints a string representation of the packet's contents, for debugging purposes.
static std::vector< uint8_t > serialize(const Packet &packet)
Serializes a Packet object into a vector of bytes suitable for network transmission.
static Packet deserialize(const std::vector< uint8_t > &data)
Deserializes a packet from a vector of bytes received over the network.
MessageType
Enum for the different message types in the UDP protocol.
const std::string myToString(const Rect< RectType > &rectangle)
Converts a Rect<T> object to its string representation.
std::pair< float, float > coords
Coordinates associated with the event, such as the position of an entity.
char username[9]
Username of player connecting.
int assetId
ID representing the game asset related to the event (e.g., entity or object).