generated from Persson-dev/Godot-Xmake
better networking
This commit is contained in:
@@ -70,13 +70,13 @@ void Lobby::Shutdown() {
|
||||
}
|
||||
}
|
||||
|
||||
void Lobby::OnPlayerConnected(int64_t a_PeerId) {
|
||||
void Lobby::OnPlayerConnected(PeerID a_PeerId) {
|
||||
if (get_multiplayer()->is_server()) {
|
||||
emit_signal("player_connected", a_PeerId);
|
||||
}
|
||||
}
|
||||
|
||||
void Lobby::OnPlayerDisconnected(int64_t a_PeerId) {
|
||||
void Lobby::OnPlayerDisconnected(PeerID a_PeerId) {
|
||||
if (get_multiplayer()->is_server()) {
|
||||
emit_signal("player_disconnected", a_PeerId);
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@ class Lobby : public godot::Node {
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
void OnPlayerConnected(int64_t a_PeerId);
|
||||
void OnPlayerDisconnected(int64_t a_PeerId);
|
||||
void OnPlayerConnected(PeerID a_PeerId);
|
||||
void OnPlayerDisconnected(PeerID a_PeerId);
|
||||
void OnConnectOk();
|
||||
void OnConnectFail();
|
||||
void OnServerDisconnected();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "NetworkInterface.h"
|
||||
|
||||
#include <blitz/protocol/PacketFactory.h>
|
||||
#include <blitz/protocol/PacketSerializer.h>
|
||||
#include <godot_cpp/classes/multiplayer_api.hpp>
|
||||
#include <godot_cpp/classes/multiplayer_peer.hpp>
|
||||
#include <godot_cpp/variant/utility_functions.hpp>
|
||||
@@ -9,49 +11,40 @@ namespace blitz {
|
||||
using namespace godot;
|
||||
|
||||
void NetworkInterface::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("AddPlayer", "a_PlayerId", "a_PlayerName"), &NetworkInterface::AddPlayer);
|
||||
ClassDB::bind_method(D_METHOD("RemovePlayer", "a_PlayerId"), &NetworkInterface::RemovePlayer);
|
||||
ClassDB::bind_method(D_METHOD("SetPlayerPositionAndRotation", "a_PlayerId", "a_Position", "a_Rotation"),
|
||||
&NetworkInterface::SetPlayerPositionAndRotation);
|
||||
|
||||
ADD_SIGNAL(MethodInfo("AddPlayer", PropertyInfo(Variant::INT, "a_PlayerId"), PropertyInfo(Variant::STRING, "a_PlayerName")));
|
||||
ADD_SIGNAL(MethodInfo("RemovePlayer", PropertyInfo(Variant::INT, "a_PlayerId")));
|
||||
ADD_SIGNAL(MethodInfo("SetPlayerPositionAndRotation", PropertyInfo(Variant::INT, "a_PlayerId"),
|
||||
PropertyInfo(Variant::VECTOR3, "a_Position"), PropertyInfo(Variant::VECTOR3, "a_Rotation")));
|
||||
ClassDB::bind_method(D_METHOD("RecievePacketDataReliable", "a_PacketData"), &NetworkInterface::RecievePacketDataReliable);
|
||||
protocol::PacketFactory::Init();
|
||||
}
|
||||
|
||||
NetworkInterface::NetworkInterface() {}
|
||||
|
||||
NetworkInterface::~NetworkInterface() {}
|
||||
|
||||
void NetworkInterface::AddPlayer(int64_t a_PlayerId, godot::String a_PlayerName) {
|
||||
emit_signal("AddPlayer", a_PlayerId, a_PlayerName);
|
||||
}
|
||||
|
||||
void NetworkInterface::RemovePlayer(int64_t a_PlayerId) {
|
||||
emit_signal("RemovePlayer", a_PlayerId);
|
||||
}
|
||||
|
||||
void NetworkInterface::SetPlayerPositionAndRotation(int64_t a_PlayerId, Vector3 a_Position, Vector3 a_Rotation) {
|
||||
emit_signal("SetPlayerPositionAndRotation", a_PlayerId, a_Position, a_Rotation);
|
||||
}
|
||||
|
||||
void NetworkInterface::_ready() {
|
||||
// TODO: unreliable
|
||||
Dictionary config;
|
||||
config["rpc_mode"] = MultiplayerAPI::RPC_MODE_AUTHORITY;
|
||||
config["rpc_mode"] = MultiplayerAPI::RPC_MODE_ANY_PEER;
|
||||
config["transfer_mode"] = MultiplayerPeer::TRANSFER_MODE_RELIABLE;
|
||||
config["call_local"] = true;
|
||||
config["channel"] = 0;
|
||||
rpc_config("AddPlayer", config);
|
||||
rpc_config("RemovePlayer", config);
|
||||
|
||||
Dictionary config2;
|
||||
config["transfer_mode"] = MultiplayerPeer::TRANSFER_MODE_RELIABLE;
|
||||
config["channel"] = 0;
|
||||
config2["rpc_mode"] = MultiplayerAPI::RPC_MODE_ANY_PEER;
|
||||
config2["call_local"] = false;
|
||||
rpc_config("SetPlayerPositionAndRotation", config2);
|
||||
rpc_config("RecievePacketDataReliable", config);
|
||||
}
|
||||
|
||||
void NetworkInterface::BroadcastPacket(const protocol::Packet& a_Packet) {
|
||||
PackedByteArray byteArray = protocol::PacketSerializer::Serialize(a_Packet);
|
||||
rpc("RecievePacketDataReliable", byteArray);
|
||||
}
|
||||
|
||||
void NetworkInterface::SendPacket(PeerID a_Peer, const protocol::Packet& a_Packet) {
|
||||
PackedByteArray byteArray = protocol::PacketSerializer::Serialize(a_Packet);
|
||||
rpc_id(a_Peer, "RecievePacketDataReliable", byteArray);
|
||||
}
|
||||
|
||||
void NetworkInterface::RecievePacketDataReliable(godot::PackedByteArray a_PacketData) {
|
||||
auto packet = protocol::PacketSerializer::Deserialize(a_PacketData);
|
||||
if (packet) {
|
||||
packet->m_Sender = get_multiplayer()->get_remote_sender_id();
|
||||
Dispatch(*packet);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blitz
|
||||
@@ -1,9 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <blitz/protocol/Packets.h>
|
||||
#include <godot_cpp/classes/node.hpp>
|
||||
#include <blitz/protocol/PacketDispatcher.h>
|
||||
|
||||
namespace blitz {
|
||||
class NetworkInterface : public godot::Node {
|
||||
class NetworkInterface : public godot::Node, public protocol::PacketDispatcher {
|
||||
GDCLASS(NetworkInterface, godot::Node)
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
@@ -12,11 +14,13 @@ class NetworkInterface : public godot::Node {
|
||||
NetworkInterface();
|
||||
~NetworkInterface();
|
||||
|
||||
void AddPlayer(int64_t a_PlayerId, godot::String a_PlayerName);
|
||||
void RemovePlayer(int64_t a_PlayerId);
|
||||
void SetPlayerPositionAndRotation(int64_t a_PlayerId, godot::Vector3 a_Position, godot::Vector3 a_Rotation);
|
||||
void BroadcastPacket(const protocol::Packet& a_Packet);
|
||||
void SendPacket(PeerID a_Peer, const protocol::Packet& a_Packet);
|
||||
|
||||
void _ready() override;
|
||||
void _ready() override;
|
||||
|
||||
private:
|
||||
void RecievePacketDataReliable(godot::PackedByteArray a_PacketData);
|
||||
};
|
||||
|
||||
} // namespace blitz
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <godot_cpp/classes/animation_tree.hpp>
|
||||
#include <godot_cpp/classes/character_body3d.hpp>
|
||||
#include <godot_cpp/classes/node3d.hpp>
|
||||
#include <blitz/common/Types.h>
|
||||
|
||||
namespace blitz {
|
||||
|
||||
@@ -26,7 +27,7 @@ class Player : public godot::CharacterBody3D {
|
||||
godot::Vector3 GetCameraRotation() const;
|
||||
void SetCameraRotation(const godot::Vector3& a_Rotation);
|
||||
|
||||
uint64_t GetId() const {
|
||||
PlayerID GetId() const {
|
||||
return m_PeerId;
|
||||
}
|
||||
|
||||
@@ -36,7 +37,7 @@ class Player : public godot::CharacterBody3D {
|
||||
|
||||
godot::Vector3 m_SnapVector;
|
||||
float m_Speed;
|
||||
uint64_t m_PeerId;
|
||||
PeerID m_PeerId;
|
||||
|
||||
friend class World;
|
||||
};
|
||||
|
||||
@@ -28,17 +28,18 @@ void Server::_ready() {
|
||||
m_Lobby->connect("player_disconnected", callable_mp(this, &Server::OnPlayerDisconnect));
|
||||
}
|
||||
|
||||
void Server::OnPlayerConnect(uint64_t a_PeerId) {
|
||||
void Server::OnPlayerConnect(PeerID a_PeerId) {
|
||||
protocol::PlayerInfo playerInfo{a_PeerId, "whoami"};
|
||||
for (int i = 0; i < m_Peers.size(); i++) {
|
||||
m_NetworkInterface->rpc_id(a_PeerId, "AddPlayer", m_Peers[i], "Aucuneidee");
|
||||
m_NetworkInterface->SendPacket(a_PeerId, protocol::packets::PlayerJoin({m_Peers[i], "whoami"}));
|
||||
}
|
||||
m_Peers.push_back(a_PeerId);
|
||||
m_NetworkInterface->rpc("AddPlayer", a_PeerId, "Aucuneidee");
|
||||
m_NetworkInterface->BroadcastPacket(protocol::packets::PlayerJoin({playerInfo}));
|
||||
}
|
||||
|
||||
void Server::OnPlayerDisconnect(uint64_t a_PeerId) {
|
||||
void Server::OnPlayerDisconnect(PeerID a_PeerId) {
|
||||
m_Peers.erase(a_PeerId);
|
||||
m_NetworkInterface->rpc("RemovePlayer", a_PeerId);
|
||||
m_NetworkInterface->BroadcastPacket(protocol::packets::PlayerLeave({a_PeerId}));
|
||||
}
|
||||
|
||||
} // namespace blitz
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <godot_cpp/classes/node.hpp>
|
||||
#include <blitz/common/Types.h>
|
||||
|
||||
namespace blitz {
|
||||
|
||||
@@ -18,14 +19,14 @@ class Server : public godot::Node {
|
||||
|
||||
void _ready() override;
|
||||
|
||||
void OnPlayerConnect(uint64_t a_PeerId);
|
||||
void OnPlayerDisconnect(uint64_t a_PeerId);
|
||||
void OnPlayerConnect(PeerID a_PeerId);
|
||||
void OnPlayerDisconnect(PeerID a_PeerId);
|
||||
|
||||
private:
|
||||
Lobby* m_Lobby;
|
||||
NetworkInterface* m_NetworkInterface;
|
||||
|
||||
godot::TypedArray<uint64_t> m_Peers;
|
||||
godot::TypedArray<PeerID> m_Peers;
|
||||
};
|
||||
|
||||
} // namespace blitz
|
||||
@@ -32,37 +32,53 @@ void World::_ready() {
|
||||
m_NetworkInterface = Object::cast_to<NetworkInterface>(lobby->find_child("NetworkInterface"));
|
||||
DEV_ASSERT(m_NetworkInterface);
|
||||
|
||||
m_NetworkInterface->connect("AddPlayer", callable_mp(this, &World::AddPlayer));
|
||||
m_NetworkInterface->connect("RemovePlayer", callable_mp(this, &World::RemovePlayer));
|
||||
m_NetworkInterface->connect("SetPlayerPositionAndRotation", callable_mp(this, &World::SetPlayerPositionAndRotation));
|
||||
m_NetworkInterface->RegisterHandler(protocol::PacketType::PlayerJoin, *this);
|
||||
m_NetworkInterface->RegisterHandler(protocol::PacketType::PlayerLeave, *this);
|
||||
m_NetworkInterface->RegisterHandler(protocol::PacketType::PlayerPositionAndRotation, *this);
|
||||
}
|
||||
|
||||
|
||||
World::World() {}
|
||||
|
||||
World::~World() {}
|
||||
World::~World() {
|
||||
if (Engine::get_singleton()->is_editor_hint())
|
||||
return;
|
||||
|
||||
m_NetworkInterface->UnregisterHandler(*this);
|
||||
}
|
||||
|
||||
void World::_process(float delta) {
|
||||
#if DEBUG_ENABLED
|
||||
if (Engine::get_singleton()->is_editor_hint())
|
||||
return;
|
||||
#endif
|
||||
m_PassedTime += delta;
|
||||
if (m_PassedTime < 0.05f)
|
||||
return;
|
||||
|
||||
// UtilityFunctions::print(m_PassedTime);
|
||||
|
||||
// m_PassedTime -= 0.05f;
|
||||
// if (m_PassedTime > 0.5f)
|
||||
// m_PassedTime = 0.0f;
|
||||
|
||||
if (get_multiplayer()->is_server()) {
|
||||
for (int i = 0; i < m_Players->get_child_count(); i++) {
|
||||
Player* player = Object::cast_to<Player>(m_Players->get_child(i));
|
||||
DEV_ASSERT(player);
|
||||
m_NetworkInterface->rpc(
|
||||
"SetPlayerPositionAndRotation", player->m_PeerId, player->get_position(), player->GetCameraRotation());
|
||||
m_NetworkInterface->BroadcastPacket(
|
||||
protocol::packets::PlayerPositionAndRotation({player->GetId(), player->get_position(), player->GetCameraRotation()}));
|
||||
}
|
||||
} else {
|
||||
Player* player = GetPlayerById(get_multiplayer()->get_unique_id());
|
||||
if (player)
|
||||
m_NetworkInterface->rpc("SetPlayerPositionAndRotation", get_multiplayer()->get_unique_id(), player->get_position(),
|
||||
player->GetCameraRotation());
|
||||
if (player) {
|
||||
m_NetworkInterface->BroadcastPacket(protocol::packets::PlayerPositionAndRotation(
|
||||
{get_multiplayer()->get_unique_id(), player->get_position(), player->GetCameraRotation()}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Player* World::GetPlayerById(uint64_t a_PlayerId) {
|
||||
Player* World::GetPlayerById(PlayerID a_PlayerId) {
|
||||
String stringId = UtilityFunctions::var_to_str(a_PlayerId);
|
||||
for (int i = 0; i < m_Players->get_child_count(); i++) {
|
||||
Node* player = m_Players->get_child(i);
|
||||
@@ -73,8 +89,25 @@ Player* World::GetPlayerById(uint64_t a_PlayerId) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void World::AddPlayer(int32_t a_PlayerId, String a_PlayerName) {
|
||||
UtilityFunctions::print("New Player with id : ", a_PlayerId);
|
||||
void World::HandlePacket(const protocol::packets::PlayerJoin& a_PlayerJoin) {
|
||||
const protocol::PlayerInfo& playerInfo = a_PlayerJoin.m_Data.m_Player;
|
||||
AddPlayer(playerInfo.m_PlayerId, playerInfo.m_PlayerName);
|
||||
}
|
||||
|
||||
void World::HandlePacket(const protocol::packets::PlayerLeave& a_PlayerLeave) {
|
||||
RemovePlayer(a_PlayerLeave.m_Data.m_PlayerId);
|
||||
}
|
||||
|
||||
void World::HandlePacket(const protocol::packets::PlayerPositionAndRotation& a_PlayerPos) {
|
||||
const auto& data = a_PlayerPos.m_Data;
|
||||
if (data.m_Player == get_multiplayer()->get_unique_id() || data.m_Player != a_PlayerPos.m_Sender)
|
||||
return;
|
||||
|
||||
SetPlayerPositionAndRotation(data.m_Player, data.m_Position, data.m_Rotation);
|
||||
}
|
||||
|
||||
void World::AddPlayer(PlayerID a_PlayerId, String a_PlayerName) {
|
||||
UtilityFunctions::print("New Player with id : ", a_PlayerId, " and name ", a_PlayerName);
|
||||
if (a_PlayerId == get_multiplayer()->get_unique_id()) {
|
||||
Ref<PackedScene> serverScene = ResourceLoader::get_singleton()->load(FirstPersonPlayerScenePath);
|
||||
FirstPersonPlayer* player = Object::cast_to<FirstPersonPlayer>(serverScene->instantiate());
|
||||
@@ -90,7 +123,7 @@ void World::AddPlayer(int32_t a_PlayerId, String a_PlayerName) {
|
||||
}
|
||||
}
|
||||
|
||||
void World::RemovePlayer(int32_t a_PlayerId) {
|
||||
void World::RemovePlayer(PlayerID a_PlayerId) {
|
||||
UtilityFunctions::print("Removing Player with id : ", a_PlayerId);
|
||||
Player* player = GetPlayerById(a_PlayerId);
|
||||
if (player) {
|
||||
@@ -98,10 +131,7 @@ void World::RemovePlayer(int32_t a_PlayerId) {
|
||||
}
|
||||
}
|
||||
|
||||
void World::SetPlayerPositionAndRotation(int64_t a_PlayerId, Vector3 a_Position, Vector3 a_Rotation) {
|
||||
if (a_PlayerId == get_multiplayer()->get_unique_id())
|
||||
return;
|
||||
|
||||
void World::SetPlayerPositionAndRotation(PlayerID a_PlayerId, const Vector3& a_Position, const Vector3& a_Rotation) {
|
||||
Player* player = GetPlayerById(a_PlayerId);
|
||||
if (player) {
|
||||
player->set_position(a_Position);
|
||||
|
||||
21
src/World.h
21
src/World.h
@@ -2,12 +2,14 @@
|
||||
|
||||
#include <godot_cpp/classes/node3d.hpp>
|
||||
|
||||
#include <blitz/protocol/PacketHandler.h>
|
||||
|
||||
namespace blitz {
|
||||
|
||||
class Player;
|
||||
class NetworkInterface;
|
||||
|
||||
class World : public godot::Node3D {
|
||||
class World : public godot::Node3D, public protocol::PacketHandler {
|
||||
GDCLASS(World, godot::Node3D)
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
@@ -16,19 +18,24 @@ class World : public godot::Node3D {
|
||||
World();
|
||||
~World();
|
||||
|
||||
// Godot overrides
|
||||
void _ready() override;
|
||||
void _process(float delta);
|
||||
|
||||
void _ready() override;
|
||||
Player* GetPlayerById(PlayerID a_PlayerId);
|
||||
|
||||
Player* GetPlayerById(uint64_t a_PlayerId);
|
||||
|
||||
void AddPlayer(int32_t a_PlayerId, godot::String a_PlayerName);
|
||||
void RemovePlayer(int32_t a_PlayerId);
|
||||
void SetPlayerPositionAndRotation(int64_t a_PlayerId, godot::Vector3 a_Position, godot::Vector3 a_Rotation);
|
||||
void HandlePacket(const protocol::packets::PlayerJoin&) override;
|
||||
void HandlePacket(const protocol::packets::PlayerLeave&) override;
|
||||
void HandlePacket(const protocol::packets::PlayerPositionAndRotation&) override;
|
||||
|
||||
private:
|
||||
NetworkInterface* m_NetworkInterface;
|
||||
godot::Node* m_Players;
|
||||
float m_PassedTime;
|
||||
|
||||
|
||||
void AddPlayer(PlayerID a_PlayerId, godot::String a_PlayerName);
|
||||
void RemovePlayer(PlayerID a_PlayerId);
|
||||
void SetPlayerPositionAndRotation(PlayerID a_PlayerId, const godot::Vector3& a_Position, const godot::Vector3& a_Rotation);
|
||||
};
|
||||
} // namespace blitz
|
||||
Reference in New Issue
Block a user