Skip to content

feat: owner-writable NetworkVariable<T> #1762

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Mar 17, 2022
Merged

Conversation

0xFA11
Copy link
Contributor

@0xFA11 0xFA11 commented Mar 1, 2022

By adding enum NetworkVariableWritePermission and Owner/Server options, we're also implementing owner-writable network variables which allows owning clients to change value immediately and replicate that across the network via server.

MTT-2845

Changelog

com.unity.netcode.gameobjects

  • Added NetworkVariableWritePermission to NetworkVariableBase and implemented Owner writable netvars.

Testing and Documentation

  • Added NetworkVariablePermissionTests
  • Documentation will be done by MTT-2846 separately

@0xFA11 0xFA11 force-pushed the feat/ownernetworkvariable branch from 07aed2e to d174d40 Compare March 12, 2022 00:50
@0xFA11 0xFA11 changed the title feat: OwnerNetworkVariable feat: owner-writable NetworkVariable<T> Mar 12, 2022
@0xFA11 0xFA11 force-pushed the feat/ownernetworkvariable branch from a3562e4 to d174d40 Compare March 13, 2022 02:48
[TestFixtureSource(nameof(TestDataSource))]
public class NetworkVariablePermissionTests : NetcodeIntegrationTest
{
public static IEnumerable<TestFixtureData> TestDataSource()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😍

yield return null;
}

private void AssertOwnerWritableAreEqualOnAll()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎺

@0xFA11 0xFA11 marked this pull request as ready for review March 17, 2022 15:12
@@ -595,9 +593,11 @@ private void NetworkVariableUpdate(ulong clientId, int behaviourIndex)
var shouldSend = false;
for (int k = 0; k < NetworkVariableFields.Count; k++)
{
if (NetworkVariableFields[k].ShouldWrite(clientId, IsServer))
var networkVariable = NetworkVariableFields[k];
if (networkVariable.IsDirty() && networkVariable.CanClientRead(targetClientId))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the rationale for copying the code from ShouldWrite and editing it here, as opposed to improving/adjusting/modifying ShouldWrite? Just wondering what will make the code more easily maintainable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because there is no ShouldWrite anymore. there are CanClientRead and CanClientWrite for perm checks, whether or not to write (send) is determined outside, here.

@@ -429,8 +425,7 @@ internal void SnapshotDespawn()
internal void SnapshotDespawn(ulong clientId)
{
var command = GetDespawnCommand();
command.TargetClientIds = new List<ulong>();
command.TargetClientIds.Add(clientId);
command.TargetClientIds = new List<ulong> { clientId };
Copy link
Contributor

@jeffreyrainy jeffreyrainy Mar 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, yeah, those are great changes, but they make the PR harder to process and possibly harder to merge later. We should try to have PRs that address just one thing and side clean-up PRs are fine too :-). < /nitpick> < /jeffshouldgethiscoffee>

@@ -31,9 +31,9 @@ public void Serialize(FastBufferWriter writer)
writer.WriteValue(NetworkObjectId);
writer.WriteValue(NetworkBehaviourIndex);

for (int k = 0; k < NetworkBehaviour.NetworkVariableFields.Count; k++)
for (int i = 0; i < NetworkBehaviour.NetworkVariableFields.Count; i++)
Copy link
Contributor

@jeffreyrainy jeffreyrainy Mar 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:headscratch:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol, sorry

/// </summary>
/// <param name="values">The initial value to use for the NetworkList</param>
public NetworkList(IEnumerable<T> values)
public NetworkList(IEnumerable<T> values = default,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😻

/// </summary>
/// <param name="value">The initial value to use for the NetworkVariable</param>
public NetworkVariable(T value)
public NetworkVariable(T value = default,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😻

Copy link
Collaborator

@NoelStephensUnity NoelStephensUnity left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other than adding a PR number to the end of your changelog entry, it looks good to me!

@@ -10,9 +10,12 @@ Additional documentation and release notes are available at [Multiplayer Documen

### Added

- Added `NetworkVariableWritePermission` to `NetworkVariableBase` and implemented `Owner` writable netvars. (#1762)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dunno if we want to mention this adds client driven capabilities? Just so users do the association?

testCompServer.OwnerWritable_Position.Value = newValue;
yield return NetcodeIntegrationTestHelpers.WaitForTicks(m_ServerNetworkManager, 2);

AssertOwnerWritableAreEqualOnAll();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if for whatever reason server side Value gets reverted back to it's original value and then client side the Value never changes, this test would still pass :(
with these, I usually prefer to set very specific values and make sure they are the ones expected on arrival.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SamuelBellomo Ok, I see what you are saying...
@MFatihMAR So maybe you could do this:

private void AssertServerWritableAreEqualOnAll(Vector3 expectedPosition)
{
    var testObjServer = m_ServerNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
    var testCompServer = testObjServer.GetComponent<NetVarPermTestComp>();
    foreach (var clientNetworkManager in m_ClientNetworkManagers)
    {
        var testObjClient = clientNetworkManager.SpawnManager.SpawnedObjects[m_TestObjId];
        var testCompClient = testObjClient.GetComponent<NetVarPermTestComp>();
        Assert.AreEqual(testCompServer.ServerWritable_Position.Value, expectedPosition); 
        Assert.AreEqual(testCompServer.ServerWritable_Position.Value, testCompClient.ServerWritable_Position.Value);
        Assert.AreEqual(testCompServer.ServerWritable_Position.ReadPerm, testCompClient.ServerWritable_Position.ReadPerm);
        Assert.AreEqual(testCompServer.ServerWritable_Position.WritePerm, testCompClient.ServerWritable_Position.WritePerm);
    }
}

And update your tests to pass in the expected new value to AssertServerWritableAreEqualOnAll?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

technically that's being caught but the fact that it's hard to imply made me add an extra assert to compare .Value against newValue

yield return NetcodeIntegrationTestHelpers.WaitForTicks(m_ClientNetworkManagers[clientManagerIndex], 4);

AssertOwnerWritableAreEqualOnAll();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also check that a non owner can't write on that netvar, but both owner and non-owner can still read

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also check that the server can't write to those, in addition to another client that's not the owner.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

implemented NetworkVariablePermissionTests.ServerCannotChangeOwnerWritableNetVar() test

yield return NetcodeIntegrationTestHelpers.WaitForTicks(m_ClientNetworkManagers[clientManagerIndex], 4);
Assert.AreEqual(testCompServer.ServerWritable_Position.Value, oldValue);

AssertServerWritableAreEqualOnAll();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, if the value did change, even with throwing the exception, this would still pass

@0xFA11 0xFA11 enabled auto-merge (squash) March 17, 2022 21:11
@0xFA11 0xFA11 merged commit 6695fbc into develop Mar 17, 2022
@0xFA11 0xFA11 deleted the feat/ownernetworkvariable branch March 17, 2022 22:42
@0xFA11 0xFA11 mentioned this pull request Mar 18, 2022
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants