Add automatic network serializers generation for NetworkReplicated fields in C++ types
This commit is contained in:
@@ -96,6 +96,18 @@ void NetworkReplicationService::Dispose()
|
||||
|
||||
NetworkReplicationService NetworkReplicationServiceInstance;
|
||||
|
||||
Dictionary<ScriptingTypeHandle, NetworkReplicator::SerializeFuncPair> NetworkReplicator::SerializersTable;
|
||||
|
||||
void INetworkSerializable_Serialize(void* instance, NetworkStream* stream)
|
||||
{
|
||||
((INetworkSerializable*)instance)->Serialize(stream);
|
||||
}
|
||||
|
||||
void INetworkSerializable_Deserialize(void* instance, NetworkStream* stream)
|
||||
{
|
||||
((INetworkSerializable*)instance)->Deserialize(stream);
|
||||
}
|
||||
|
||||
NetworkReplicatedObject* ResolveObject(Guid objectId, Guid ownerId, char objectTypeName[128])
|
||||
{
|
||||
// Lookup object
|
||||
@@ -131,6 +143,25 @@ NetworkReplicatedObject* ResolveObject(Guid objectId, Guid ownerId, char objectT
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NetworkReplicator::SerializeFuncPair NetworkReplicator::GetSerializer(const ScriptingTypeHandle& typeHandle)
|
||||
{
|
||||
// Get serializers pair from table
|
||||
SerializeFuncPair result(nullptr, nullptr);
|
||||
if (!SerializersTable.TryGet(typeHandle, result))
|
||||
{
|
||||
// Fallback to INetworkSerializable interface (if type implements it)
|
||||
const ScriptingType& type = typeHandle.GetType();
|
||||
const ScriptingType::InterfaceImplementation* interface = type.GetInterface(INetworkSerializable::TypeInitializer);
|
||||
if (interface)
|
||||
{
|
||||
result.First = INetworkSerializable_Serialize;
|
||||
result.Second = INetworkSerializable_Deserialize;
|
||||
SerializersTable.Add(typeHandle, result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void NetworkReplicator::AddObject(ScriptingObject* obj, ScriptingObject* owner)
|
||||
{
|
||||
if (!obj || NetworkManager::State == NetworkConnectionState::Offline)
|
||||
@@ -215,11 +246,11 @@ void NetworkInternal::NetworkReplicatorUpdate()
|
||||
}
|
||||
|
||||
// Serialize object
|
||||
// TODO: cache per-type serialization thunk to boost CPU performance
|
||||
stream->Initialize();
|
||||
if (auto* serializable = ScriptingObject::ToInterface<INetworkSerializable>(obj))
|
||||
const auto serializerFunc = NetworkReplicator::GetSerializer(obj->GetTypeHandle()).First;
|
||||
if (serializerFunc)
|
||||
{
|
||||
serializable->Serialize(stream);
|
||||
serializerFunc(obj, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -227,7 +258,7 @@ void NetworkInternal::NetworkReplicatorUpdate()
|
||||
if (!item.InvalidTypeWarn)
|
||||
{
|
||||
item.InvalidTypeWarn = true;
|
||||
LOG(Error, "[NetworkReplicator] Cannot serialize object {} (missing serialization logic)", item.ToString());
|
||||
LOG(Error, "[NetworkReplicator] Cannot serialize object {} of type {} (missing serialization logic)", item.ToString(), obj->GetType().ToString());
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
@@ -279,10 +310,10 @@ void NetworkInternal::OnNetworkMessageReplicatedObject(NetworkEvent& event, Netw
|
||||
stream->Initialize(event.Message.Buffer + event.Message.Position, msgData.DataSize);
|
||||
|
||||
// Deserialize object
|
||||
// TODO: cache per-type serialization thunk to boost CPU performance
|
||||
if (auto* serializable = ScriptingObject::ToInterface<INetworkSerializable>(obj))
|
||||
const auto deserializerFunc = NetworkReplicator::GetSerializer(obj->GetTypeHandle()).Second;
|
||||
if (deserializerFunc)
|
||||
{
|
||||
serializable->Deserialize(stream);
|
||||
deserializerFunc(obj, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -290,7 +321,7 @@ void NetworkInternal::OnNetworkMessageReplicatedObject(NetworkEvent& event, Netw
|
||||
if (!item.InvalidTypeWarn)
|
||||
{
|
||||
item.InvalidTypeWarn = true;
|
||||
LOG(Error, "[NetworkReplicator] Cannot serialize object {} (missing serialization logic)", item.ToString());
|
||||
LOG(Error, "[NetworkReplicator] Cannot serialize object {} of type {} (missing serialization logic)", item.ToString(), obj->GetType().ToString());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "Types.h"
|
||||
#include "Engine/Core/Types/Pair.h"
|
||||
#include "Engine/Core/Collections/Dictionary.h"
|
||||
#include "Engine/Scripting/ScriptingObject.h"
|
||||
#include "Engine/Scripting/ScriptingType.h"
|
||||
|
||||
@@ -12,6 +14,17 @@
|
||||
API_CLASS(static, Namespace = "FlaxEngine.Networking") class FLAXENGINE_API NetworkReplicator
|
||||
{
|
||||
DECLARE_SCRIPTING_TYPE_MINIMAL(NetworkReplicator);
|
||||
|
||||
public:
|
||||
typedef void (*SerializeFunc)(void* instance, NetworkStream* stream);
|
||||
typedef Pair<SerializeFunc, SerializeFunc> SerializeFuncPair;
|
||||
static SerializeFuncPair GetSerializer(const ScriptingTypeHandle& typeHandle);
|
||||
|
||||
/// <summary>
|
||||
/// Global table for registered types serialization methods (key is type name, value is pair of methods to serialize and deserialize object).
|
||||
/// </summary>
|
||||
static Dictionary<ScriptingTypeHandle, SerializeFuncPair> SerializersTable;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Adds the object to the network replication system.
|
||||
|
||||
Reference in New Issue
Block a user