@@ -258,18 +258,32 @@ void NetworkReplicationService::Dispose()
|
||||
|
||||
NetworkReplicationService NetworkReplicationServiceInstance;
|
||||
|
||||
void INetworkSerializable_Serialize(void* instance, NetworkStream* stream, void* tag)
|
||||
void INetworkSerializable_Native_Serialize(void* instance, NetworkStream* stream, void* tag)
|
||||
{
|
||||
const int16 vtableOffset = (int16)(intptr)tag;
|
||||
((INetworkSerializable*)((byte*)instance + vtableOffset))->Serialize(stream);
|
||||
}
|
||||
|
||||
void INetworkSerializable_Deserialize(void* instance, NetworkStream* stream, void* tag)
|
||||
void INetworkSerializable_Native_Deserialize(void* instance, NetworkStream* stream, void* tag)
|
||||
{
|
||||
const int16 vtableOffset = (int16)(intptr)tag;
|
||||
((INetworkSerializable*)((byte*)instance + vtableOffset))->Deserialize(stream);
|
||||
}
|
||||
|
||||
void INetworkSerializable_Script_Serialize(void* instance, NetworkStream* stream, void* tag)
|
||||
{
|
||||
auto obj = (ScriptingObject*)instance;
|
||||
auto interface = ScriptingObject::ToInterface<INetworkSerializable>(obj);
|
||||
interface->Serialize(stream);
|
||||
}
|
||||
|
||||
void INetworkSerializable_Script_Deserialize(void* instance, NetworkStream* stream, void* tag)
|
||||
{
|
||||
auto obj = (ScriptingObject*)instance;
|
||||
auto interface = ScriptingObject::ToInterface<INetworkSerializable>(obj);
|
||||
interface->Deserialize(stream);
|
||||
}
|
||||
|
||||
NetworkReplicatedObject* ResolveObject(Guid objectId)
|
||||
{
|
||||
auto it = Objects.Find(objectId);
|
||||
@@ -1064,9 +1078,21 @@ bool NetworkReplicator::InvokeSerializer(const ScriptingTypeHandle& typeHandle,
|
||||
const ScriptingType::InterfaceImplementation* interface = type.GetInterface(INetworkSerializable::TypeInitializer);
|
||||
if (interface)
|
||||
{
|
||||
serializer.Methods[0] = INetworkSerializable_Serialize;
|
||||
serializer.Methods[1] = INetworkSerializable_Deserialize;
|
||||
serializer.Tags[0] = serializer.Tags[1] = (void*)(intptr)interface->VTableOffset; // Pass VTableOffset to the callback
|
||||
if (interface->IsNative)
|
||||
{
|
||||
// Native interface (implemented in C++)
|
||||
serializer.Methods[0] = INetworkSerializable_Native_Serialize;
|
||||
serializer.Methods[1] = INetworkSerializable_Native_Deserialize;
|
||||
serializer.Tags[0] = serializer.Tags[1] = (void*)(intptr)interface->VTableOffset; // Pass VTableOffset to the callback
|
||||
}
|
||||
else
|
||||
{
|
||||
// Generic interface (implemented in C# or elsewhere)
|
||||
ASSERT(type.Type == ScriptingTypes::Script);
|
||||
serializer.Methods[0] = INetworkSerializable_Script_Serialize;
|
||||
serializer.Methods[1] = INetworkSerializable_Script_Deserialize;
|
||||
serializer.Tags[0] = serializer.Tags[1] = nullptr;
|
||||
}
|
||||
SerializersTable.Add(typeHandle, serializer);
|
||||
}
|
||||
else if (const ScriptingTypeHandle baseTypeHandle = typeHandle.GetType().GetBaseType())
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "BinaryModule.h"
|
||||
#include "Engine/Level/Actor.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Core/Types/Pair.h"
|
||||
#include "Engine/Utilities/StringConverter.h"
|
||||
#include "Engine/Content/Asset.h"
|
||||
#include "Engine/Content/Content.h"
|
||||
@@ -25,7 +26,8 @@
|
||||
#define ScriptingObject_id "__internalId"
|
||||
|
||||
// TODO: don't leak memory (use some kind of late manual GC for those wrapper objects)
|
||||
Dictionary<ScriptingObject*, void*> ScriptingObjectsInterfaceWrappers;
|
||||
typedef Pair<ScriptingObject*, ScriptingTypeHandle> ScriptingObjectsInterfaceKey;
|
||||
Dictionary<ScriptingObjectsInterfaceKey, void*> ScriptingObjectsInterfaceWrappers;
|
||||
|
||||
SerializableScriptingObject::SerializableScriptingObject(const SpawnParams& params)
|
||||
: ScriptingObject(params)
|
||||
@@ -202,10 +204,10 @@ ScriptingObject* ScriptingObject::FromInterface(void* interfaceObj, const Script
|
||||
}
|
||||
|
||||
// Special case for interface wrapper object
|
||||
for (auto& e : ScriptingObjectsInterfaceWrappers)
|
||||
for (const auto& e : ScriptingObjectsInterfaceWrappers)
|
||||
{
|
||||
if (e.Value == interfaceObj)
|
||||
return e.Key;
|
||||
return e.Key.First;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@@ -226,10 +228,11 @@ void* ScriptingObject::ToInterface(ScriptingObject* obj, const ScriptingTypeHand
|
||||
else if (interface)
|
||||
{
|
||||
// Interface implemented in scripting (eg. C# class inherits C++ interface)
|
||||
if (!ScriptingObjectsInterfaceWrappers.TryGet(obj, result))
|
||||
const ScriptingObjectsInterfaceKey key(obj, interfaceType);
|
||||
if (!ScriptingObjectsInterfaceWrappers.TryGet(key, result))
|
||||
{
|
||||
result = interfaceType.GetType().Interface.GetInterfaceWrapper(obj);
|
||||
ScriptingObjectsInterfaceWrappers.Add(obj, result);
|
||||
ScriptingObjectsInterfaceWrappers.Add(key, result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user