Fix invoking Client RPC on Host client when it's not included in targetIds list
This commit is contained in:
@@ -114,3 +114,14 @@ inline Span<T> ToSpan(const T* ptr, int32 length)
|
||||
{
|
||||
return Span<T>(ptr, length);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool SpanContains(const Span<T> span, const T& value)
|
||||
{
|
||||
for (int32 i = 0; i < span.Length(); i++)
|
||||
{
|
||||
if (span.Get()[i] == value)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -700,9 +700,9 @@ void NetworkReplicator::AddRPC(const ScriptingTypeHandle& typeHandle, const Stri
|
||||
NetworkRpcInfo::RPCsTable[rpcName] = rpcInfo;
|
||||
}
|
||||
|
||||
void NetworkReplicator::CSharpEndInvokeRPC(ScriptingObject* obj, const ScriptingTypeHandle& type, const StringAnsiView& name, NetworkStream* argsStream, MArray* targetIds)
|
||||
bool NetworkReplicator::CSharpEndInvokeRPC(ScriptingObject* obj, const ScriptingTypeHandle& type, const StringAnsiView& name, NetworkStream* argsStream, MArray* targetIds)
|
||||
{
|
||||
EndInvokeRPC(obj, type, GetCSharpCachedName(name), argsStream, MUtils::ToSpan<uint32>(targetIds));
|
||||
return EndInvokeRPC(obj, type, GetCSharpCachedName(name), argsStream, MUtils::ToSpan<uint32>(targetIds));
|
||||
}
|
||||
|
||||
StringAnsiView NetworkReplicator::GetCSharpCachedName(const StringAnsiView& name)
|
||||
@@ -1113,12 +1113,12 @@ NetworkStream* NetworkReplicator::BeginInvokeRPC()
|
||||
return CachedWriteStream;
|
||||
}
|
||||
|
||||
void NetworkReplicator::EndInvokeRPC(ScriptingObject* obj, const ScriptingTypeHandle& type, const StringAnsiView& name, NetworkStream* argsStream, Span<uint32> targetIds)
|
||||
bool NetworkReplicator::EndInvokeRPC(ScriptingObject* obj, const ScriptingTypeHandle& type, const StringAnsiView& name, NetworkStream* argsStream, Span<uint32> targetIds)
|
||||
{
|
||||
Scripting::ObjectsLookupIdMapping.Set(nullptr);
|
||||
const NetworkRpcInfo* info = NetworkRpcInfo::RPCsTable.TryGet(NetworkRpcName(type, name));
|
||||
if (!info || !obj || NetworkManager::IsOffline())
|
||||
return;
|
||||
return false;
|
||||
ObjectsLock.Lock();
|
||||
auto& rpc = RpcQueue.AddOne();
|
||||
rpc.Object = obj;
|
||||
@@ -1135,6 +1135,16 @@ void NetworkReplicator::EndInvokeRPC(ScriptingObject* obj, const ScriptingTypeHa
|
||||
}
|
||||
#endif
|
||||
ObjectsLock.Unlock();
|
||||
|
||||
// Check if skip local execution (eg. server rpc called from client or client rpc with specific targets)
|
||||
const NetworkManagerMode networkMode = NetworkManager::Mode;
|
||||
if (info->Server && networkMode == NetworkManagerMode::Client)
|
||||
return true;
|
||||
if (info->Client && networkMode == NetworkManagerMode::Server)
|
||||
return true;
|
||||
if (info->Client && networkMode == NetworkManagerMode::Host && targetIds.IsValid() && !SpanContains(targetIds, NetworkManager::LocalClientId))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void NetworkInternal::NetworkReplicatorClientConnected(NetworkClient* client)
|
||||
|
||||
@@ -120,10 +120,11 @@ namespace FlaxEngine.Networking
|
||||
/// <param name="name">The RPC name.</param>
|
||||
/// <param name="argsStream">The RPC serialized arguments stream returned from BeginInvokeRPC.</param>
|
||||
/// <param name="targetIds">Optional list with network client IDs that should receive RPC. Empty to send on all clients. Ignored by Server RPCs.</param>
|
||||
/// <returns>True if RPC cannot be executed locally, false if execute it locally too (checks RPC mode and target client ids).</returns>
|
||||
[Unmanaged]
|
||||
public static void EndInvokeRPC(Object obj, Type type, string name, NetworkStream argsStream, uint[] targetIds = null)
|
||||
public static bool EndInvokeRPC(Object obj, Type type, string name, NetworkStream argsStream, uint[] targetIds = null)
|
||||
{
|
||||
Internal_CSharpEndInvokeRPC(FlaxEngine.Object.GetUnmanagedPtr(obj), type, name, FlaxEngine.Object.GetUnmanagedPtr(argsStream), targetIds);
|
||||
return Internal_CSharpEndInvokeRPC(FlaxEngine.Object.GetUnmanagedPtr(obj), type, name, FlaxEngine.Object.GetUnmanagedPtr(argsStream), targetIds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -195,13 +195,14 @@ public:
|
||||
/// <param name="name">The RPC name.</param>
|
||||
/// <param name="argsStream">The RPC serialized arguments stream returned from BeginInvokeRPC.</param>
|
||||
/// <param name="targetIds">Optional list with network client IDs that should receive RPC. Empty to send on all clients. Ignored by Server RPCs.</param>
|
||||
static void EndInvokeRPC(ScriptingObject* obj, const ScriptingTypeHandle& type, const StringAnsiView& name, NetworkStream* argsStream, Span<uint32> targetIds = Span<uint32>());
|
||||
/// <returns>True if RPC cannot be executed locally, false if execute it locally too (checks RPC mode and target client ids).</returns>
|
||||
static bool EndInvokeRPC(ScriptingObject* obj, const ScriptingTypeHandle& type, const StringAnsiView& name, NetworkStream* argsStream, Span<uint32> targetIds = Span<uint32>());
|
||||
|
||||
private:
|
||||
#if !COMPILE_WITHOUT_CSHARP
|
||||
API_FUNCTION(NoProxy) static void AddSerializer(const ScriptingTypeHandle& typeHandle, const Function<void(void*, void*)>& serialize, const Function<void(void*, void*)>& deserialize);
|
||||
API_FUNCTION(NoProxy) static void AddRPC(const ScriptingTypeHandle& typeHandle, const StringAnsiView& name, const Function<void(void*, void*)>& execute, bool isServer, bool isClient, NetworkChannelType channel);
|
||||
API_FUNCTION(NoProxy) static void CSharpEndInvokeRPC(ScriptingObject* obj, const ScriptingTypeHandle& type, const StringAnsiView& name, NetworkStream* argsStream, MArray* targetIds);
|
||||
API_FUNCTION(NoProxy) static bool CSharpEndInvokeRPC(ScriptingObject* obj, const ScriptingTypeHandle& type, const StringAnsiView& name, NetworkStream* argsStream, MArray* targetIds);
|
||||
static StringAnsiView GetCSharpCachedName(const StringAnsiView& name);
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -41,7 +41,7 @@ struct FLAXENGINE_API NetworkRpcInfo
|
||||
uint8 Client : 1;
|
||||
uint8 Channel : 4;
|
||||
void (*Execute)(ScriptingObject* obj, NetworkStream* stream, void* tag);
|
||||
void (*Invoke)(ScriptingObject* obj, void** args);
|
||||
bool (*Invoke)(ScriptingObject* obj, void** args);
|
||||
void* Tag;
|
||||
|
||||
/// <summary>
|
||||
@@ -83,10 +83,7 @@ FORCE_INLINE void NetworkRpcInitArg(Array<void*, FixedAllocation<16>>& args, con
|
||||
{ \
|
||||
Array<void*, FixedAllocation<16>> args; \
|
||||
NetworkRpcInitArg(args, __VA_ARGS__); \
|
||||
rpcInfo.Invoke(this, args.Get()); \
|
||||
if (rpcInfo.Server && networkMode == NetworkManagerMode::Client) \
|
||||
return; \
|
||||
if (rpcInfo.Client && networkMode == NetworkManagerMode::Server) \
|
||||
if (rpcInfo.Invoke(this, args.Get())) \
|
||||
return; \
|
||||
} \
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user