Initial network manager with clients
This commit is contained in:
29
Source/Engine/Networking/NetworkClient.h
Normal file
29
Source/Engine/Networking/NetworkClient.h
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Types.h"
|
||||
#include "NetworkConnection.h"
|
||||
#include "NetworkConnectionState.h"
|
||||
#include "Engine/Scripting/ScriptingObject.h"
|
||||
|
||||
/// <summary>
|
||||
/// High-level network client object (local or connected to the server).
|
||||
/// </summary>
|
||||
API_CLASS(sealed, NoSpawn, Namespace = "FlaxEngine.Networking") class FLAXENGINE_API NetworkClient final : public ScriptingObject
|
||||
{
|
||||
DECLARE_SCRIPTING_TYPE_NO_SPAWN(NetworkClient);
|
||||
friend class NetworkManager;
|
||||
explicit NetworkClient(NetworkConnection connection);
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Identifier of the client (connection id from local peer).
|
||||
/// </summary>
|
||||
API_FIELD(ReadOnly) NetworkConnection Connection;
|
||||
|
||||
/// <summary>
|
||||
/// Client connection state.
|
||||
/// </summary>
|
||||
API_FIELD(ReadOnly) NetworkConnectionState State;
|
||||
};
|
||||
36
Source/Engine/Networking/NetworkConnectionState.h
Normal file
36
Source/Engine/Networking/NetworkConnectionState.h
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Core/Config.h"
|
||||
|
||||
/// <summary>
|
||||
/// The high-level network connection state.
|
||||
/// </summary>
|
||||
API_ENUM(Namespace="FlaxEngine.Networking") enum class NetworkConnectionState
|
||||
{
|
||||
/// <summary>
|
||||
/// Not connected.
|
||||
/// </summary>
|
||||
Offline = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Connection process was started but not yet finished.
|
||||
/// </summary>
|
||||
Connecting,
|
||||
|
||||
/// <summary>
|
||||
/// Connection has been made.
|
||||
/// </summary>
|
||||
Connected,
|
||||
|
||||
/// <summary>
|
||||
/// Disconnection process was started but not yet finished.
|
||||
/// </summary>
|
||||
Disconnecting,
|
||||
|
||||
/// <summary>
|
||||
/// Connection ended.
|
||||
/// </summary>
|
||||
Disconnected,
|
||||
};
|
||||
400
Source/Engine/Networking/NetworkManager.cpp
Normal file
400
Source/Engine/Networking/NetworkManager.cpp
Normal file
@@ -0,0 +1,400 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
#include "NetworkManager.h"
|
||||
#include "NetworkClient.h"
|
||||
#include "NetworkPeer.h"
|
||||
#include "NetworkEvent.h"
|
||||
#include "NetworkChannelType.h"
|
||||
#include "NetworkSettings.h"
|
||||
#include "FlaxEngine.Gen.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Core/Collections/Array.h"
|
||||
#include "Engine/Engine/EngineService.h"
|
||||
#include "Engine/Engine/Time.h"
|
||||
#include "Engine/Profiler/ProfilerCPU.h"
|
||||
#include "Engine/Scripting/Scripting.h"
|
||||
|
||||
float NetworkManager::NetworkFPS = 60.0f;
|
||||
NetworkManagerMode NetworkManager::Mode = NetworkManagerMode::Offline;
|
||||
NetworkConnectionState NetworkManager::State = NetworkConnectionState::Offline;
|
||||
NetworkClient* NetworkManager::LocalClient = nullptr;
|
||||
Array<NetworkClient*> NetworkManager::Clients;
|
||||
Action NetworkManager::StateChanged;
|
||||
Delegate<NetworkClientConnectionData&> NetworkManager::ClientConnecting;
|
||||
Delegate<NetworkClient*> NetworkManager::ClientConnected;
|
||||
Delegate<NetworkClient*> NetworkManager::ClientDisconnected;
|
||||
|
||||
enum class NetworkMessageIDs : uint8
|
||||
{
|
||||
None = 0,
|
||||
Handshake,
|
||||
HandshakeReply,
|
||||
};
|
||||
|
||||
PACK_STRUCT(struct NetworkMessageHandshake
|
||||
{
|
||||
NetworkMessageIDs ID;
|
||||
uint32 EngineBuild;
|
||||
uint32 EngineProtocolVersion;
|
||||
uint32 GameProtocolVersion;
|
||||
byte Platform;
|
||||
byte Architecture;
|
||||
uint16 PayloadDataSize;
|
||||
});
|
||||
|
||||
PACK_STRUCT(struct NetworkMessageHandshakeReply
|
||||
{
|
||||
NetworkMessageIDs ID;
|
||||
int32 Result;
|
||||
});
|
||||
|
||||
namespace
|
||||
{
|
||||
NetworkPeer* Peer = nullptr;
|
||||
uint32 GameProtocolVersion = 0;
|
||||
double LastUpdateTime = 0;
|
||||
}
|
||||
|
||||
class NetworkManagerService : public EngineService
|
||||
{
|
||||
public:
|
||||
NetworkManagerService()
|
||||
: EngineService(TEXT("Network Manager"), 1000)
|
||||
{
|
||||
}
|
||||
|
||||
void Update() override;
|
||||
|
||||
void Dispose() override
|
||||
{
|
||||
// Ensure to dispose any resources upon exiting
|
||||
NetworkManager::Stop();
|
||||
}
|
||||
};
|
||||
|
||||
NetworkManagerService NetworkManagerServiceInstance;
|
||||
|
||||
bool StartPeer()
|
||||
{
|
||||
PROFILE_CPU();
|
||||
ASSERT_LOW_LAYER(!Peer);
|
||||
NetworkManager::State = NetworkConnectionState::Connecting;
|
||||
NetworkManager::StateChanged();
|
||||
const auto& settings = *NetworkSettings::Get();
|
||||
|
||||
// Create Network Peer that will use underlying INetworkDriver to send messages over the network
|
||||
NetworkConfig networkConfig;
|
||||
if (NetworkManager::Mode == NetworkManagerMode::Client)
|
||||
{
|
||||
// Client
|
||||
networkConfig.Address = settings.Address;
|
||||
networkConfig.Port = settings.Port;
|
||||
networkConfig.ConnectionsLimit = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Server or Host
|
||||
networkConfig.Address = TEXT("any");
|
||||
networkConfig.Port = settings.Port;
|
||||
networkConfig.ConnectionsLimit = (uint16)settings.MaxClients;
|
||||
}
|
||||
const ScriptingTypeHandle networkDriverType = Scripting::FindScriptingType(settings.NetworkDriver);
|
||||
if (!networkDriverType)
|
||||
{
|
||||
LOG(Error, "Unknown Network Driver type {0}", String(settings.NetworkDriver));
|
||||
return true;
|
||||
}
|
||||
networkConfig.NetworkDriver = ScriptingObject::NewObject(networkDriverType);
|
||||
Peer = NetworkPeer::CreatePeer(networkConfig);
|
||||
if (!Peer)
|
||||
{
|
||||
LOG(Error, "Failed to create Network Peer at {0}:{1}", networkConfig.Address, networkConfig.Port);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void StopPeer()
|
||||
{
|
||||
if (!Peer)
|
||||
return;
|
||||
PROFILE_CPU();
|
||||
if (NetworkManager::Mode == NetworkManagerMode::Client)
|
||||
Peer->Disconnect();
|
||||
NetworkPeer::ShutdownPeer(Peer);
|
||||
Peer = nullptr;
|
||||
}
|
||||
|
||||
void NetworkSettings::Apply()
|
||||
{
|
||||
NetworkManager::NetworkFPS = NetworkFPS;
|
||||
GameProtocolVersion = ProtocolVersion;
|
||||
}
|
||||
|
||||
NetworkClient::NetworkClient(NetworkConnection connection)
|
||||
: ScriptingObject(SpawnParams(Guid::New(), TypeInitializer))
|
||||
, Connection(connection)
|
||||
, State(NetworkConnectionState::Connecting)
|
||||
{
|
||||
}
|
||||
|
||||
NetworkClient* NetworkManager::GetClient(const NetworkConnection& connection)
|
||||
{
|
||||
if (connection.ConnectionId == 0)
|
||||
return LocalClient;
|
||||
for (NetworkClient* client : Clients)
|
||||
{
|
||||
if (client->Connection == connection)
|
||||
return client;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool NetworkManager::StartServer()
|
||||
{
|
||||
PROFILE_CPU();
|
||||
Stop();
|
||||
|
||||
Mode = NetworkManagerMode::Server;
|
||||
if (StartPeer())
|
||||
return true;
|
||||
if (!Peer->Listen())
|
||||
return true;
|
||||
|
||||
State = NetworkConnectionState::Connected;
|
||||
StateChanged();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetworkManager::StartClient()
|
||||
{
|
||||
PROFILE_CPU();
|
||||
Stop();
|
||||
|
||||
Mode = NetworkManagerMode::Client;
|
||||
if (StartPeer())
|
||||
return true;
|
||||
if (!Peer->Connect())
|
||||
return true;
|
||||
LocalClient = New<NetworkClient>(NetworkConnection{0});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetworkManager::StartHost()
|
||||
{
|
||||
PROFILE_CPU();
|
||||
Stop();
|
||||
|
||||
Mode = NetworkManagerMode::Host;
|
||||
if (StartPeer())
|
||||
return true;
|
||||
if (!Peer->Listen())
|
||||
return true;
|
||||
LocalClient = New<NetworkClient>(NetworkConnection{0});
|
||||
|
||||
// Auto-connect host
|
||||
LocalClient->State = NetworkConnectionState::Connected;
|
||||
ClientConnected(LocalClient);
|
||||
|
||||
State = NetworkConnectionState::Connected;
|
||||
StateChanged();
|
||||
return false;
|
||||
}
|
||||
|
||||
void NetworkManager::Stop()
|
||||
{
|
||||
if (Mode == NetworkManagerMode::Offline && State == NetworkConnectionState::Offline)
|
||||
return;
|
||||
PROFILE_CPU();
|
||||
|
||||
State = NetworkConnectionState::Disconnecting;
|
||||
if (LocalClient)
|
||||
LocalClient->State = NetworkConnectionState::Disconnecting;
|
||||
for (NetworkClient* client : Clients)
|
||||
client->State = NetworkConnectionState::Disconnecting;
|
||||
StateChanged();
|
||||
|
||||
for (int32 i = Clients.Count() - 1; i >= 0; i--)
|
||||
{
|
||||
NetworkClient* client = Clients[i];
|
||||
ClientDisconnected(client);
|
||||
client->State = NetworkConnectionState::Disconnected;
|
||||
Delete(client);
|
||||
Clients.RemoveAt(i);
|
||||
}
|
||||
StopPeer();
|
||||
if (LocalClient)
|
||||
{
|
||||
LocalClient->State = NetworkConnectionState::Disconnected;
|
||||
Delete(LocalClient);
|
||||
LocalClient = nullptr;
|
||||
}
|
||||
|
||||
State = NetworkConnectionState::Disconnected;
|
||||
Mode = NetworkManagerMode::Offline;
|
||||
StateChanged();
|
||||
}
|
||||
|
||||
void NetworkManagerService::Update()
|
||||
{
|
||||
const double currentTime = Time::Update.UnscaledTime.GetTotalSeconds();
|
||||
const float minDeltaTime = NetworkManager::NetworkFPS > 0 ? 1.0f / NetworkManager::NetworkFPS : 0.0f;
|
||||
if (NetworkManager::Mode == NetworkManagerMode::Offline || (float)(currentTime - LastUpdateTime) < minDeltaTime)
|
||||
return;
|
||||
PROFILE_CPU();
|
||||
LastUpdateTime = currentTime;
|
||||
// TODO: convert into TaskGraphSystems and use async jobs
|
||||
|
||||
// Process network messages
|
||||
NetworkEvent event;
|
||||
while (Peer->PopEvent(event))
|
||||
{
|
||||
switch (event.EventType)
|
||||
{
|
||||
case NetworkEventType::Connected:
|
||||
LOG(Info, "Incoming connection with Id={0}", event.Sender.ConnectionId);
|
||||
if (NetworkManager::IsClient())
|
||||
{
|
||||
// Initialize client connection data
|
||||
NetworkClientConnectionData connectionData;
|
||||
connectionData.Client = NetworkManager::LocalClient;
|
||||
connectionData.Result = 0;
|
||||
connectionData.Platform = PLATFORM_TYPE;
|
||||
connectionData.Architecture = PLATFORM_ARCH;
|
||||
NetworkManager::ClientConnecting(connectionData); // Allow client to validate connection or inject custom connection data
|
||||
if (connectionData.Result != 0)
|
||||
{
|
||||
LOG(Info, "Connection blocked with result {0}.", connectionData.Result);
|
||||
NetworkManager::Stop();
|
||||
break;
|
||||
}
|
||||
|
||||
// Send initial handshake message from client to server
|
||||
NetworkMessageHandshake msgData;
|
||||
msgData.ID = NetworkMessageIDs::Handshake;
|
||||
msgData.EngineBuild = FLAXENGINE_VERSION_BUILD;
|
||||
msgData.EngineProtocolVersion = 1;
|
||||
msgData.GameProtocolVersion = GameProtocolVersion;
|
||||
msgData.Platform = (byte)connectionData.Platform;
|
||||
msgData.Architecture = (byte)connectionData.Architecture;
|
||||
msgData.PayloadDataSize = (uint16)connectionData.PayloadData.Count();
|
||||
NetworkMessage msg = Peer->BeginSendMessage();
|
||||
msg.WriteStructure(msgData);
|
||||
msg.WriteBytes(connectionData.PayloadData.Get(), connectionData.PayloadData.Count());
|
||||
Peer->EndSendMessage(NetworkChannelType::ReliableOrdered, msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create incoming client
|
||||
auto client = New<NetworkClient>(event.Sender);
|
||||
NetworkManager::Clients.Add(client);
|
||||
}
|
||||
break;
|
||||
case NetworkEventType::Disconnected:
|
||||
case NetworkEventType::Timeout:
|
||||
LOG(Info, "{1} with Id={0}", event.Sender.ConnectionId, event.EventType == NetworkEventType::Disconnected ? TEXT("Disconnected") : TEXT("Disconnected on timeout"));
|
||||
if (NetworkManager::IsClient())
|
||||
{
|
||||
// Server disconnected from client
|
||||
NetworkManager::Stop();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Client disconnected from server/host
|
||||
NetworkClient* client = NetworkManager::GetClient(event.Sender);
|
||||
if (!client)
|
||||
{
|
||||
LOG(Error, "Unknown client");
|
||||
break;
|
||||
}
|
||||
client->State = NetworkConnectionState::Disconnecting;
|
||||
LOG(Info, "Client id={0} disconnected", event.Sender.ConnectionId);
|
||||
NetworkManager::Clients.RemoveKeepOrder(client);
|
||||
NetworkManager::ClientDisconnected(client);
|
||||
client->State = NetworkConnectionState::Disconnected;
|
||||
Delete(client);
|
||||
}
|
||||
break;
|
||||
case NetworkEventType::Message:
|
||||
{
|
||||
// Process network message
|
||||
NetworkClient* client = NetworkManager::GetClient(event.Sender);
|
||||
if (!client && NetworkManager::Mode != NetworkManagerMode::Client)
|
||||
{
|
||||
LOG(Error, "Unknown client");
|
||||
break;
|
||||
}
|
||||
uint8 id = *event.Message.Buffer;
|
||||
switch ((NetworkMessageIDs)id)
|
||||
{
|
||||
case NetworkMessageIDs::Handshake:
|
||||
{
|
||||
// Read client connection data
|
||||
NetworkMessageHandshake msgData;
|
||||
event.Message.ReadStructure(msgData);
|
||||
NetworkClientConnectionData connectionData;
|
||||
connectionData.Client = client;
|
||||
connectionData.Result = 0;
|
||||
connectionData.Platform = (PlatformType)msgData.Platform;
|
||||
connectionData.Architecture = (ArchitectureType)msgData.Architecture;
|
||||
connectionData.PayloadData.Resize(msgData.PayloadDataSize);
|
||||
event.Message.ReadBytes(connectionData.PayloadData.Get(), msgData.PayloadDataSize);
|
||||
NetworkManager::ClientConnecting(connectionData); // Allow server to validate connection
|
||||
|
||||
// Reply to the handshake message with a result
|
||||
NetworkMessageHandshakeReply replyData;
|
||||
replyData.ID = NetworkMessageIDs::HandshakeReply;
|
||||
replyData.Result = connectionData.Result;
|
||||
NetworkMessage msgReply = Peer->BeginSendMessage();
|
||||
msgReply.WriteStructure(replyData);
|
||||
Peer->EndSendMessage(NetworkChannelType::ReliableOrdered, msgReply, event.Sender);
|
||||
|
||||
// Update client based on connection result
|
||||
if (connectionData.Result != 0)
|
||||
{
|
||||
LOG(Info, "Connection blocked with result {0} from client id={1}.", connectionData.Result, event.Sender.ConnectionId);
|
||||
client->State = NetworkConnectionState::Disconnecting;
|
||||
Peer->Disconnect(event.Sender);
|
||||
client->State = NetworkConnectionState::Disconnected;
|
||||
}
|
||||
else
|
||||
{
|
||||
client->State = NetworkConnectionState::Connected;
|
||||
LOG(Info, "Client id={0} connected", event.Sender.ConnectionId);
|
||||
NetworkManager::ClientConnected(client);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NetworkMessageIDs::HandshakeReply:
|
||||
{
|
||||
ASSERT_LOW_LAYER(NetworkManager::IsClient());
|
||||
NetworkMessageHandshakeReply msgData;
|
||||
event.Message.ReadStructure(msgData);
|
||||
if (msgData.Result != 0)
|
||||
{
|
||||
// Server failed to connect with client
|
||||
// TODO: feed game with result from msgData.Result
|
||||
NetworkManager::Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
// Client got connected with server
|
||||
NetworkManager::LocalClient->State = NetworkConnectionState::Connected;
|
||||
NetworkManager::State = NetworkConnectionState::Connected;
|
||||
NetworkManager::StateChanged();
|
||||
break;
|
||||
}
|
||||
#if !BUILD_RELEASE
|
||||
default:
|
||||
LOG(Warning, "Unknown message id={0} from connection {1}", id, event.Sender.ConnectionId);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
Peer->RecycleMessage(event.Message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
150
Source/Engine/Networking/NetworkManager.h
Normal file
150
Source/Engine/Networking/NetworkManager.h
Normal file
@@ -0,0 +1,150 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "NetworkConnection.h"
|
||||
#include "Types.h"
|
||||
#include "NetworkConnectionState.h"
|
||||
#include "Engine/Core/Delegate.h"
|
||||
#include "Engine/Core/Collections/Array.h"
|
||||
#include "Engine/Scripting/ScriptingType.h"
|
||||
|
||||
/// <summary>
|
||||
/// The high-level network manage modes.
|
||||
/// </summary>
|
||||
API_ENUM(Namespace="FlaxEngine.Networking") enum class NetworkManagerMode
|
||||
{
|
||||
// Disabled.
|
||||
Offline = 0,
|
||||
// Server-only without a client (host a game but not participate).
|
||||
Server,
|
||||
// Client-only (connected to Server or Host).
|
||||
Client,
|
||||
// Both server and client (other clients can connect).
|
||||
Host,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The high-level network client connection data. Can be used to accept/deny new connection.
|
||||
/// </summary>
|
||||
API_STRUCT(Namespace="FlaxEngine.Networking") struct NetworkClientConnectionData
|
||||
{
|
||||
DECLARE_SCRIPTING_TYPE_MINIMAL(NetworkClientConnectionData);
|
||||
// The incoming client.
|
||||
API_FIELD() NetworkClient* Client;
|
||||
// 0 if accept new connection, error code otherwise. Send back to the client.
|
||||
API_FIELD() int32 Result;
|
||||
// Client platform type (can be different that current one when using cross-play).
|
||||
API_FIELD() PlatformType Platform;
|
||||
// Client platform architecture (can be different that current one when using cross-play).
|
||||
API_FIELD() ArchitectureType Architecture;
|
||||
// Custom data to send from client to server as part of connection initialization and verification. Can contain game build info, platform data or certificate needed upon joining the game.
|
||||
API_FIELD() Array<byte> PayloadData;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// High-level networking manager for multiplayer games.
|
||||
/// </summary>
|
||||
API_CLASS(static, Namespace = "FlaxEngine.Networking") class FLAXENGINE_API NetworkManager
|
||||
{
|
||||
DECLARE_SCRIPTING_TYPE_MINIMAL(NetworkManager);
|
||||
public:
|
||||
/// <summary>
|
||||
/// The target amount of the network logic updates per second (frequency of replication, events sending and network ticking). Use 0 to run every game update.
|
||||
/// </summary>
|
||||
API_FIELD() static float NetworkFPS;
|
||||
|
||||
/// <summary>
|
||||
/// Current manager mode.
|
||||
/// </summary>
|
||||
API_FIELD(ReadOnly) static NetworkManagerMode Mode;
|
||||
|
||||
/// <summary>
|
||||
/// Current network connection state.
|
||||
/// </summary>
|
||||
API_FIELD(ReadOnly) static NetworkConnectionState State;
|
||||
|
||||
/// <summary>
|
||||
/// Local client, valid only when Network Manager is running in client or host mode (server doesn't have a client).
|
||||
/// </summary>
|
||||
API_FIELD(ReadOnly) static NetworkClient* LocalClient;
|
||||
|
||||
/// <summary>
|
||||
/// List of all clients: connecting, connected and disconnected. Empty on clients.
|
||||
/// </summary>
|
||||
API_FIELD(ReadOnly) static Array<NetworkClient*, HeapAllocation> Clients;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Event called when network manager state gets changed (eg. client connected to the server, or server shutdown started).
|
||||
/// </summary>
|
||||
API_EVENT() static Action StateChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Event called when new client is connecting. Can be used to accept/deny connection. Called on client to fill PayloadData send and called on server/host to validate incoming client connection (eg. with PayloadData validation).
|
||||
/// </summary>
|
||||
API_EVENT() static Delegate<NetworkClientConnectionData&> ClientConnecting;
|
||||
|
||||
/// <summary>
|
||||
/// Event called after new client successfully connected.
|
||||
/// </summary>
|
||||
API_EVENT() static Delegate<NetworkClient*> ClientConnected;
|
||||
|
||||
/// <summary>
|
||||
/// Event called after new client successfully disconnected.
|
||||
/// </summary>
|
||||
API_EVENT() static Delegate<NetworkClient*> ClientDisconnected;
|
||||
|
||||
public:
|
||||
// Returns true if network is a client.
|
||||
API_PROPERTY() FORCE_INLINE static bool IsClient()
|
||||
{
|
||||
return Mode == NetworkManagerMode::Client;
|
||||
}
|
||||
|
||||
// Returns true if network is a server.
|
||||
API_PROPERTY() FORCE_INLINE static bool IsServer()
|
||||
{
|
||||
return Mode == NetworkManagerMode::Server;
|
||||
}
|
||||
|
||||
// Returns true if network is a host (both client and server).
|
||||
API_PROPERTY() FORCE_INLINE static bool IsHost()
|
||||
{
|
||||
return Mode == NetworkManagerMode::Host;
|
||||
}
|
||||
|
||||
// Returns true if network is connected and online.
|
||||
API_PROPERTY() FORCE_INLINE static bool IsConnected()
|
||||
{
|
||||
return State == NetworkConnectionState::Connected;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the network client for a given connection. Returns null if failed to find it.
|
||||
/// </summary>
|
||||
/// <param name="connection">Network connection identifier.</param>
|
||||
/// <returns>Found client or null.</returns>
|
||||
API_FUNCTION() static NetworkClient* GetClient(API_PARAM(Ref) const NetworkConnection& connection);
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Starts the network in server mode. Returns true if failed (eg. invalid config).
|
||||
/// </summary>
|
||||
API_FUNCTION() static bool StartServer();
|
||||
|
||||
/// <summary>
|
||||
/// Starts the network in client mode. Returns true if failed (eg. invalid config).
|
||||
/// </summary>
|
||||
API_FUNCTION() static bool StartClient();
|
||||
|
||||
/// <summary>
|
||||
/// Starts the network in host mode. Returns true if failed (eg. invalid config).
|
||||
/// </summary>
|
||||
API_FUNCTION() static bool StartHost();
|
||||
|
||||
/// <summary>
|
||||
/// Stops the network.
|
||||
/// </summary>
|
||||
API_FUNCTION() static void Stop();
|
||||
};
|
||||
@@ -19,6 +19,12 @@ public:
|
||||
API_FIELD(Attributes="EditorOrder(0), EditorDisplay(\"General\")")
|
||||
int32 MaxClients = 100;
|
||||
|
||||
/// <summary>
|
||||
/// Network protocol version of the game. Network clients and server can use only the same protocol version (verified upon client joining).
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(10), EditorDisplay(\"General\")")
|
||||
uint32 ProtocolVersion = 1;
|
||||
|
||||
/// <summary>
|
||||
/// The target amount of the network system updates per second. Higher values provide better network synchronization (eg. 60 for shooters), lower values reduce network usage and performance impact (eg. 30 for strategy games). Can be used to tweak networking performance impact on game. Cannot be higher that UpdateFPS (from Time Settings). Use 0 to run every game update.
|
||||
/// </summary>
|
||||
|
||||
@@ -4,9 +4,11 @@
|
||||
|
||||
enum class NetworkChannelType;
|
||||
enum class NetworkEventType;
|
||||
enum class NetworkConnectionState;
|
||||
|
||||
class INetworkDriver;
|
||||
class NetworkPeer;
|
||||
class NetworkClient;
|
||||
|
||||
struct NetworkEvent;
|
||||
struct NetworkConnection;
|
||||
|
||||
Reference in New Issue
Block a user