Skip to content

Commit

Permalink
fix: fixing use of GO/NI/NB inside Constructor
Browse files Browse the repository at this point in the history
  • Loading branch information
James-Frowen committed Mar 28, 2024
1 parent f183d42 commit 2f5db3d
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 5 deletions.
24 changes: 19 additions & 5 deletions Assets/Mirage/Weaver/Processors/PropertySiteProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@

namespace Mirage.Weaver
{
// todo add docs for what this type does
/// <summary>
/// Replaces SyncVar fields with their property getter/setting
/// </summary>
public class PropertySiteProcessor
{
// setter functions that replace [SyncVar] member variable references. dict<field, replacement>
Expand All @@ -19,10 +21,22 @@ public void Process(ModuleDefinition moduleDef)
CodePass.ForEachInstruction(moduleDef, WeavedMethods, ProcessInstruction);
}

private static bool WeavedMethods(MethodDefinition md) =>
md.Name != ".cctor" &&
md.Name != NetworkBehaviourProcessor.ProcessedFunctionName &&
!md.IsConstructor;
private static bool WeavedMethods(MethodDefinition md)
{
if (md.Name == ".cctor")
return false;
if (md.Name == NetworkBehaviourProcessor.ProcessedFunctionName)
return false;

// dont use network get/set inside unity consturctors
// this is because they will try to set dirtyBit and throw unity errors
if (md.DeclaringType.IsDerivedFrom<UnityEngine.Object>() && md.IsConstructor)
return false;

// note: Constructor for non-unity types should be safe to use, for example get/set a sync var on a NB from without a struct

return true;
}

private Instruction ProcessInstruction(MethodDefinition md, Instruction instr, SequencePoint sequencePoint)
{
Expand Down
92 changes: 92 additions & 0 deletions Assets/Tests/Runtime/Syncing/SyncVarFieldReplaceTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using Cysharp.Threading.Tasks;
using NUnit.Framework;

namespace Mirage.Tests.Runtime.Syncing
{
public class SyncVarFieldReplaceTest : ServerSetup
{
private NetworkIdentity _target1;
private NetworkIdentity _target2;
private MockPlayer component;

protected override UniTask LateSetup()
{
_target1 = CreateNetworkIdentity();
serverObjectManager.Spawn(_target1, 1);

_target2 = CreateNetworkIdentity();
serverObjectManager.Spawn(_target2, 1);

component = CreateBehaviour<MockPlayer>();
component.target = _target1;
serverObjectManager.Spawn(component.Identity, 2);

return base.LateSetup();
}

[Test]
public void CanGetSyncVarFromMethod()
{
var mock = new MockCSharpClass();
mock.GetTarget(component);
Assert.That(mock.netid, Is.Not.Zero.And.EqualTo(component.target.NetId));
}

[Test]
public void CanSetSyncVarFromMethod()
{
var mock = new MockCSharpClass();
mock.SetTarget(component, _target2);
Assert.That(component.target, Is.EqualTo(_target2));
}
[Test]
public void CanGetSyncVarFromConstructor()
{
var mock = new MockCSharpClass(component);
Assert.That(mock.netid, Is.Not.Zero.And.EqualTo(component.target.NetId));
}

[Test]
public void CanSetSyncVarFromConstructor()
{
var mock = new MockCSharpClass(component, _target2);
Assert.That(component.target, Is.EqualTo(_target2));
}


public class MockCSharpClass
{
public uint netid;
private MockPlayer player;

public MockCSharpClass() { }
public MockCSharpClass(MockPlayer myPlayer)
{
// tests getting syncvar from constructor of c# only class
if (myPlayer.target != null)
netid = myPlayer.target.NetId;

player = myPlayer;
}

public MockCSharpClass(MockPlayer myPlayer, NetworkIdentity target)
{
// tests setting syncvar from constructor of c# only class
myPlayer.target = target;
}

public void GetTarget(MockPlayer myPlayer)
{
if (myPlayer.target != null)
{
netid = myPlayer.target.NetId;
}
}

public void SetTarget(MockPlayer myPlayer, NetworkIdentity target)
{
myPlayer.target = target;
}
}
}
}
11 changes: 11 additions & 0 deletions Assets/Tests/Runtime/Syncing/SyncVarFieldReplaceTest.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 2f5db3d

Please sign in to comment.