#ifndef HYPERSWARM_PACKET_QUEUE_H
#define HYPERSWARM_PACKET_QUEUE_H
#include <cstdint>
#include <cstring>
#include <deque>
#include <mutex>
#include <vector>
// Transfer mode matching Godot's MultiplayerPeer::TransferMode
enum PacketTransferMode {
PACKET_UNRELIABLE = 0,
PACKET_UNRELIABLE_ORDERED = 1,
PACKET_RELIABLE = 2
};
struct Packet {
std::vector<uint8_t> data;
int32_t peer_id;
int32_t channel;
PacketTransferMode mode;
Packet()
: peer_id(0), channel(0), mode(PACKET_RELIABLE) {}
Packet(const uint8_t *p_data, int32_t p_size, int32_t p_peer, int32_t p_channel, PacketTransferMode p_mode)
: data(p_data, p_data + p_size), peer_id(p_peer), channel(p_channel), mode(p_mode) {}
};
// Thread-safe packet queue for passing data between the UDX network thread
// and Godot's main thread.
class PacketQueue {
public:
void push(const Packet &pkt) {
std::lock_guard<std::mutex> lock(_mutex);
_queue.push_back(pkt);
}
void push(Packet &&pkt) {
std::lock_guard<std::mutex> lock(_mutex);
_queue.push_back(std::move(pkt));
}
bool pop(Packet &out) {
std::lock_guard<std::mutex> lock(_mutex);
if (_queue.empty()) return false;
out = std::move(_queue.front());
_queue.pop_front();
return true;
}
// Peek without removing — used by _get_packet_peer() etc.
bool peek(Packet &out) const {
std::lock_guard<std::mutex> lock(_mutex);
if (_queue.empty()) return false;
out = _queue.front();
return true;
}
int32_t size() const {
std::lock_guard<std::mutex> lock(_mutex);
return static_cast<int32_t>(_queue.size());
}
bool empty() const {
std::lock_guard<std::mutex> lock(_mutex);
return _queue.empty();
}
void clear() {
std::lock_guard<std::mutex> lock(_mutex);
_queue.clear();
}
private:
std::deque<Packet> _queue;
mutable std::mutex _mutex;
};
#endif // HYPERSWARM_PACKET_QUEUE_H