unreliable packets

This commit is contained in:
2024-08-20 19:27:20 +02:00
parent bebc306097
commit d0948f6ce5
5 changed files with 144 additions and 15 deletions

View File

@@ -27,6 +27,8 @@ class NetworkInterface : public godot::Node, public protocol::PacketDispatcher {
private: private:
void RecievePacketDataReliable(godot::PackedByteArray a_PacketData); void RecievePacketDataReliable(godot::PackedByteArray a_PacketData);
void RecievePacketDataUnreliable(godot::PackedByteArray a_PacketData);
void RecievePacketDataUnreliableOrdered(godot::PackedByteArray a_PacketData);
void OnPlayerConnected(PeerID a_PeerId); void OnPlayerConnected(PeerID a_PeerId);
void OnPlayerDisconnected(PeerID a_PeerId); void OnPlayerDisconnected(PeerID a_PeerId);

View File

@@ -12,7 +12,7 @@ namespace protocol {
* \enum PacketSender * \enum PacketSender
* \brief Indicate who should send a packet * \brief Indicate who should send a packet
*/ */
enum class PacketSender { enum class PacketSenderType {
/** Sent by clients and server */ /** Sent by clients and server */
Both, Both,
/** Sent by clients to the server */ /** Sent by clients to the server */
@@ -36,7 +36,7 @@ enum class PacketSender {
DeclarePacket(PlayerLeave, Reliable, Server) \ DeclarePacket(PlayerLeave, Reliable, Server) \
DeclarePacket(PlayerList, Reliable, Server) \ DeclarePacket(PlayerList, Reliable, Server) \
DeclarePacket(PlayerLogin, Reliable, Client) \ DeclarePacket(PlayerLogin, Reliable, Client) \
DeclarePacket(PlayerPositionAndRotation, Reliable, Both) \ DeclarePacket(PlayerPositionAndRotation, Unreliable, Both) \
DeclarePacket(PlayerShoot, Reliable, Both) \ DeclarePacket(PlayerShoot, Reliable, Both) \
DeclarePacket(PlayerStats, Reliable, Server) \ DeclarePacket(PlayerStats, Reliable, Server) \
DeclarePacket(ServerConfig, Reliable, Server) \ DeclarePacket(ServerConfig, Reliable, Server) \

View File

@@ -0,0 +1,57 @@
#pragma once
#include <blitz/protocol/PacketVisitor.h>
namespace blitz {
class NetworkInterface;
namespace protocol {
///////////////////////
/* PacketBroadcaster */
///////////////////////
#define DeclarePacket(PacketName, Reliability, ...) void Visit(const protocol::packets::PacketName& a_Packet) override;
class PacketBroadcaster : public protocol::PacketVisitor {
private:
NetworkInterface& m_NetworkInterface;
public:
PacketBroadcaster(NetworkInterface& a_NetworkInterface) : m_NetworkInterface(a_NetworkInterface) {}
void BroadcastPacket(const protocol::Packet& a_Packet) {
Check(a_Packet);
}
DeclareAllPacket()
};
//////////////////
/* PacketSender */
//////////////////
class PacketSender : public protocol::PacketVisitor {
private:
NetworkInterface& m_NetworkInterface;
PeerID m_PeerId;
public:
PacketSender(PeerID a_PeerId, NetworkInterface& a_NetworkInterface) : m_PeerId(a_PeerId), m_NetworkInterface(a_NetworkInterface) {}
void SendPacket(const protocol::Packet& a_Packet) {
Check(a_Packet);
}
DeclareAllPacket()
};
#undef DeclarePacket
} // namespace protocol
} // namespace blitz

View File

@@ -1,21 +1,37 @@
#include <blitz/godot/NetworkInterface.h> #include <blitz/godot/NetworkInterface.h>
#include <blitz/protocol/PacketFactory.h> #include <blitz/protocol/PacketFactory.h>
#include <blitz/protocol/PacketSender.h>
#include <blitz/protocol/PacketSerializer.h> #include <blitz/protocol/PacketSerializer.h>
#include <blitz/protocol/PacketVisitor.h>
#include <godot_cpp/classes/e_net_multiplayer_peer.hpp> #include <godot_cpp/classes/e_net_multiplayer_peer.hpp>
#include <godot_cpp/classes/multiplayer_api.hpp> #include <godot_cpp/classes/multiplayer_api.hpp>
#include <godot_cpp/classes/packed_scene.hpp> #include <godot_cpp/classes/packed_scene.hpp>
#include <godot_cpp/classes/resource_loader.hpp> #include <godot_cpp/classes/resource_loader.hpp>
#include <godot_cpp/variant/utility_functions.hpp> #include <godot_cpp/variant/utility_functions.hpp>
namespace blitz { namespace blitz {
#define RPC_CONFIG(functionName, rpc_mode, transfer_mode, call_local, channel) \
{ \
Dictionary config; \
config["rpc_mode"] = rpc_mode; \
config["transfer_mode"] = transfer_mode; \
config["call_local"] = call_local; \
config["channel"] = channel; \
rpc_config(functionName, config); \
}
static const char ServerScenePath[] = "res://Scenes/Network/server.tscn"; static const char ServerScenePath[] = "res://Scenes/Network/server.tscn";
using namespace godot; using namespace godot;
void NetworkInterface::_bind_methods() { void NetworkInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("RecievePacketDataReliable", "a_PacketData"), &NetworkInterface::RecievePacketDataReliable); ClassDB::bind_method(D_METHOD("RecievePacketDataReliable", "a_PacketData"), &NetworkInterface::RecievePacketDataReliable);
ClassDB::bind_method(D_METHOD("RecievePacketDataUnreliable", "a_PacketData"), &NetworkInterface::RecievePacketDataUnreliable);
ClassDB::bind_method(
D_METHOD("RecievePacketDataUnreliableOrdered", "a_PacketData"), &NetworkInterface::RecievePacketDataUnreliableOrdered);
// server // server
ADD_SIGNAL(MethodInfo("player_connected", PropertyInfo(Variant::INT, "peer_id"))); ADD_SIGNAL(MethodInfo("player_connected", PropertyInfo(Variant::INT, "peer_id")));
@@ -33,13 +49,10 @@ NetworkInterface::NetworkInterface() {}
NetworkInterface::~NetworkInterface() {} NetworkInterface::~NetworkInterface() {}
void NetworkInterface::_ready() { void NetworkInterface::_ready() {
// TODO: unreliable RPC_CONFIG("RecievePacketDataReliable", MultiplayerAPI::RPC_MODE_ANY_PEER, MultiplayerPeer::TRANSFER_MODE_RELIABLE, true, 0);
Dictionary config; RPC_CONFIG("RecievePacketDataUnreliable", MultiplayerAPI::RPC_MODE_ANY_PEER, MultiplayerPeer::TRANSFER_MODE_UNRELIABLE, true, 1);
config["rpc_mode"] = MultiplayerAPI::RPC_MODE_ANY_PEER; RPC_CONFIG("RecievePacketDataUnreliableOrdered", MultiplayerAPI::RPC_MODE_ANY_PEER,
config["transfer_mode"] = MultiplayerPeer::TRANSFER_MODE_RELIABLE; MultiplayerPeer::TRANSFER_MODE_UNRELIABLE_ORDERED, true, 2);
config["call_local"] = true;
config["channel"] = 0;
rpc_config("RecievePacketDataReliable", config);
get_multiplayer()->connect("peer_connected", callable_mp(this, &NetworkInterface::OnPlayerConnected)); get_multiplayer()->connect("peer_connected", callable_mp(this, &NetworkInterface::OnPlayerConnected));
get_multiplayer()->connect("peer_disconnected", callable_mp(this, &NetworkInterface::OnPlayerDisconnected)); get_multiplayer()->connect("peer_disconnected", callable_mp(this, &NetworkInterface::OnPlayerDisconnected));
@@ -49,13 +62,13 @@ void NetworkInterface::_ready() {
} }
void NetworkInterface::BroadcastPacket(const protocol::Packet& a_Packet) { void NetworkInterface::BroadcastPacket(const protocol::Packet& a_Packet) {
PackedByteArray byteArray = protocol::PacketSerializer::Serialize(a_Packet); protocol::PacketBroadcaster packetBroadcaster(*this);
rpc("RecievePacketDataReliable", byteArray); packetBroadcaster.BroadcastPacket(a_Packet);
} }
void NetworkInterface::SendPacket(PeerID a_Peer, const protocol::Packet& a_Packet) { void NetworkInterface::SendPacket(PeerID a_Peer, const protocol::Packet& a_Packet) {
PackedByteArray byteArray = protocol::PacketSerializer::Serialize(a_Packet); protocol::PacketSender packetSender(a_Peer, *this);
rpc_id(a_Peer, "RecievePacketDataReliable", byteArray); packetSender.SendPacket(a_Packet);
} }
void NetworkInterface::RecievePacketDataReliable(godot::PackedByteArray a_PacketData) { void NetworkInterface::RecievePacketDataReliable(godot::PackedByteArray a_PacketData) {
@@ -66,9 +79,27 @@ void NetworkInterface::RecievePacketDataReliable(godot::PackedByteArray a_Packet
} }
} }
void NetworkInterface::RecievePacketDataUnreliable(godot::PackedByteArray a_PacketData) {
// we have to copy the function body in order to preserve the remote sender id
auto packet = protocol::PacketSerializer::Deserialize(a_PacketData);
if (packet) {
packet->m_Sender = get_multiplayer()->get_remote_sender_id();
Dispatch(*packet);
}
}
void NetworkInterface::RecievePacketDataUnreliableOrdered(godot::PackedByteArray a_PacketData) {
// we have to copy the function body in order to preserve the remote sender id
auto packet = protocol::PacketSerializer::Deserialize(a_PacketData);
if (packet) {
packet->m_Sender = get_multiplayer()->get_remote_sender_id();
Dispatch(*packet);
}
}
Error NetworkInterface::JoinGame(const String& a_Address, uint16_t a_Port) { Error NetworkInterface::JoinGame(const String& a_Address, uint16_t a_Port) {
auto* peer = memnew(ENetMultiplayerPeer); auto* peer = memnew(ENetMultiplayerPeer);
Error error = peer->create_client(a_Address, a_Port); Error error = peer->create_client(a_Address, a_Port, 3);
if (error) { if (error) {
OnConnectFail(); OnConnectFail();
return error; return error;
@@ -80,7 +111,7 @@ Error NetworkInterface::JoinGame(const String& a_Address, uint16_t a_Port) {
Error NetworkInterface::CreateGame(uint16_t a_Port, bool a_Dedicated) { Error NetworkInterface::CreateGame(uint16_t a_Port, bool a_Dedicated) {
auto* peer = memnew(ENetMultiplayerPeer); auto* peer = memnew(ENetMultiplayerPeer);
Error error = peer->create_server(a_Port); Error error = peer->create_server(a_Port, 50, 3);
if (error) if (error)
return error; return error;

View File

@@ -0,0 +1,39 @@
#include <blitz/protocol/PacketSender.h>
#include <blitz/godot/NetworkInterface.h>
#include <blitz/protocol/PacketSerializer.h>
namespace blitz {
namespace protocol {
///////////////////////
/* PacketBroadcaster */
///////////////////////
#define DeclarePacket(PacketName, Reliability, ...) \
void PacketBroadcaster::Visit(const protocol::packets::PacketName& a_Packet) { \
m_NetworkInterface.rpc("RecievePacketData" #Reliability, protocol::PacketSerializer::Serialize(a_Packet)); \
}
DeclareAllPacket()
#undef DeclarePacket
//////////////////
/* PacketSender */
//////////////////
#define DeclarePacket(PacketName, Reliability, ...) \
void PacketSender::Visit(const protocol::packets::PacketName& a_Packet) { \
m_NetworkInterface.rpc_id(m_PeerId, "RecievePacketData" #Reliability, protocol::PacketSerializer::Serialize(a_Packet)); \
}
DeclareAllPacket()
#undef DeclarePacket
} // namespace protocol
} // namespace blitz