Skip to content

Commit 0c9ac4e

Browse files
fix: notauthority da mode urpc sending to self (#3000)
* fix NotAuthority should not include the service observer. * fix ProxyRpcTargetGroup should not send anything if there is no one to send to. * style Adding comments about why this was changed * test adding partial validation of this fix where it still has to be manually tested with a service connection. * update updating the changelog entry.
1 parent 29e5146 commit 0c9ac4e

File tree

5 files changed

+119
-0
lines changed

5 files changed

+119
-0
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ Additional documentation and release notes are available at [Multiplayer Documen
1212

1313
### Fixed
1414

15+
- Fixed issue where `NotAuthorityTarget` would include the service observer in the list of targets to send the RPC to as opposed to excluding the service observer as it should. (#3000)
16+
- Fixed issue where `ProxyRpcTargetGroup` could attempt to send a message if there were no targets to send to. (#3000)
17+
1518
### Changed
1619

1720

com.unity.netcode.gameobjects/Runtime/Messaging/RpcTargets/NotAuthorityRpcTarget.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ internal override void Send(NetworkBehaviour behaviour, ref RpcMessage message,
2929
{
3030
continue;
3131
}
32+
33+
// The CMB-Service holds ID 0 and should not be added to the targets
34+
if (clientId == NetworkManager.ServerClientId && m_NetworkManager.CMBServiceConnection)
35+
{
36+
continue;
37+
}
3238
m_GroupSendTarget.Add(clientId);
3339
}
3440
}
@@ -41,6 +47,12 @@ internal override void Send(NetworkBehaviour behaviour, ref RpcMessage message,
4147
continue;
4248
}
4349

50+
// The CMB-Service holds ID 0 and should not be added to the targets
51+
if (clientId == NetworkManager.ServerClientId && m_NetworkManager.CMBServiceConnection)
52+
{
53+
continue;
54+
}
55+
4456
if (clientId == m_NetworkManager.LocalClientId)
4557
{
4658
m_LocalSendRpcTarget.Send(behaviour, ref message, delivery, rpcParams);

com.unity.netcode.gameobjects/Runtime/Messaging/RpcTargets/ProxyRpcTargetGroup.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ internal class ProxyRpcTargetGroup : BaseRpcTarget, IDisposable, IGroupRpcTarget
1717

1818
internal override void Send(NetworkBehaviour behaviour, ref RpcMessage message, NetworkDelivery delivery, RpcParams rpcParams)
1919
{
20+
// If there are no targets then don't attempt to send anything.
21+
if (TargetClientIds.Length == 0 && Ids.Count == 0)
22+
{
23+
return;
24+
}
2025
var proxyMessage = new ProxyMessage { Delivery = delivery, TargetClientIds = TargetClientIds.AsArray(), WrappedMessage = message };
2126
#if DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE
2227
var size =
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
using System.Collections;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
using NUnit.Framework;
5+
using Unity.Netcode.TestHelpers.Runtime;
6+
7+
namespace Unity.Netcode.RuntimeTests
8+
{
9+
/// <summary>
10+
/// This test validates PR-3000 where it would invoke
11+
/// TODO:
12+
/// We really need to get the service running during tests
13+
/// so we can validate these issues. While this test does
14+
/// partially validate it we still need to manually validate
15+
/// with a service connection.
16+
/// </summary>
17+
[TestFixture(HostOrServer.Host)]
18+
[TestFixture(HostOrServer.DAHost)]
19+
public class RpcProxyMessageTesting : NetcodeIntegrationTest
20+
{
21+
protected override int NumberOfClients => 2;
22+
23+
private List<RpcProxyText> m_ProxyTestInstances = new List<RpcProxyText>();
24+
25+
private StringBuilder m_ValidationLogger = new StringBuilder();
26+
27+
public RpcProxyMessageTesting(HostOrServer hostOrServer) : base(hostOrServer) { }
28+
29+
protected override IEnumerator OnSetup()
30+
{
31+
m_ProxyTestInstances.Clear();
32+
return base.OnSetup();
33+
}
34+
35+
protected override void OnCreatePlayerPrefab()
36+
{
37+
m_PlayerPrefab.AddComponent<RpcProxyText>();
38+
base.OnCreatePlayerPrefab();
39+
}
40+
41+
42+
private bool ValidateRpcProxyRpcs()
43+
{
44+
m_ValidationLogger.Clear();
45+
foreach (var proxy in m_ProxyTestInstances)
46+
{
47+
if (proxy.ReceivedRpc.Count < NumberOfClients)
48+
{
49+
m_ValidationLogger.AppendLine($"Not all clients received RPC from Client-{proxy.OwnerClientId}!");
50+
}
51+
foreach (var clientId in proxy.ReceivedRpc)
52+
{
53+
if (clientId == proxy.OwnerClientId)
54+
{
55+
m_ValidationLogger.AppendLine($"Client-{proxy.OwnerClientId} sent itself an Rpc!");
56+
}
57+
}
58+
}
59+
return m_ValidationLogger.Length == 0;
60+
}
61+
62+
63+
public IEnumerator ProxyDoesNotInvokeOnSender()
64+
{
65+
m_ProxyTestInstances.Add(m_ServerNetworkManager.LocalClient.PlayerObject.GetComponent<RpcProxyText>());
66+
foreach (var client in m_ClientNetworkManagers)
67+
{
68+
m_ProxyTestInstances.Add(client.LocalClient.PlayerObject.GetComponent<RpcProxyText>());
69+
}
70+
71+
foreach (var clientProxyTest in m_ProxyTestInstances)
72+
{
73+
clientProxyTest.SendToEveryOneButMe();
74+
}
75+
76+
yield return WaitForConditionOrTimeOut(ValidateRpcProxyRpcs);
77+
AssertOnTimeout(m_ValidationLogger.ToString());
78+
}
79+
80+
public class RpcProxyText : NetworkBehaviour
81+
{
82+
public List<ulong> ReceivedRpc = new List<ulong>();
83+
84+
public void SendToEveryOneButMe()
85+
{
86+
var baseTarget = NetworkManager.DistributedAuthorityMode ? RpcTarget.NotAuthority : RpcTarget.NotMe;
87+
TestRpc(baseTarget);
88+
}
89+
90+
[Rpc(SendTo.SpecifiedInParams)]
91+
private void TestRpc(RpcParams rpcParams = default)
92+
{
93+
ReceivedRpc.Add(rpcParams.Receive.SenderClientId);
94+
}
95+
}
96+
}
97+
}

com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/RpcProxyMessageTesting.cs.meta

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)