mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 11:00:32 +00:00
fix: Allowing overrides for virtual commands to call base method (#1944)
* adding override method that calls base * trying to debug instruction for call to base * extra tests * adding tests for client and target Rpc * adding fix for calls to base class Since networkbehaviour parents are processed first we can just fix the method when we see it in SubstituteMethod
This commit is contained in:
parent
2ce5880646
commit
b92da91d7a
@ -54,7 +54,58 @@ public static MethodDefinition SubstituteMethod(TypeDefinition td, MethodDefinit
|
|||||||
(md.DebugInformation.Scope, cmd.DebugInformation.Scope) = (cmd.DebugInformation.Scope, md.DebugInformation.Scope);
|
(md.DebugInformation.Scope, cmd.DebugInformation.Scope) = (cmd.DebugInformation.Scope, md.DebugInformation.Scope);
|
||||||
|
|
||||||
td.Methods.Add(cmd);
|
td.Methods.Add(cmd);
|
||||||
|
|
||||||
|
FixRemoteCallToBaseMethod(td, cmd);
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finds and fixes call to base methods within remote calls
|
||||||
|
/// <para>For example, changes `base.CmdDoSomething` to `base.CallCmdDoSomething` within `this.CallCmdDoSomething`</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <param name="method"></param>
|
||||||
|
public static void FixRemoteCallToBaseMethod(TypeDefinition type, MethodDefinition method)
|
||||||
|
{
|
||||||
|
string callName = method.Name;
|
||||||
|
|
||||||
|
// all Commands/Rpc start with "Call"
|
||||||
|
// eg CallCmdDoSomething
|
||||||
|
if (!callName.StartsWith("Call"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// eg CmdDoSomething
|
||||||
|
string baseRemoteCallName = method.Name.Substring(4);
|
||||||
|
|
||||||
|
foreach (Instruction instruction in method.Body.Instructions)
|
||||||
|
{
|
||||||
|
// if call to base.CmdDoSomething within this.CallCmdDoSomething
|
||||||
|
if (IsCallToMethod(instruction, out MethodDefinition calledMethod) &&
|
||||||
|
calledMethod.Name == baseRemoteCallName)
|
||||||
|
{
|
||||||
|
TypeDefinition baseType = type.BaseType.Resolve();
|
||||||
|
MethodDefinition baseMethod = baseType.GetMethod(callName);
|
||||||
|
|
||||||
|
instruction.Operand = baseMethod;
|
||||||
|
|
||||||
|
Weaver.DLog(type, "Replacing call to '{0}' with '{1}' inside '{2}'", calledMethod.FullName, baseMethod.FullName, method.FullName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsCallToMethod(Instruction instruction, out MethodDefinition calledMethod)
|
||||||
|
{
|
||||||
|
if (instruction.OpCode == OpCodes.Call &&
|
||||||
|
instruction.Operand is MethodDefinition method)
|
||||||
|
{
|
||||||
|
calledMethod = method;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
calledMethod = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,11 @@ public virtual void RpcSendInt(int someInt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class VirtualNoOverrideClientRpc : VirtualClientRpc
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
class VirtualOverrideClientRpc : VirtualClientRpc
|
class VirtualOverrideClientRpc : VirtualClientRpc
|
||||||
{
|
{
|
||||||
public event Action<int> onOverrideSendInt;
|
public event Action<int> onOverrideSendInt;
|
||||||
@ -25,6 +30,18 @@ public override void RpcSendInt(int someInt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class VirtualOverrideClientRpcWithBase : VirtualClientRpc
|
||||||
|
{
|
||||||
|
public event Action<int> onOverrideSendInt;
|
||||||
|
|
||||||
|
[ClientRpc]
|
||||||
|
public override void RpcSendInt(int someInt)
|
||||||
|
{
|
||||||
|
base.RpcSendInt(someInt);
|
||||||
|
onOverrideSendInt?.Invoke(someInt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class ClientRpcOverrideTest : RemoteTestBase
|
public class ClientRpcOverrideTest : RemoteTestBase
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
@ -46,6 +63,24 @@ public void VirtualRpcIsCalled()
|
|||||||
Assert.That(virtualCallCount, Is.EqualTo(1));
|
Assert.That(virtualCallCount, Is.EqualTo(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void VirtualCommandWithNoOverrideIsCalled()
|
||||||
|
{
|
||||||
|
VirtualNoOverrideClientRpc hostBehaviour = CreateHostObject<VirtualNoOverrideClientRpc>(true);
|
||||||
|
|
||||||
|
const int someInt = 20;
|
||||||
|
|
||||||
|
int virtualCallCount = 0;
|
||||||
|
hostBehaviour.onVirtualSendInt += incomingInt =>
|
||||||
|
{
|
||||||
|
virtualCallCount++;
|
||||||
|
Assert.That(incomingInt, Is.EqualTo(someInt));
|
||||||
|
};
|
||||||
|
|
||||||
|
hostBehaviour.RpcSendInt(someInt);
|
||||||
|
ProcessMessages();
|
||||||
|
Assert.That(virtualCallCount, Is.EqualTo(1));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void OverrideVirtualRpcIsCalled()
|
public void OverrideVirtualRpcIsCalled()
|
||||||
@ -71,5 +106,31 @@ public void OverrideVirtualRpcIsCalled()
|
|||||||
Assert.That(virtualCallCount, Is.EqualTo(0));
|
Assert.That(virtualCallCount, Is.EqualTo(0));
|
||||||
Assert.That(overrideCallCount, Is.EqualTo(1));
|
Assert.That(overrideCallCount, Is.EqualTo(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void OverrideVirtualWithBaseCallsBothVirtualAndBase()
|
||||||
|
{
|
||||||
|
VirtualOverrideClientRpcWithBase hostBehaviour = CreateHostObject<VirtualOverrideClientRpcWithBase>(true);
|
||||||
|
|
||||||
|
const int someInt = 20;
|
||||||
|
|
||||||
|
int virtualCallCount = 0;
|
||||||
|
int overrideCallCount = 0;
|
||||||
|
hostBehaviour.onVirtualSendInt += incomingInt =>
|
||||||
|
{
|
||||||
|
virtualCallCount++;
|
||||||
|
Assert.That(incomingInt, Is.EqualTo(someInt));
|
||||||
|
};
|
||||||
|
hostBehaviour.onOverrideSendInt += incomingInt =>
|
||||||
|
{
|
||||||
|
overrideCallCount++;
|
||||||
|
Assert.That(incomingInt, Is.EqualTo(someInt));
|
||||||
|
};
|
||||||
|
|
||||||
|
hostBehaviour.RpcSendInt(someInt);
|
||||||
|
ProcessMessages();
|
||||||
|
Assert.That(virtualCallCount, Is.EqualTo(1));
|
||||||
|
Assert.That(overrideCallCount, Is.EqualTo(1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,11 @@ public virtual void CmdSendInt(int someInt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class VirtualNoOverrideCommand : VirtualCommand
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
class VirtualOverrideCommand : VirtualCommand
|
class VirtualOverrideCommand : VirtualCommand
|
||||||
{
|
{
|
||||||
public event Action<int> onOverrideSendInt;
|
public event Action<int> onOverrideSendInt;
|
||||||
@ -25,6 +30,18 @@ public override void CmdSendInt(int someInt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class VirtualOverrideCommandWithBase : VirtualCommand
|
||||||
|
{
|
||||||
|
public event Action<int> onOverrideSendInt;
|
||||||
|
|
||||||
|
[Command]
|
||||||
|
public override void CmdSendInt(int someInt)
|
||||||
|
{
|
||||||
|
base.CmdSendInt(someInt);
|
||||||
|
onOverrideSendInt?.Invoke(someInt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class CommandOverrideTest : RemoteTestBase
|
public class CommandOverrideTest : RemoteTestBase
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
@ -46,6 +63,24 @@ public void VirtualCommandIsCalled()
|
|||||||
Assert.That(virtualCallCount, Is.EqualTo(1));
|
Assert.That(virtualCallCount, Is.EqualTo(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void VirtualCommandWithNoOverrideIsCalled()
|
||||||
|
{
|
||||||
|
VirtualNoOverrideCommand hostBehaviour = CreateHostObject<VirtualNoOverrideCommand>(true);
|
||||||
|
|
||||||
|
const int someInt = 20;
|
||||||
|
|
||||||
|
int virtualCallCount = 0;
|
||||||
|
hostBehaviour.onVirtualSendInt += incomingInt =>
|
||||||
|
{
|
||||||
|
virtualCallCount++;
|
||||||
|
Assert.That(incomingInt, Is.EqualTo(someInt));
|
||||||
|
};
|
||||||
|
|
||||||
|
hostBehaviour.CmdSendInt(someInt);
|
||||||
|
ProcessMessages();
|
||||||
|
Assert.That(virtualCallCount, Is.EqualTo(1));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void OverrideVirtualCommandIsCalled()
|
public void OverrideVirtualCommandIsCalled()
|
||||||
@ -71,5 +106,31 @@ public void OverrideVirtualCommandIsCalled()
|
|||||||
Assert.That(virtualCallCount, Is.EqualTo(0));
|
Assert.That(virtualCallCount, Is.EqualTo(0));
|
||||||
Assert.That(overrideCallCount, Is.EqualTo(1));
|
Assert.That(overrideCallCount, Is.EqualTo(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void OverrideVirtualWithBaseCallsBothVirtualAndBase()
|
||||||
|
{
|
||||||
|
VirtualOverrideCommandWithBase hostBehaviour = CreateHostObject<VirtualOverrideCommandWithBase>(true);
|
||||||
|
|
||||||
|
const int someInt = 20;
|
||||||
|
|
||||||
|
int virtualCallCount = 0;
|
||||||
|
int overrideCallCount = 0;
|
||||||
|
hostBehaviour.onVirtualSendInt += incomingInt =>
|
||||||
|
{
|
||||||
|
virtualCallCount++;
|
||||||
|
Assert.That(incomingInt, Is.EqualTo(someInt));
|
||||||
|
};
|
||||||
|
hostBehaviour.onOverrideSendInt += incomingInt =>
|
||||||
|
{
|
||||||
|
overrideCallCount++;
|
||||||
|
Assert.That(incomingInt, Is.EqualTo(someInt));
|
||||||
|
};
|
||||||
|
|
||||||
|
hostBehaviour.CmdSendInt(someInt);
|
||||||
|
ProcessMessages();
|
||||||
|
Assert.That(virtualCallCount, Is.EqualTo(1));
|
||||||
|
Assert.That(overrideCallCount, Is.EqualTo(1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,11 @@ public virtual void TargetSendInt(int someInt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class VirtualNoOverrideTargetRpc : VirtualTargetRpc
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
class VirtualOverrideTargetRpc : VirtualTargetRpc
|
class VirtualOverrideTargetRpc : VirtualTargetRpc
|
||||||
{
|
{
|
||||||
public event Action<int> onOverrideSendInt;
|
public event Action<int> onOverrideSendInt;
|
||||||
@ -25,6 +30,18 @@ public override void TargetSendInt(int someInt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class VirtualOverrideTargetRpcWithBase : VirtualTargetRpc
|
||||||
|
{
|
||||||
|
public event Action<int> onOverrideSendInt;
|
||||||
|
|
||||||
|
[TargetRpc]
|
||||||
|
public override void TargetSendInt(int someInt)
|
||||||
|
{
|
||||||
|
base.TargetSendInt(someInt);
|
||||||
|
onOverrideSendInt?.Invoke(someInt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class TargetRpcOverrideTest : RemoteTestBase
|
public class TargetRpcOverrideTest : RemoteTestBase
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
@ -46,6 +63,24 @@ public void VirtualRpcIsCalled()
|
|||||||
Assert.That(virtualCallCount, Is.EqualTo(1));
|
Assert.That(virtualCallCount, Is.EqualTo(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void VirtualCommandWithNoOverrideIsCalled()
|
||||||
|
{
|
||||||
|
VirtualNoOverrideTargetRpc hostBehaviour = CreateHostObject<VirtualNoOverrideTargetRpc>(true);
|
||||||
|
|
||||||
|
const int someInt = 20;
|
||||||
|
|
||||||
|
int virtualCallCount = 0;
|
||||||
|
hostBehaviour.onVirtualSendInt += incomingInt =>
|
||||||
|
{
|
||||||
|
virtualCallCount++;
|
||||||
|
Assert.That(incomingInt, Is.EqualTo(someInt));
|
||||||
|
};
|
||||||
|
|
||||||
|
hostBehaviour.TargetSendInt(someInt);
|
||||||
|
ProcessMessages();
|
||||||
|
Assert.That(virtualCallCount, Is.EqualTo(1));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void OverrideVirtualRpcIsCalled()
|
public void OverrideVirtualRpcIsCalled()
|
||||||
@ -71,5 +106,31 @@ public void OverrideVirtualRpcIsCalled()
|
|||||||
Assert.That(virtualCallCount, Is.EqualTo(0));
|
Assert.That(virtualCallCount, Is.EqualTo(0));
|
||||||
Assert.That(overrideCallCount, Is.EqualTo(1));
|
Assert.That(overrideCallCount, Is.EqualTo(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void OverrideVirtualWithBaseCallsBothVirtualAndBase()
|
||||||
|
{
|
||||||
|
VirtualOverrideTargetRpcWithBase hostBehaviour = CreateHostObject<VirtualOverrideTargetRpcWithBase>(true);
|
||||||
|
|
||||||
|
const int someInt = 20;
|
||||||
|
|
||||||
|
int virtualCallCount = 0;
|
||||||
|
int overrideCallCount = 0;
|
||||||
|
hostBehaviour.onVirtualSendInt += incomingInt =>
|
||||||
|
{
|
||||||
|
virtualCallCount++;
|
||||||
|
Assert.That(incomingInt, Is.EqualTo(someInt));
|
||||||
|
};
|
||||||
|
hostBehaviour.onOverrideSendInt += incomingInt =>
|
||||||
|
{
|
||||||
|
overrideCallCount++;
|
||||||
|
Assert.That(incomingInt, Is.EqualTo(someInt));
|
||||||
|
};
|
||||||
|
|
||||||
|
hostBehaviour.TargetSendInt(someInt);
|
||||||
|
ProcessMessages();
|
||||||
|
Assert.That(virtualCallCount, Is.EqualTo(1));
|
||||||
|
Assert.That(overrideCallCount, Is.EqualTo(1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,6 +99,7 @@
|
|||||||
<Compile Include="WeaverCommandTests~\CommandValid.cs" />
|
<Compile Include="WeaverCommandTests~\CommandValid.cs" />
|
||||||
<Compile Include="WeaverCommandTests~\CommandWithArguments.cs" />
|
<Compile Include="WeaverCommandTests~\CommandWithArguments.cs" />
|
||||||
<Compile Include="WeaverCommandTests~\OverrideAbstractCommand.cs" />
|
<Compile Include="WeaverCommandTests~\OverrideAbstractCommand.cs" />
|
||||||
|
<Compile Include="WeaverCommandTests~\OverrideVirtualCallBaseCommand.cs" />
|
||||||
<Compile Include="WeaverCommandTests~\OverrideVirtualCommand.cs" />
|
<Compile Include="WeaverCommandTests~\OverrideVirtualCommand.cs" />
|
||||||
<Compile Include="WeaverCommandTests~\VirtualCommand.cs" />
|
<Compile Include="WeaverCommandTests~\VirtualCommand.cs" />
|
||||||
<Compile Include="WeaverCommandTests~\CommandWithSenderConnectionAndOtherArgs.cs" />
|
<Compile Include="WeaverCommandTests~\CommandWithSenderConnectionAndOtherArgs.cs" />
|
||||||
|
@ -70,6 +70,12 @@ public void OverrideVirtualCommand()
|
|||||||
Assert.That(weaverErrors, Is.Empty);
|
Assert.That(weaverErrors, Is.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void OverrideVirtualCallBaseCommand()
|
||||||
|
{
|
||||||
|
Assert.That(weaverErrors, Is.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void AbstractCommand()
|
public void AbstractCommand()
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
using Mirror;
|
||||||
|
|
||||||
|
|
||||||
|
namespace WeaverCommandTests.OverrideVirtualCallBaseCommand
|
||||||
|
{
|
||||||
|
class OverrideVirtualCallBaseCommand : baseBehaviour
|
||||||
|
{
|
||||||
|
[Command]
|
||||||
|
protected override void CmdDoSomething()
|
||||||
|
{
|
||||||
|
// do somethin
|
||||||
|
base.CmdDoSomething();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class baseBehaviour : NetworkBehaviour
|
||||||
|
{
|
||||||
|
[Command]
|
||||||
|
protected virtual void CmdDoSomething()
|
||||||
|
{
|
||||||
|
// do more stuff
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user