breaking: adding option to receive NetworkConnectionToClient in Comand (#1970)

* moving exists check to its own function

* moving order and adding whitespace

* adding SenderConnection Attribute

* adding weaver tests for SenderConnection Attribute

* tests for sender connection

* updating valid method to work with sender connection

* using RemoteCallType in read write calls

* adding sender connection to CallCmd

* updating CmdDelegate

* adding NetworkConnection to invokeFunction

* updating old tests

* removing SenderConnectionAttribute

* typo

* adding version 14 defines
This commit is contained in:
James Frowen 2020-06-07 11:25:21 +01:00 committed by GitHub
parent 822b04155d
commit 55736eba5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 262 additions and 45 deletions

View File

@ -27,7 +27,8 @@ public static void AddDefineSymbols()
"MIRROR_10_0_OR_NEWER",
"MIRROR_11_0_OR_NEWER",
"MIRROR_12_0_OR_NEWER",
"MIRROR_13_0_OR_NEWER"
"MIRROR_13_0_OR_NEWER",
"MIRROR_14_0_OR_NEWER"
};
// only touch PlayerSettings if we actually modified it.

View File

@ -7,6 +7,11 @@ namespace Mirror.Weaver
public static class Extensions
{
public static bool IsDerivedFrom(this TypeDefinition td, TypeReference baseClass)
{
return IsDerivedFrom(td, baseClass.FullName);
}
public static bool IsDerivedFrom(this TypeDefinition td, string baseClassFullName)
{
if (!td.IsClass)
return false;
@ -24,7 +29,7 @@ public static bool IsDerivedFrom(this TypeDefinition td, TypeReference baseClass
parentName = parentName.Substring(0, index);
}
if (parentName == baseClass.FullName)
if (parentName == baseClassFullName)
{
return true;
}

View File

@ -51,7 +51,7 @@ public static MethodDefinition ProcessCommandCall(TypeDefinition td, MethodDefin
NetworkBehaviourProcessor.WriteCreateWriter(worker);
// write all the arguments that the user passed to the Cmd call
if (!NetworkBehaviourProcessor.WriteArguments(worker, md, false))
if (!NetworkBehaviourProcessor.WriteArguments(worker, md, RemoteCallType.Command))
return null;
string cmdName = md.Name;
@ -87,7 +87,7 @@ public static MethodDefinition ProcessCommandCall(TypeDefinition td, MethodDefin
/*
// generates code like:
protected static void InvokeCmdCmdThrust(NetworkBehaviour obj, NetworkReader reader)
protected static void InvokeCmdCmdThrust(NetworkBehaviour obj, NetworkReader reader, NetworkConnection senderConnection)
{
if (!NetworkServer.active)
{
@ -111,9 +111,11 @@ public static MethodDefinition ProcessCommandInvoke(TypeDefinition td, MethodDef
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Castclass, td));
if (!NetworkBehaviourProcessor.ReadArguments(method, worker, false))
if (!NetworkBehaviourProcessor.ReadArguments(method, worker, RemoteCallType.Command))
return null;
AddSenderConnection(method, worker);
// invoke actual command function
worker.Append(worker.Create(OpCodes.Callvirt, cmdCallFunc));
worker.Append(worker.Create(OpCodes.Ret));
@ -124,6 +126,19 @@ public static MethodDefinition ProcessCommandInvoke(TypeDefinition td, MethodDef
return cmd;
}
static void AddSenderConnection(MethodDefinition method, ILProcessor worker)
{
foreach (ParameterDefinition param in method.Parameters)
{
if (NetworkBehaviourProcessor.IsSenderConnection(param, RemoteCallType.Command))
{
// NetworkConnection is 3nd arg (arg0 is "obj" not "this" because method is static)
// exmaple: static void InvokeCmdCmdSendCommand(NetworkBehaviour obj, NetworkReader reader, NetworkConnection connection)
worker.Append(worker.Create(OpCodes.Ldarg_2));
}
}
}
public static bool ProcessMethodsValidateCommand(MethodDefinition md)
{
if (!md.Name.StartsWith("Cmd"))

View File

@ -9,8 +9,10 @@ public enum RemoteCallType
Command,
ClientRpc,
TargetRpc,
SyncEvent
}
/// <summary>
/// processes SyncVars, Cmds, Rpcs, etc. of NetworkBehaviours
/// </summary>
@ -134,7 +136,7 @@ public static void WriteRecycleWriter(ILProcessor worker)
worker.Append(worker.Create(OpCodes.Call, Weaver.RecycleWriterReference));
}
public static bool WriteArguments(ILProcessor worker, MethodDefinition method, bool skipFirst)
public static bool WriteArguments(ILProcessor worker, MethodDefinition method, RemoteCallType callType)
{
// write each argument
// example result
@ -143,6 +145,9 @@ public static bool WriteArguments(ILProcessor worker, MethodDefinition method, b
writer.WriteNetworkIdentity(someTarget);
*/
bool skipFirst = (callType == RemoteCallType.TargetRpc
&& TargetRpcProcessor.HasNetworkConnectionParameter(method));
// arg of calling function, arg 0 is "this" so start counting at 1
int argNum = 1;
foreach (ParameterDefinition param in method.Parameters)
@ -154,6 +159,12 @@ public static bool WriteArguments(ILProcessor worker, MethodDefinition method, b
argNum += 1;
continue;
}
// skip SenderConnection in Command
if (IsSenderConnection(param, callType))
{
argNum += 1;
continue;
}
MethodReference writeFunc = Writers.GetWriteFunc(param.ParameterType);
if (writeFunc == null)
@ -781,7 +792,7 @@ void GenerateDeSerialization()
netBehaviourSubclass.Methods.Add(serialize);
}
public static bool ReadArguments(MethodDefinition method, ILProcessor worker, bool skipFirst)
public static bool ReadArguments(MethodDefinition method, ILProcessor worker, RemoteCallType callType)
{
// read each argument
// example result
@ -789,6 +800,9 @@ public static bool ReadArguments(MethodDefinition method, ILProcessor worker, bo
CallCmdDoSomething(reader.ReadPackedInt32(), reader.ReadNetworkIdentity());
*/
bool skipFirst = (callType == RemoteCallType.TargetRpc
&& TargetRpcProcessor.HasNetworkConnectionParameter(method));
// arg of calling function, arg 0 is "this" so start counting at 1
int argNum = 1;
foreach (ParameterDefinition param in method.Parameters)
@ -800,6 +814,12 @@ public static bool ReadArguments(MethodDefinition method, ILProcessor worker, bo
argNum += 1;
continue;
}
// skip SenderConnection in Command
if (IsSenderConnection(param, callType))
{
argNum += 1;
continue;
}
MethodReference readFunc = Readers.GetReadFunc(param.ParameterType);
@ -830,6 +850,8 @@ public static void AddInvokeParameters(ICollection<ParameterDefinition> collecti
{
collection.Add(new ParameterDefinition("obj", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkBehaviourType)));
collection.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkReaderType)));
// senderConnection is only used for commands but NetworkBehaviour.CmdDelegate is used for all remote calls
collection.Add(new ParameterDefinition("senderConnection", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkConnectionType)));
}
public static bool ProcessMethodsValidateFunction(MethodReference md)
@ -871,6 +893,7 @@ public static bool ProcessMethodsValidateParameters(MethodReference method, Remo
static bool ValidateParameter(MethodReference method, ParameterDefinition param, RemoteCallType callType, bool firstParam)
{
bool isNetworkConnection = param.ParameterType.FullName == Weaver.NetworkConnectionType.FullName;
bool isSenderConnection = IsSenderConnection(param, callType);
if (param.IsOut)
{
@ -879,15 +902,22 @@ static bool ValidateParameter(MethodReference method, ParameterDefinition param,
}
// TargetRPC is an exception to this rule and can have a NetworkConnection as first parameter
if (isNetworkConnection && !(callType == RemoteCallType.TargetRpc && firstParam))
// if not SenderConnection And not TargetRpc NetworkConnection first param
if (!isSenderConnection && isNetworkConnection && !(callType == RemoteCallType.TargetRpc && firstParam))
{
Weaver.Error($"{method.Name} has invalid parameter {param}. Cannot pass NeworkConnections", method);
if (callType == RemoteCallType.Command)
{
Weaver.Error($"{method.Name} has invalid parameter {param}, Cannot pass NeworkConnections. Instead use 'NetworkConnectionToClient conn = null' to get the sender's connection on the server", method);
}
else
{
Weaver.Error($"{method.Name} has invalid parameter {param}. Cannot pass NeworkConnections", method);
}
return false;
}
// sender connection can be optional
if (param.IsOptional)
if (param.IsOptional && !isSenderConnection)
{
Weaver.Error($"{method.Name} cannot have optional parameters", method);
return false;
@ -896,6 +926,21 @@ static bool ValidateParameter(MethodReference method, ParameterDefinition param,
return true;
}
public static bool IsSenderConnection(ParameterDefinition param, RemoteCallType callType)
{
if (callType != RemoteCallType.Command)
{
return false;
}
TypeReference type = param.ParameterType;
const string ConnectionToClient = "Mirror.NetworkConnectionToClient";
bool isConnectionToClient = type.FullName == ConnectionToClient || type.Resolve().IsDerivedFrom(ConnectionToClient);
return isConnectionToClient;
}
void ProcessMethods()
{
HashSet<string> names = new HashSet<string>();

View File

@ -26,7 +26,7 @@ public static MethodDefinition ProcessRpcInvoke(TypeDefinition td, MethodDefinit
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Castclass, td));
if (!NetworkBehaviourProcessor.ReadArguments(md, worker, false))
if (!NetworkBehaviourProcessor.ReadArguments(md, worker, RemoteCallType.ClientRpc))
return null;
// invoke actual command function
@ -77,7 +77,7 @@ public static MethodDefinition ProcessRpcCall(TypeDefinition td, MethodDefinitio
NetworkBehaviourProcessor.WriteCreateWriter(worker);
// write all the arguments that the user passed to the Rpc call
if (!NetworkBehaviourProcessor.WriteArguments(worker, md, false))
if (!NetworkBehaviourProcessor.WriteArguments(worker, md, RemoteCallType.ClientRpc))
return null;
string rpcName = md.Name;

View File

@ -53,7 +53,7 @@ public static MethodDefinition ProcessEventInvoke(TypeDefinition td, EventDefini
// read the event arguments
MethodReference invoke = Resolvers.ResolveMethod(eventField.FieldType, Weaver.CurrentAssembly, "Invoke");
if (!NetworkBehaviourProcessor.ReadArguments(invoke.Resolve(), worker, false))
if (!NetworkBehaviourProcessor.ReadArguments(invoke.Resolve(), worker, RemoteCallType.SyncEvent))
return null;
// invoke actual event delegate function
@ -87,7 +87,7 @@ public static MethodDefinition ProcessEventCall(TypeDefinition td, EventDefiniti
NetworkBehaviourProcessor.WriteCreateWriter(worker);
// write all the arguments that the user passed to the syncevent
if (!NetworkBehaviourProcessor.WriteArguments(worker, invoke.Resolve(), false))
if (!NetworkBehaviourProcessor.WriteArguments(worker, invoke.Resolve(), RemoteCallType.SyncEvent))
return null;
// invoke interal send and return

View File

@ -34,15 +34,15 @@ public static MethodDefinition ProcessTargetRpcInvoke(TypeDefinition td, MethodD
worker.Append(worker.Create(OpCodes.Castclass, td));
// NetworkConnection parameter is optional
bool hasNetworkConnection = HasNetworkConnectionParameter(md);
if (hasNetworkConnection)
if (HasNetworkConnectionParameter(md))
{
// if call has NetworkConnection write clients connection as first arg
//ClientScene.readyconnection
worker.Append(worker.Create(OpCodes.Call, Weaver.ReadyConnectionReference));
}
// process reader parameters and skip first one if first one is NetworkConnection
if (!NetworkBehaviourProcessor.ReadArguments(md, worker, hasNetworkConnection))
if (!NetworkBehaviourProcessor.ReadArguments(md, worker, RemoteCallType.TargetRpc))
return null;
// invoke actual command function
@ -97,12 +97,9 @@ public static MethodDefinition ProcessTargetRpcCall(TypeDefinition td, MethodDef
NetworkBehaviourProcessor.WriteCreateWriter(worker);
// NetworkConnection parameter is optional
bool hasNetworkConnection = HasNetworkConnectionParameter(md);
// write all the arguments that the user passed to the TargetRpc call
// (skip first one if first one is NetworkConnection)
if (!NetworkBehaviourProcessor.WriteArguments(worker, md, hasNetworkConnection))
if (!NetworkBehaviourProcessor.WriteArguments(worker, md, RemoteCallType.TargetRpc))
return null;
string rpcName = md.Name;

View File

@ -361,7 +361,7 @@ public virtual bool InvokeSyncEvent(int eventHash, NetworkReader reader)
/// </summary>
/// <param name="obj"></param>
/// <param name="reader"></param>
public delegate void CmdDelegate(NetworkBehaviour obj, NetworkReader reader);
public delegate void CmdDelegate(NetworkBehaviour obj, NetworkReader reader, NetworkConnectionToClient senderConnection);
protected class Invoker
{
@ -471,11 +471,12 @@ static bool GetInvokerForHash(int cmdHash, MirrorInvokeType invokeType, out Invo
}
// InvokeCmd/Rpc/SyncEventDelegate can all use the same function here
internal bool InvokeHandlerDelegate(int cmdHash, MirrorInvokeType invokeType, NetworkReader reader)
internal bool InvokeHandlerDelegate(int cmdHash, MirrorInvokeType invokeType, NetworkReader reader, NetworkConnectionToClient senderConnection = null)
{
if (GetInvokerForHash(cmdHash, invokeType, out Invoker invoker) && invoker.invokeClass.IsInstanceOfType(this))
{
invoker.invokeFunction(this, reader);
invoker.invokeFunction(this, reader, senderConnection);
return true;
}
return false;

View File

@ -983,7 +983,7 @@ internal void OnDeserializeAllSafely(NetworkReader reader, bool initialState)
}
// helper function to handle SyncEvent/Command/Rpc
void HandleRemoteCall(int componentIndex, int functionHash, MirrorInvokeType invokeType, NetworkReader reader)
void HandleRemoteCall(int componentIndex, int functionHash, MirrorInvokeType invokeType, NetworkReader reader, NetworkConnectionToClient senderConnection = null)
{
if (gameObject == null)
{
@ -995,7 +995,7 @@ void HandleRemoteCall(int componentIndex, int functionHash, MirrorInvokeType inv
if (0 <= componentIndex && componentIndex < NetworkBehaviours.Length)
{
NetworkBehaviour invokeComponent = NetworkBehaviours[componentIndex];
if (!invokeComponent.InvokeHandlerDelegate(functionHash, invokeType, reader))
if (!invokeComponent.InvokeHandlerDelegate(functionHash, invokeType, reader, senderConnection))
{
logger.LogError("Found no receiver for incoming " + invokeType + " [" + functionHash + "] on " + gameObject + ", the server and client should have the same NetworkBehaviour instances [netId=" + netId + "].");
}
@ -1013,9 +1013,9 @@ internal void HandleSyncEvent(int componentIndex, int eventHash, NetworkReader r
}
// happens on server
internal void HandleCommand(int componentIndex, int cmdHash, NetworkReader reader)
internal void HandleCommand(int componentIndex, int cmdHash, NetworkReader reader, NetworkConnectionToClient senderConnection)
{
HandleRemoteCall(componentIndex, cmdHash, MirrorInvokeType.Command, reader);
HandleRemoteCall(componentIndex, cmdHash, MirrorInvokeType.Command, reader, senderConnection);
}
// happens on server

View File

@ -1008,7 +1008,7 @@ static void OnCommandMessage(NetworkConnection conn, CommandMessage msg)
if (logger.LogEnabled()) logger.Log("OnCommandMessage for netId=" + msg.netId + " conn=" + conn);
using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(msg.payload))
identity.HandleCommand(msg.componentIndex, msg.functionHash, networkReader);
identity.HandleCommand(msg.componentIndex, msg.functionHash, networkReader, conn as NetworkConnectionToClient);
}
internal static void SpawnObject(GameObject obj, NetworkConnection ownerConnection)

View File

@ -27,6 +27,28 @@ public void CmdSendInt(int someInt)
}
}
class SenderConnectionBehaviour : NetworkBehaviour
{
public event Action<int, NetworkConnection> onSendInt;
[Command]
public void CmdSendInt(int someInt, NetworkConnectionToClient conn = null)
{
onSendInt?.Invoke(someInt, conn);
}
}
class SenderConnectionIgnoreAuthorityBehaviour : NetworkBehaviour
{
public event Action<int, NetworkConnection> onSendInt;
[Command(ignoreAuthority = true)]
public void CmdSendInt(int someInt, NetworkConnectionToClient conn = null)
{
onSendInt?.Invoke(someInt, conn);
}
}
public class CommandTest : RemoteTestBase
{
[Test]
@ -101,5 +123,48 @@ public void CommandIsSentWithoutAuthorityWhenIgnoringAuthority()
ProcessMessages();
Assert.That(callCount, Is.EqualTo(1));
}
[Test]
public void SenderConnectionIsSetWhenCommandIsRecieved()
{
SenderConnectionBehaviour hostBehaviour = CreateHostObject<SenderConnectionBehaviour>(true);
const int someInt = 20;
NetworkConnectionToClient connectionToClient = NetworkServer.connections[0];
Debug.Assert(connectionToClient != null, $"connectionToClient was null, This means that the test is broken and will give the wrong results");
int callCount = 0;
hostBehaviour.onSendInt += (incomingInt, incomingConn) =>
{
callCount++;
Assert.That(incomingInt, Is.EqualTo(someInt));
Assert.That(incomingConn, Is.EqualTo(connectionToClient));
};
hostBehaviour.CmdSendInt(someInt);
ProcessMessages();
Assert.That(callCount, Is.EqualTo(1));
}
[Test]
public void SenderConnectionIsSetWhenCommandIsRecievedWithIgnoreAuthority()
{
SenderConnectionIgnoreAuthorityBehaviour hostBehaviour = CreateHostObject<SenderConnectionIgnoreAuthorityBehaviour>(false);
const int someInt = 20;
NetworkConnectionToClient connectionToClient = NetworkServer.connections[0];
Debug.Assert(connectionToClient != null, $"connectionToClient was null, This means that the test is broken and will give the wrong results");
int callCount = 0;
hostBehaviour.onSendInt += (incomingInt, incomingConn) =>
{
callCount++;
Assert.That(incomingInt, Is.EqualTo(someInt));
Assert.That(incomingConn, Is.EqualTo(connectionToClient));
};
hostBehaviour.CmdSendInt(someInt);
ProcessMessages();
Assert.That(callCount, Is.EqualTo(1));
}
}
}

View File

@ -30,7 +30,7 @@ public class NetworkBehaviourSendCommandInternalComponent : NetworkBehaviour
// weaver generates this from [Command]
// but for tests we need to add it manually
public static void CommandGenerated(NetworkBehaviour comp, NetworkReader reader)
public static void CommandGenerated(NetworkBehaviour comp, NetworkReader reader, NetworkConnection senderConnection)
{
++((NetworkBehaviourSendCommandInternalComponent)comp).called;
}
@ -50,7 +50,7 @@ public class NetworkBehaviourSendRPCInternalComponent : NetworkBehaviour
// weaver generates this from [ClientRpc]
// but for tests we need to add it manually
public static void RPCGenerated(NetworkBehaviour comp, NetworkReader reader)
public static void RPCGenerated(NetworkBehaviour comp, NetworkReader reader, NetworkConnection senderConnection)
{
++((NetworkBehaviourSendRPCInternalComponent)comp).called;
}
@ -70,7 +70,7 @@ public class NetworkBehaviourSendTargetRPCInternalComponent : NetworkBehaviour
// weaver generates this from [TargetRpc]
// but for tests we need to add it manually
public static void TargetRPCGenerated(NetworkBehaviour comp, NetworkReader reader)
public static void TargetRPCGenerated(NetworkBehaviour comp, NetworkReader reader, NetworkConnection senderConnection)
{
++((NetworkBehaviourSendTargetRPCInternalComponent)comp).called;
}
@ -90,7 +90,7 @@ public class NetworkBehaviourSendEventInternalComponent : NetworkBehaviour
// weaver generates this from [SyncEvent]
// but for tests we need to add it manually
public static void EventGenerated(NetworkBehaviour comp, NetworkReader reader)
public static void EventGenerated(NetworkBehaviour comp, NetworkReader reader, NetworkConnection senderConnection)
{
++((NetworkBehaviourSendEventInternalComponent)comp).called;
}
@ -105,8 +105,8 @@ public void CallSendEventInternal()
// we need to inherit from networkbehaviour to test protected functions
public class NetworkBehaviourDelegateComponent : NetworkBehaviour
{
public static void Delegate(NetworkBehaviour comp, NetworkReader reader) { }
public static void Delegate2(NetworkBehaviour comp, NetworkReader reader) { }
public static void Delegate(NetworkBehaviour comp, NetworkReader reader, NetworkConnection senderConnection) { }
public static void Delegate2(NetworkBehaviour comp, NetworkReader reader, NetworkConnection senderConnection) { }
}
// we need to inherit from networkbehaviour to test protected functions

View File

@ -1292,7 +1292,9 @@ public void HandleCommand()
{
// add component
CommandTestNetworkBehaviour comp0 = gameObject.AddComponent<CommandTestNetworkBehaviour>();
NetworkConnectionToClient connection = new NetworkConnectionToClient(1);
Assert.That(comp0.called, Is.EqualTo(0));
Assert.That(comp0.senderConnectionInCall, Is.Null);
// register the command delegate, otherwise it's not found
NetworkBehaviour.RegisterCommandDelegate(typeof(CommandTestNetworkBehaviour), nameof(CommandTestNetworkBehaviour.CommandGenerated), CommandTestNetworkBehaviour.CommandGenerated, false);
@ -1304,20 +1306,22 @@ public void HandleCommand()
// call HandleCommand and check if the command was called in the component
int functionHash = NetworkBehaviour.GetMethodHash(typeof(CommandTestNetworkBehaviour), nameof(CommandTestNetworkBehaviour.CommandGenerated));
NetworkReader payload = new NetworkReader(new byte[0]);
identity.HandleCommand(0, functionHash, payload);
identity.HandleCommand(0, functionHash, payload, connection);
Assert.That(comp0.called, Is.EqualTo(1));
Assert.That(comp0.senderConnectionInCall, Is.EqualTo(connection));
// try wrong component index. command shouldn't be called again.
// warning is expected
LogAssert.ignoreFailingMessages = true;
identity.HandleCommand(1, functionHash, payload);
identity.HandleCommand(1, functionHash, payload, connection);
LogAssert.ignoreFailingMessages = false;
Assert.That(comp0.called, Is.EqualTo(1));
// try wrong function hash. command shouldn't be called again.
// warning is expected
LogAssert.ignoreFailingMessages = true;
identity.HandleCommand(0, functionHash + 1, payload);
identity.HandleCommand(0, functionHash + 1, payload, connection);
LogAssert.ignoreFailingMessages = false;
Assert.That(comp0.called, Is.EqualTo(1));

View File

@ -11,11 +11,13 @@ public class CommandTestNetworkBehaviour : NetworkBehaviour
{
// counter to make sure that it's called exactly once
public int called;
public NetworkConnection senderConnectionInCall;
// weaver generates this from [Command]
// but for tests we need to add it manually
public static void CommandGenerated(NetworkBehaviour comp, NetworkReader reader)
public static void CommandGenerated(NetworkBehaviour comp, NetworkReader reader, NetworkConnection senderConnection)
{
++((CommandTestNetworkBehaviour)comp).called;
((CommandTestNetworkBehaviour)comp).senderConnectionInCall = senderConnection;
}
}
@ -25,7 +27,7 @@ public class RpcTestNetworkBehaviour : NetworkBehaviour
public int called;
// weaver generates this from [Rpc]
// but for tests we need to add it manually
public static void RpcGenerated(NetworkBehaviour comp, NetworkReader reader)
public static void RpcGenerated(NetworkBehaviour comp, NetworkReader reader, NetworkConnection senderConnection)
{
++((RpcTestNetworkBehaviour)comp).called;
}
@ -37,7 +39,7 @@ public class SyncEventTestNetworkBehaviour : NetworkBehaviour
public int called;
// weaver generates this from [SyncEvent]
// but for tests we need to add it manually
public static void SyncEventGenerated(NetworkBehaviour comp, NetworkReader reader)
public static void SyncEventGenerated(NetworkBehaviour comp, NetworkReader reader, NetworkConnection senderConnection)
{
++((SyncEventTestNetworkBehaviour)comp).called;
}

View File

@ -66,6 +66,7 @@ protected T CreateHostObject<T>(bool spawnWithAuthority) where T : NetworkBehavi
if (spawnWithAuthority)
{
NetworkServer.Spawn(gameObject, NetworkServer.localConnection);
Debug.Assert(behaviour.connectionToClient != null, $"Behaviour did not have connection to client, This means that the test is broken and will give the wrong results");
}
else
{

View File

@ -94,11 +94,15 @@
<Compile Include="WeaverCommandTests~\CommandCantBeStatic.cs" />
<Compile Include="WeaverCommandTests~\CommandStartsWithCmd.cs" />
<Compile Include="WeaverCommandTests~\CommandThatIgnoresAuthority.cs" />
<Compile Include="WeaverCommandTests~\CommandThatIgnoresAuthorityWithSenderConnection.cs" />
<Compile Include="WeaverCommandTests~\CommandValid.cs" />
<Compile Include="WeaverCommandTests~\CommandWithArguments.cs" />
<Compile Include="WeaverCommandTests~\OverrideAbstractCommand.cs" />
<Compile Include="WeaverCommandTests~\OverrideVirtualCommand.cs" />
<Compile Include="WeaverCommandTests~\VirtualCommand.cs" />
<Compile Include="WeaverCommandTests~\CommandWithSenderConnectionAndOtherArgs.cs" />
<Compile Include="WeaverCommandTests~\ErrorForNetworkConnectionThatIsNotSenderConnection.cs" />
<Compile Include="WeaverCommandTests~\ErrorForOptionalNetworkConnectionThatIsNotSenderConnection.cs" />
<Compile Include="WeaverGeneralTests~\RecursionCount.cs" />
<Compile Include="WeaverGeneralTests~\TestingScriptableObjectArraySerialization.cs" />
<Compile Include="WeaverMessageTests~\MessageMemberGeneric.cs" />

View File

@ -34,6 +34,30 @@ public void CommandWithArguments()
Assert.That(weaverErrors, Is.Empty);
}
[Test]
public void CommandThatIgnoresAuthorityWithSenderConnection()
{
Assert.That(weaverErrors, Is.Empty);
}
[Test]
public void CommandWithSenderConnectionAndOtherArgs()
{
Assert.That(weaverErrors, Is.Empty);
}
[Test]
public void ErrorForOptionalNetworkConnectionThatIsNotSenderConnection()
{
Assert.That(weaverErrors, Contains.Item("CmdFunction has invalid parameter connection, Cannot pass NeworkConnections. Instead use 'NetworkConnectionToClient conn = null' to get the sender's connection on the server (at System.Void WeaverCommandTests.ErrorForOptionalNetworkConnectionThatIsNotSenderConnection.ErrorForOptionalNetworkConnectionThatIsNotSenderConnection::CmdFunction(Mirror.NetworkConnection))"));
}
[Test]
public void ErrorForNetworkConnectionThatIsNotSenderConnection()
{
Assert.That(weaverErrors, Contains.Item("CmdFunction has invalid parameter connection, Cannot pass NeworkConnections. Instead use 'NetworkConnectionToClient conn = null' to get the sender's connection on the server (at System.Void WeaverCommandTests.ErrorForNetworkConnectionThatIsNotSenderConnection.ErrorForNetworkConnectionThatIsNotSenderConnection::CmdFunction(Mirror.NetworkConnection))"));
}
[Test]
public void VirtualCommand()
{

View File

@ -1,4 +1,4 @@
using Mirror;
using Mirror;
namespace WeaverCommandTests.CommandThatIgnoresAuthority
{

View File

@ -0,0 +1,13 @@
using Mirror;
namespace WeaverCommandTests.CommandThatIgnoresAuthorityWithSenderConnection
{
class CommandThatIgnoresAuthorityWithSenderConnection : NetworkBehaviour
{
[Command(ignoreAuthority = true)]
void CmdFunction(NetworkConnectionToClient connection = null)
{
// do something
}
}
}

View File

@ -0,0 +1,13 @@
using Mirror;
namespace WeaverCommandTests.CommandWithSenderConnectionAndOtherArgs
{
class CommandWithSenderConnectionAndOtherArgs : NetworkBehaviour
{
[Command(ignoreAuthority = true)]
void CmdFunction(int someNumber, NetworkIdentity someTarget, NetworkConnectionToClient connection = null)
{
// do something
}
}
}

View File

@ -0,0 +1,14 @@
using Mirror;
namespace WeaverCommandTests.ErrorForNetworkConnectionThatIsNotSenderConnection
{
class ErrorForNetworkConnectionThatIsNotSenderConnection : NetworkBehaviour
{
[Command(ignoreAuthority = true)]
void CmdFunction(NetworkConnection connection)
{
// do something
}
}
}

View File

@ -0,0 +1,13 @@
using Mirror;
namespace WeaverCommandTests.ErrorForOptionalNetworkConnectionThatIsNotSenderConnection
{
class ErrorForOptionalNetworkConnectionThatIsNotSenderConnection : NetworkBehaviour
{
[Command(ignoreAuthority = true)]
void CmdFunction(NetworkConnection connection = null)
{
// do something
}
}
}

View File

@ -212,7 +212,7 @@ public void NetworkBehaviourCmdParamComponent()
[Test]
public void NetworkBehaviourCmdParamNetworkConnection()
{
Assert.That(weaverErrors, Contains.Item("CmdCantHaveParamOptional has invalid parameter monkeyCon. Cannot pass NeworkConnections (at System.Void WeaverNetworkBehaviourTests.NetworkBehaviourCmdParamNetworkConnection.NetworkBehaviourCmdParamNetworkConnection::CmdCantHaveParamOptional(Mirror.NetworkConnection))"));
Assert.That(weaverErrors, Contains.Item("CmdCantHaveParamOptional has invalid parameter monkeyCon, Cannot pass NeworkConnections. Instead use 'NetworkConnectionToClient conn = null' to get the sender's connection on the server (at System.Void WeaverNetworkBehaviourTests.NetworkBehaviourCmdParamNetworkConnection.NetworkBehaviourCmdParamNetworkConnection::CmdCantHaveParamOptional(Mirror.NetworkConnection))"));
}
[Test]

View File

@ -495,7 +495,7 @@ PlayerSettings:
webGLLinkerTarget: 1
webGLThreadsSupport: 0
scriptingDefineSymbols:
1: MIRROR;MIRROR_1726_OR_NEWER;MIRROR_3_0_OR_NEWER;MIRROR_3_12_OR_NEWER;MIRROR_4_0_OR_NEWER;MIRROR_5_0_OR_NEWER;MIRROR_6_0_OR_NEWER;MIRROR_7_0_OR_NEWER;MIRROR_8_0_OR_NEWER;MIRROR_9_0_OR_NEWER;MIRROR_10_0_OR_NEWER;MIRROR_11_0_OR_NEWER;MIRROR_12_0_OR_NEWER;MIRROR_13_0_OR_NEWER
1: MIRROR;MIRROR_1726_OR_NEWER;MIRROR_3_0_OR_NEWER;MIRROR_3_12_OR_NEWER;MIRROR_4_0_OR_NEWER;MIRROR_5_0_OR_NEWER;MIRROR_6_0_OR_NEWER;MIRROR_7_0_OR_NEWER;MIRROR_8_0_OR_NEWER;MIRROR_9_0_OR_NEWER;MIRROR_10_0_OR_NEWER;MIRROR_11_0_OR_NEWER;MIRROR_12_0_OR_NEWER;MIRROR_13_0_OR_NEWER;MIRROR_14_0_OR_NEWER
platformArchitecture: {}
scriptingBackend: {}
il2cppCompilerConfiguration: {}