mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 11:00:32 +00:00
Remove Host Mode
This commit is contained in:
parent
f82d7c7abc
commit
139950ea4e
@ -201,38 +201,6 @@ public static MethodDefinition GenerateSyncVarSetter(TypeDefinition td, FieldDef
|
|||||||
worker.Append(worker.Create(OpCodes.Call, gm));
|
worker.Append(worker.Create(OpCodes.Call, gm));
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodDefinition hookMethod = GetHookMethod(td, fd);
|
|
||||||
|
|
||||||
if (hookMethod != null)
|
|
||||||
{
|
|
||||||
//if (NetworkServer.localClientActive && !getSyncVarHookGuard(dirtyBit))
|
|
||||||
Instruction label = worker.Create(OpCodes.Nop);
|
|
||||||
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.NetworkServerGetLocalClientActive));
|
|
||||||
worker.Append(worker.Create(OpCodes.Brfalse, label));
|
|
||||||
worker.Append(worker.Create(OpCodes.Ldarg_0));
|
|
||||||
worker.Append(worker.Create(OpCodes.Ldc_I8, dirtyBit));
|
|
||||||
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.getSyncVarHookGuard));
|
|
||||||
worker.Append(worker.Create(OpCodes.Brtrue, label));
|
|
||||||
|
|
||||||
// setSyncVarHookGuard(dirtyBit, true);
|
|
||||||
worker.Append(worker.Create(OpCodes.Ldarg_0));
|
|
||||||
worker.Append(worker.Create(OpCodes.Ldc_I8, dirtyBit));
|
|
||||||
worker.Append(worker.Create(OpCodes.Ldc_I4_1));
|
|
||||||
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.setSyncVarHookGuard));
|
|
||||||
|
|
||||||
// call hook (oldValue, newValue)
|
|
||||||
// Generates: OnValueChanged(oldValue, value);
|
|
||||||
WriteCallHookMethodUsingArgument(worker, hookMethod, oldValue);
|
|
||||||
|
|
||||||
// setSyncVarHookGuard(dirtyBit, false);
|
|
||||||
worker.Append(worker.Create(OpCodes.Ldarg_0));
|
|
||||||
worker.Append(worker.Create(OpCodes.Ldc_I8, dirtyBit));
|
|
||||||
worker.Append(worker.Create(OpCodes.Ldc_I4_0));
|
|
||||||
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.setSyncVarHookGuard));
|
|
||||||
|
|
||||||
worker.Append(label);
|
|
||||||
}
|
|
||||||
|
|
||||||
worker.Append(endOfMethod);
|
worker.Append(endOfMethod);
|
||||||
|
|
||||||
worker.Append(worker.Create(OpCodes.Ret));
|
worker.Append(worker.Create(OpCodes.Ret));
|
||||||
|
@ -16,7 +16,6 @@ public static class WeaverTypes
|
|||||||
public static MethodReference CmdDelegateConstructor;
|
public static MethodReference CmdDelegateConstructor;
|
||||||
|
|
||||||
public static MethodReference NetworkServerGetActive;
|
public static MethodReference NetworkServerGetActive;
|
||||||
public static MethodReference NetworkServerGetLocalClientActive;
|
|
||||||
public static MethodReference NetworkClientGetActive;
|
public static MethodReference NetworkClientGetActive;
|
||||||
|
|
||||||
// custom attribute types
|
// custom attribute types
|
||||||
@ -37,8 +36,6 @@ public static class WeaverTypes
|
|||||||
public static MethodReference syncVarEqualReference;
|
public static MethodReference syncVarEqualReference;
|
||||||
public static MethodReference syncVarNetworkIdentityEqualReference;
|
public static MethodReference syncVarNetworkIdentityEqualReference;
|
||||||
public static MethodReference setSyncVarReference;
|
public static MethodReference setSyncVarReference;
|
||||||
public static MethodReference setSyncVarHookGuard;
|
|
||||||
public static MethodReference getSyncVarHookGuard;
|
|
||||||
public static MethodReference setSyncVarNetworkIdentityReference;
|
public static MethodReference setSyncVarNetworkIdentityReference;
|
||||||
public static MethodReference getSyncVarNetworkIdentityReference;
|
public static MethodReference getSyncVarNetworkIdentityReference;
|
||||||
public static MethodReference registerCommandDelegateReference;
|
public static MethodReference registerCommandDelegateReference;
|
||||||
@ -76,7 +73,6 @@ public static void SetupTargetTypes(AssemblyDefinition currentAssembly)
|
|||||||
|
|
||||||
TypeReference NetworkServerType = Import(typeof(NetworkServer));
|
TypeReference NetworkServerType = Import(typeof(NetworkServer));
|
||||||
NetworkServerGetActive = Resolvers.ResolveMethod(NetworkServerType, currentAssembly, "get_active");
|
NetworkServerGetActive = Resolvers.ResolveMethod(NetworkServerType, currentAssembly, "get_active");
|
||||||
NetworkServerGetLocalClientActive = Resolvers.ResolveMethod(NetworkServerType, currentAssembly, "get_localClientActive");
|
|
||||||
TypeReference NetworkClientType = Import(typeof(NetworkClient));
|
TypeReference NetworkClientType = Import(typeof(NetworkClient));
|
||||||
NetworkClientGetActive = Resolvers.ResolveMethod(NetworkClientType, currentAssembly, "get_active");
|
NetworkClientGetActive = Resolvers.ResolveMethod(NetworkClientType, currentAssembly, "get_active");
|
||||||
|
|
||||||
@ -103,8 +99,6 @@ public static void SetupTargetTypes(AssemblyDefinition currentAssembly)
|
|||||||
syncVarEqualReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "SyncVarEqual");
|
syncVarEqualReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "SyncVarEqual");
|
||||||
syncVarNetworkIdentityEqualReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "SyncVarNetworkIdentityEqual");
|
syncVarNetworkIdentityEqualReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "SyncVarNetworkIdentityEqual");
|
||||||
setSyncVarReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "SetSyncVar");
|
setSyncVarReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "SetSyncVar");
|
||||||
setSyncVarHookGuard = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "setSyncVarHookGuard");
|
|
||||||
getSyncVarHookGuard = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "getSyncVarHookGuard");
|
|
||||||
|
|
||||||
setSyncVarNetworkIdentityReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "SetSyncVarNetworkIdentity");
|
setSyncVarNetworkIdentityReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "SetSyncVarNetworkIdentity");
|
||||||
getSyncVarNetworkIdentityReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "GetSyncVarNetworkIdentity");
|
getSyncVarNetworkIdentityReference = Resolvers.ResolveMethod(NetworkBehaviourType, currentAssembly, "GetSyncVarNetworkIdentity");
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Guid = System.Guid;
|
using Guid = System.Guid;
|
||||||
@ -152,13 +151,6 @@ public static bool AddPlayer(NetworkConnection readyConn)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated 5/2/2020
|
|
||||||
/// <summary>
|
|
||||||
/// Obsolete: Removed as a security risk. Use <see cref="NetworkServer.RemovePlayerForConnection(NetworkConnection, bool)">NetworkServer.RemovePlayerForConnection</see> instead.
|
|
||||||
/// </summary>
|
|
||||||
[EditorBrowsable(EditorBrowsableState.Never), Obsolete("Removed as a security risk. Use NetworkServer.RemovePlayerForConnection(NetworkConnection conn, bool keepAuthority = false) instead", true)]
|
|
||||||
public static bool RemovePlayer() { return false; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Signal that the client connection is ready to enter the game.
|
/// Signal that the client connection is ready to enter the game.
|
||||||
/// <para>This could be for example when a client enters an ongoing game and has finished loading the current scene. The server should respond to the SYSTEM_READY event with an appropriate handler which instantiates the players object for example.</para>
|
/// <para>This could be for example when a client enters an ongoing game and has finished loading the current scene. The server should respond to the SYSTEM_READY event with an appropriate handler which instantiates the players object for example.</para>
|
||||||
@ -974,38 +966,6 @@ static void DestroyObject(uint netId)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void OnHostClientObjectDestroy(ObjectDestroyMessage msg)
|
|
||||||
{
|
|
||||||
// Debug.Log("ClientScene.OnLocalObjectObjDestroy netId:" + msg.netId);
|
|
||||||
|
|
||||||
NetworkIdentity.spawned.Remove(msg.netId);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void OnHostClientObjectHide(ObjectHideMessage msg)
|
|
||||||
{
|
|
||||||
// Debug.Log("ClientScene::OnLocalObjectObjHide netId:" + msg.netId);
|
|
||||||
|
|
||||||
if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity localObject) && localObject != null)
|
|
||||||
{
|
|
||||||
localObject.OnSetHostVisibility(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void OnHostClientSpawn(SpawnMessage msg)
|
|
||||||
{
|
|
||||||
if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity localObject) && localObject != null)
|
|
||||||
{
|
|
||||||
if (msg.isLocalPlayer)
|
|
||||||
InternalAddPlayer(localObject);
|
|
||||||
|
|
||||||
localObject.hasAuthority = msg.isOwner;
|
|
||||||
localObject.NotifyAuthority();
|
|
||||||
localObject.OnStartClient();
|
|
||||||
localObject.OnSetHostVisibility(true);
|
|
||||||
CheckForLocalPlayer(localObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void OnUpdateVarsMessage(UpdateVarsMessage msg)
|
internal static void OnUpdateVarsMessage(UpdateVarsMessage msg)
|
||||||
{
|
{
|
||||||
// Debug.Log("ClientScene.OnUpdateVarsMessage " + msg.netId);
|
// Debug.Log("ClientScene.OnUpdateVarsMessage " + msg.netId);
|
||||||
|
@ -1,137 +0,0 @@
|
|||||||
using System;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Mirror
|
|
||||||
{
|
|
||||||
// a server's connection TO a LocalClient.
|
|
||||||
// sending messages on this connection causes the client's handler function to be invoked directly
|
|
||||||
class ULocalConnectionToClient : NetworkConnectionToClient
|
|
||||||
{
|
|
||||||
internal ULocalConnectionToServer connectionToServer;
|
|
||||||
|
|
||||||
public ULocalConnectionToClient() : base(LocalConnectionId) { }
|
|
||||||
|
|
||||||
public override string address => "localhost";
|
|
||||||
|
|
||||||
internal override bool Send(ArraySegment<byte> segment, int channelId = Channels.DefaultReliable)
|
|
||||||
{
|
|
||||||
connectionToServer.buffer.Write(segment);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// override for host client: always return true.
|
|
||||||
internal override bool IsClientAlive() => true;
|
|
||||||
|
|
||||||
internal void DisconnectInternal()
|
|
||||||
{
|
|
||||||
// set not ready and handle clientscene disconnect in any case
|
|
||||||
// (might be client or host mode here)
|
|
||||||
isReady = false;
|
|
||||||
RemoveObservers();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disconnects this connection.
|
|
||||||
/// </summary>
|
|
||||||
public override void Disconnect()
|
|
||||||
{
|
|
||||||
DisconnectInternal();
|
|
||||||
connectionToServer.DisconnectInternal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class LocalConnectionBuffer
|
|
||||||
{
|
|
||||||
readonly NetworkWriter writer = new NetworkWriter();
|
|
||||||
readonly NetworkReader reader = new NetworkReader(default(ArraySegment<byte>));
|
|
||||||
// The buffer is atleast 1500 bytes long. So need to keep track of
|
|
||||||
// packet count to know how many ArraySegments are in the buffer
|
|
||||||
int packetCount;
|
|
||||||
|
|
||||||
public void Write(ArraySegment<byte> segment)
|
|
||||||
{
|
|
||||||
writer.WriteBytesAndSizeSegment(segment);
|
|
||||||
packetCount++;
|
|
||||||
|
|
||||||
// update buffer incase writer's length has changed
|
|
||||||
reader.buffer = writer.ToArraySegment();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool HasPackets()
|
|
||||||
{
|
|
||||||
return packetCount > 0;
|
|
||||||
}
|
|
||||||
public ArraySegment<byte> GetNextPacket()
|
|
||||||
{
|
|
||||||
ArraySegment<byte> packet = reader.ReadBytesAndSizeSegment();
|
|
||||||
packetCount--;
|
|
||||||
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ResetBuffer()
|
|
||||||
{
|
|
||||||
writer.Reset();
|
|
||||||
reader.Position = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// a localClient's connection TO a server.
|
|
||||||
// send messages on this connection causes the server's handler function to be invoked directly.
|
|
||||||
internal class ULocalConnectionToServer : NetworkConnectionToServer
|
|
||||||
{
|
|
||||||
internal ULocalConnectionToClient connectionToClient;
|
|
||||||
internal readonly LocalConnectionBuffer buffer = new LocalConnectionBuffer();
|
|
||||||
|
|
||||||
public override string address => "localhost";
|
|
||||||
|
|
||||||
internal override bool Send(ArraySegment<byte> segment, int channelId = Channels.DefaultReliable)
|
|
||||||
{
|
|
||||||
if (segment.Count == 0)
|
|
||||||
{
|
|
||||||
Debug.LogError("LocalConnection.SendBytes cannot send zero bytes");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle the server's message directly
|
|
||||||
connectionToClient.TransportReceive(segment, channelId);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void Update()
|
|
||||||
{
|
|
||||||
// process internal messages so they are applied at the correct time
|
|
||||||
while (buffer.HasPackets())
|
|
||||||
{
|
|
||||||
ArraySegment<byte> packet = buffer.GetNextPacket();
|
|
||||||
|
|
||||||
// Treat host player messages exactly like connected client
|
|
||||||
// to avoid deceptive / misleading behavior differences
|
|
||||||
TransportReceive(packet, Channels.DefaultReliable);
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.ResetBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disconnects this connection.
|
|
||||||
/// </summary>
|
|
||||||
internal void DisconnectInternal()
|
|
||||||
{
|
|
||||||
// set not ready and handle clientscene disconnect in any case
|
|
||||||
// (might be client or host mode here)
|
|
||||||
isReady = false;
|
|
||||||
ClientScene.HandleClientDisconnect(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disconnects this connection.
|
|
||||||
/// </summary>
|
|
||||||
public override void Disconnect()
|
|
||||||
{
|
|
||||||
connectionToClient.DisconnectInternal();
|
|
||||||
DisconnectInternal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: a88758df7db2043d6a9d926e0b6d4191
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -91,20 +91,6 @@ public abstract class NetworkBehaviour : MonoBehaviour
|
|||||||
public NetworkConnection connectionToClient => netIdentity.connectionToClient;
|
public NetworkConnection connectionToClient => netIdentity.connectionToClient;
|
||||||
|
|
||||||
protected ulong syncVarDirtyBits { get; private set; }
|
protected ulong syncVarDirtyBits { get; private set; }
|
||||||
ulong syncVarHookGuard;
|
|
||||||
|
|
||||||
protected bool getSyncVarHookGuard(ulong dirtyBit)
|
|
||||||
{
|
|
||||||
return (syncVarHookGuard & dirtyBit) != 0UL;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setSyncVarHookGuard(ulong dirtyBit, bool value)
|
|
||||||
{
|
|
||||||
if (value)
|
|
||||||
syncVarHookGuard |= dirtyBit;
|
|
||||||
else
|
|
||||||
syncVarHookGuard &= ~dirtyBit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// objects that can synchronize themselves, such as synclists
|
/// objects that can synchronize themselves, such as synclists
|
||||||
@ -310,9 +296,6 @@ protected bool SyncVarNetworkIdentityEqual(NetworkIdentity newIdentity, uint net
|
|||||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
protected void SetSyncVarNetworkIdentity(NetworkIdentity newIdentity, ref NetworkIdentity identityField, ulong dirtyBit, ref uint netIdField)
|
protected void SetSyncVarNetworkIdentity(NetworkIdentity newIdentity, ref NetworkIdentity identityField, ulong dirtyBit, ref uint netIdField)
|
||||||
{
|
{
|
||||||
if (getSyncVarHookGuard(dirtyBit))
|
|
||||||
return;
|
|
||||||
|
|
||||||
uint newNetId = 0;
|
uint newNetId = 0;
|
||||||
if (newIdentity != null)
|
if (newIdentity != null)
|
||||||
{
|
{
|
||||||
|
@ -49,11 +49,6 @@ public static class NetworkClient
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool isConnected => connectState == ConnectState.Connected;
|
public static bool isConnected => connectState == ConnectState.Connected;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// NetworkClient can connect to local server in host mode too
|
|
||||||
/// </summary>
|
|
||||||
public static bool isLocalClient => connection is ULocalConnectionToServer;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Connect client to a NetworkServer instance.
|
/// Connect client to a NetworkServer instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -62,7 +57,7 @@ public static void Connect(string address)
|
|||||||
{
|
{
|
||||||
// Debug.Log("Client Connect: " + address);
|
// Debug.Log("Client Connect: " + address);
|
||||||
|
|
||||||
RegisterSystemHandlers(false);
|
RegisterSystemHandlers();
|
||||||
Transport.activeTransport.enabled = true;
|
Transport.activeTransport.enabled = true;
|
||||||
InitializeTransportHandlers();
|
InitializeTransportHandlers();
|
||||||
|
|
||||||
@ -82,7 +77,7 @@ public static void Connect(Uri uri)
|
|||||||
{
|
{
|
||||||
// Debug.Log("Client Connect: " + uri);
|
// Debug.Log("Client Connect: " + uri);
|
||||||
|
|
||||||
RegisterSystemHandlers(false);
|
RegisterSystemHandlers();
|
||||||
Transport.activeTransport.enabled = true;
|
Transport.activeTransport.enabled = true;
|
||||||
InitializeTransportHandlers();
|
InitializeTransportHandlers();
|
||||||
|
|
||||||
@ -94,53 +89,6 @@ public static void Connect(Uri uri)
|
|||||||
connection.SetHandlers(handlers);
|
connection.SetHandlers(handlers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ConnectHost()
|
|
||||||
{
|
|
||||||
Debug.Log("Client Connect Host to Server");
|
|
||||||
|
|
||||||
RegisterSystemHandlers(true);
|
|
||||||
|
|
||||||
connectState = ConnectState.Connected;
|
|
||||||
|
|
||||||
// create local connection objects and connect them
|
|
||||||
ULocalConnectionToServer connectionToServer = new ULocalConnectionToServer();
|
|
||||||
ULocalConnectionToClient connectionToClient = new ULocalConnectionToClient();
|
|
||||||
connectionToServer.connectionToClient = connectionToClient;
|
|
||||||
connectionToClient.connectionToServer = connectionToServer;
|
|
||||||
|
|
||||||
connection = connectionToServer;
|
|
||||||
connection.SetHandlers(handlers);
|
|
||||||
|
|
||||||
// create server connection to local client
|
|
||||||
NetworkServer.SetLocalConnection(connectionToClient);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// connect host mode
|
|
||||||
/// </summary>
|
|
||||||
public static void ConnectLocalServer()
|
|
||||||
{
|
|
||||||
NetworkServer.OnConnected(NetworkServer.localConnection);
|
|
||||||
NetworkServer.localConnection.Send(new ConnectMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// disconnect host mode. this is needed to call DisconnectMessage for
|
|
||||||
/// the host client too.
|
|
||||||
/// </summary>
|
|
||||||
public static void DisconnectLocalServer()
|
|
||||||
{
|
|
||||||
// only if host connection is running
|
|
||||||
if (NetworkServer.localConnection != null)
|
|
||||||
{
|
|
||||||
// TODO ConnectLocalServer manually sends a ConnectMessage to the
|
|
||||||
// local connection. should we send a DisconnectMessage here too?
|
|
||||||
// (if we do then we get an Unknown Message ID log)
|
|
||||||
//NetworkServer.localConnection.Send(new DisconnectMessage());
|
|
||||||
NetworkServer.OnDisconnected(NetworkServer.localConnection.connectionId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void InitializeTransportHandlers()
|
static void InitializeTransportHandlers()
|
||||||
{
|
{
|
||||||
Transport.activeTransport.OnClientConnected.AddListener(OnConnected);
|
Transport.activeTransport.OnClientConnected.AddListener(OnConnected);
|
||||||
@ -197,24 +145,12 @@ public static void Disconnect()
|
|||||||
connectState = ConnectState.Disconnected;
|
connectState = ConnectState.Disconnected;
|
||||||
ClientScene.HandleClientDisconnect(connection);
|
ClientScene.HandleClientDisconnect(connection);
|
||||||
|
|
||||||
// local or remote connection?
|
if (connection != null)
|
||||||
if (isLocalClient)
|
|
||||||
{
|
{
|
||||||
if (isConnected)
|
connection.Disconnect();
|
||||||
{
|
connection.Dispose();
|
||||||
NetworkServer.localConnection.Send(new DisconnectMessage());
|
connection = null;
|
||||||
}
|
RemoveTransportHandlers();
|
||||||
NetworkServer.RemoveLocalConnection();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (connection != null)
|
|
||||||
{
|
|
||||||
connection.Disconnect();
|
|
||||||
connection.Dispose();
|
|
||||||
connection = null;
|
|
||||||
RemoveTransportHandlers();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,49 +189,22 @@ public static bool Send<T>(T message, int channelId = Channels.DefaultReliable)
|
|||||||
|
|
||||||
public static void Update()
|
public static void Update()
|
||||||
{
|
{
|
||||||
// local connection?
|
// only update things while connected
|
||||||
if (connection is ULocalConnectionToServer localConnection)
|
if (active && connectState == ConnectState.Connected)
|
||||||
{
|
{
|
||||||
localConnection.Update();
|
NetworkTime.UpdateClient();
|
||||||
}
|
|
||||||
// remote connection?
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// only update things while connected
|
|
||||||
if (active && connectState == ConnectState.Connected)
|
|
||||||
{
|
|
||||||
NetworkTime.UpdateClient();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void RegisterSystemHandlers(bool hostMode)
|
internal static void RegisterSystemHandlers()
|
||||||
{
|
{
|
||||||
// host mode client / regular client react to some messages differently.
|
RegisterHandler<ObjectDestroyMessage>(ClientScene.OnObjectDestroy);
|
||||||
// but we still need to add handlers for all of them to avoid
|
RegisterHandler<ObjectHideMessage>(ClientScene.OnObjectHide);
|
||||||
// 'message id not found' errors.
|
RegisterHandler<NetworkPongMessage>(NetworkTime.OnClientPong, false);
|
||||||
if (hostMode)
|
RegisterHandler<SpawnMessage>(ClientScene.OnSpawn);
|
||||||
{
|
RegisterHandler<ObjectSpawnStartedMessage>(ClientScene.OnObjectSpawnStarted);
|
||||||
RegisterHandler<ObjectDestroyMessage>(ClientScene.OnHostClientObjectDestroy);
|
RegisterHandler<ObjectSpawnFinishedMessage>(ClientScene.OnObjectSpawnFinished);
|
||||||
RegisterHandler<ObjectHideMessage>(ClientScene.OnHostClientObjectHide);
|
RegisterHandler<UpdateVarsMessage>(ClientScene.OnUpdateVarsMessage);
|
||||||
RegisterHandler<NetworkPongMessage>((conn, msg) => { }, false);
|
|
||||||
RegisterHandler<SpawnMessage>(ClientScene.OnHostClientSpawn);
|
|
||||||
// host mode doesn't need spawning
|
|
||||||
RegisterHandler<ObjectSpawnStartedMessage>((conn, msg) => { });
|
|
||||||
// host mode doesn't need spawning
|
|
||||||
RegisterHandler<ObjectSpawnFinishedMessage>((conn, msg) => { });
|
|
||||||
RegisterHandler<UpdateVarsMessage>((conn, msg) => { });
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RegisterHandler<ObjectDestroyMessage>(ClientScene.OnObjectDestroy);
|
|
||||||
RegisterHandler<ObjectHideMessage>(ClientScene.OnObjectHide);
|
|
||||||
RegisterHandler<NetworkPongMessage>(NetworkTime.OnClientPong, false);
|
|
||||||
RegisterHandler<SpawnMessage>(ClientScene.OnSpawn);
|
|
||||||
RegisterHandler<ObjectSpawnStartedMessage>(ClientScene.OnObjectSpawnStarted);
|
|
||||||
RegisterHandler<ObjectSpawnFinishedMessage>(ClientScene.OnObjectSpawnFinished);
|
|
||||||
RegisterHandler<UpdateVarsMessage>(ClientScene.OnUpdateVarsMessage);
|
|
||||||
}
|
|
||||||
RegisterHandler<RpcMessage>(ClientScene.OnRPCMessage);
|
RegisterHandler<RpcMessage>(ClientScene.OnRPCMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,8 +16,6 @@ namespace Mirror
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
public abstract class NetworkConnection : IDisposable
|
public abstract class NetworkConnection : IDisposable
|
||||||
{
|
{
|
||||||
public const int LocalConnectionId = 0;
|
|
||||||
|
|
||||||
// internal so it can be tested
|
// internal so it can be tested
|
||||||
internal readonly HashSet<NetworkIdentity> visList = new HashSet<NetworkIdentity>();
|
internal readonly HashSet<NetworkIdentity> visList = new HashSet<NetworkIdentity>();
|
||||||
|
|
||||||
|
@ -839,21 +839,6 @@ internal void OnStopAuthority()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnSetHostVisibility(bool visible)
|
|
||||||
{
|
|
||||||
if (visibility != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
visibility.OnSetHostVisibility(visible);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Debug.LogError("Exception in OnSetLocalVisibility:" + e.Message + " " + e.StackTrace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// check if observer can be seen by connection.
|
/// check if observer can be seen by connection.
|
||||||
/// <list type="bullet">
|
/// <list type="bullet">
|
||||||
@ -1252,12 +1237,6 @@ internal void AddAllReadyServerConnectionsToObservers()
|
|||||||
if (conn.isReady)
|
if (conn.isReady)
|
||||||
AddObserver(conn);
|
AddObserver(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add local host connection (if any)
|
|
||||||
if (NetworkServer.localConnection != null && NetworkServer.localConnection.isReady)
|
|
||||||
{
|
|
||||||
AddObserver(NetworkServer.localConnection);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static readonly HashSet<NetworkConnection> newObservers = new HashSet<NetworkConnection>();
|
static readonly HashSet<NetworkConnection> newObservers = new HashSet<NetworkConnection>();
|
||||||
@ -1337,35 +1316,6 @@ public void RebuildObservers(bool initialize)
|
|||||||
observers.Add(conn.connectionId, conn);
|
observers.Add(conn.connectionId, conn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// special case for host mode: we use SetHostVisibility to hide
|
|
||||||
// NetworkIdentities that aren't in observer range from host.
|
|
||||||
// this is what games like Dota/Counter-Strike do too, where a host
|
|
||||||
// does NOT see all players by default. they are in memory, but
|
|
||||||
// hidden to the host player.
|
|
||||||
//
|
|
||||||
// this code is from UNET, it's a bit strange but it works:
|
|
||||||
// * it hides newly connected identities in host mode
|
|
||||||
// => that part was the intended behaviour
|
|
||||||
// * it hides ALL NetworkIdentities in host mode when the host
|
|
||||||
// connects but hasn't selected a character yet
|
|
||||||
// => this only works because we have no .localConnection != null
|
|
||||||
// check. at this stage, localConnection is null because
|
|
||||||
// StartHost starts the server first, then calls this code,
|
|
||||||
// then starts the client and sets .localConnection. so we can
|
|
||||||
// NOT add a null check without breaking host visibility here.
|
|
||||||
// * it hides ALL NetworkIdentities in server-only mode because
|
|
||||||
// observers never contain the 'null' .localConnection
|
|
||||||
// => that was not intended, but let's keep it as it is so we
|
|
||||||
// don't break anything in host mode. it's way easier than
|
|
||||||
// iterating all identities in a special function in StartHost.
|
|
||||||
if (initialize)
|
|
||||||
{
|
|
||||||
if (!newObservers.Contains(NetworkServer.localConnection))
|
|
||||||
{
|
|
||||||
OnSetHostVisibility(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -17,7 +17,7 @@ public enum PlayerSpawnMethod { Random, RoundRobin }
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enumeration of methods of current Network Manager state at runtime.
|
/// Enumeration of methods of current Network Manager state at runtime.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum NetworkManagerMode { Offline, ServerOnly, ClientOnly, Host }
|
public enum NetworkManagerMode { Offline, ServerOnly, ClientOnly }
|
||||||
|
|
||||||
[DisallowMultipleComponent]
|
[DisallowMultipleComponent]
|
||||||
[AddComponentMenu("Network/NetworkManager")]
|
[AddComponentMenu("Network/NetworkManager")]
|
||||||
@ -442,150 +442,6 @@ public void StartClient(Uri uri)
|
|||||||
OnStartClient();
|
OnStartClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This starts a network "host" - a server and client in the same application.
|
|
||||||
/// <para>The client returned from StartHost() is a special "local" client that communicates to the in-process server using a message queue instead of the real network. But in almost all other cases, it can be treated as a normal client.</para>
|
|
||||||
/// </summary>
|
|
||||||
public void StartHost()
|
|
||||||
{
|
|
||||||
mode = NetworkManagerMode.Host;
|
|
||||||
|
|
||||||
// StartHost is inherently ASYNCHRONOUS (=doesn't finish immediately)
|
|
||||||
//
|
|
||||||
// Here is what it does:
|
|
||||||
// Listen
|
|
||||||
// ConnectHost
|
|
||||||
// if onlineScene:
|
|
||||||
// LoadSceneAsync
|
|
||||||
// ...
|
|
||||||
// FinishLoadSceneHost
|
|
||||||
// FinishStartHost
|
|
||||||
// SpawnObjects
|
|
||||||
// StartHostClient <= not guaranteed to happen after SpawnObjects if onlineScene is set!
|
|
||||||
// ClientAuth
|
|
||||||
// success: server sends changescene msg to client
|
|
||||||
// else:
|
|
||||||
// FinishStartHost
|
|
||||||
//
|
|
||||||
// there is NO WAY to make it synchronous because both LoadSceneAsync
|
|
||||||
// and LoadScene do not finish loading immediately. as long as we
|
|
||||||
// have the onlineScene feature, it will be asynchronous!
|
|
||||||
|
|
||||||
// setup server first
|
|
||||||
SetupServer();
|
|
||||||
|
|
||||||
// call OnStartHost AFTER SetupServer. this way we can use
|
|
||||||
// NetworkServer.Spawn etc. in there too. just like OnStartServer
|
|
||||||
// is called after the server is actually properly started.
|
|
||||||
OnStartHost();
|
|
||||||
|
|
||||||
// scene change needed? then change scene and spawn afterwards.
|
|
||||||
// => BEFORE host client connects. if client auth succeeds then the
|
|
||||||
// server tells it to load 'onlineScene'. we can't do that if
|
|
||||||
// server is still in 'offlineScene'. so load on server first.
|
|
||||||
if (IsServerOnlineSceneChangeNeeded())
|
|
||||||
{
|
|
||||||
// call FinishStartHost after changing scene.
|
|
||||||
finishStartHostPending = true;
|
|
||||||
ServerChangeScene(onlineScene);
|
|
||||||
}
|
|
||||||
// otherwise call FinishStartHost directly
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FinishStartHost();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This may be set true in StartHost and is evaluated in FinishStartHost
|
|
||||||
bool finishStartHostPending;
|
|
||||||
|
|
||||||
// FinishStartHost is guaranteed to be called after the host server was
|
|
||||||
// fully started and all the asynchronous StartHost magic is finished
|
|
||||||
// (= scene loading), or immediately if there was no asynchronous magic.
|
|
||||||
//
|
|
||||||
// note: we don't really need FinishStartClient/FinishStartServer. the
|
|
||||||
// host version is enough.
|
|
||||||
void FinishStartHost()
|
|
||||||
{
|
|
||||||
// ConnectHost needs to be called BEFORE SpawnObjects:
|
|
||||||
// https://github.com/vis2k/Mirror/pull/1249/
|
|
||||||
// -> this sets NetworkServer.localConnection.
|
|
||||||
// -> localConnection needs to be set before SpawnObjects because:
|
|
||||||
// -> SpawnObjects calls OnStartServer in all NetworkBehaviours
|
|
||||||
// -> OnStartServer might spawn an object and set [SyncVar(hook="OnColorChanged")] object.color = green;
|
|
||||||
// -> this calls SyncVar.set (generated by Weaver), which has
|
|
||||||
// a custom case for host mode (because host mode doesn't
|
|
||||||
// get OnDeserialize calls, where SyncVar hooks are usually
|
|
||||||
// called):
|
|
||||||
//
|
|
||||||
// if (!SyncVarEqual(value, ref color))
|
|
||||||
// {
|
|
||||||
// if (NetworkServer.localClientActive && !getSyncVarHookGuard(1uL))
|
|
||||||
// {
|
|
||||||
// setSyncVarHookGuard(1uL, value: true);
|
|
||||||
// OnColorChangedHook(value);
|
|
||||||
// setSyncVarHookGuard(1uL, value: false);
|
|
||||||
// }
|
|
||||||
// SetSyncVar(value, ref color, 1uL);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// -> localClientActive needs to be true, otherwise the hook
|
|
||||||
// isn't called in host mode!
|
|
||||||
//
|
|
||||||
// TODO call this after spawnobjects and worry about the syncvar hook fix later?
|
|
||||||
NetworkClient.ConnectHost();
|
|
||||||
|
|
||||||
// server scene was loaded. now spawn all the objects
|
|
||||||
NetworkServer.SpawnObjects();
|
|
||||||
|
|
||||||
// connect client and call OnStartClient AFTER server scene was
|
|
||||||
// loaded and all objects were spawned.
|
|
||||||
// DO NOT do this earlier. it would cause race conditions where a
|
|
||||||
// client will do things before the server is even fully started.
|
|
||||||
Debug.Log("StartHostClient called");
|
|
||||||
StartHostClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
void StartHostClient()
|
|
||||||
{
|
|
||||||
Debug.Log("NetworkManager ConnectLocalClient");
|
|
||||||
|
|
||||||
if (authenticator != null)
|
|
||||||
{
|
|
||||||
authenticator.OnStartClient();
|
|
||||||
authenticator.OnClientAuthenticated.AddListener(OnClientAuthenticated);
|
|
||||||
}
|
|
||||||
|
|
||||||
networkAddress = "localhost";
|
|
||||||
NetworkServer.ActivateHostScene();
|
|
||||||
RegisterClientMessages();
|
|
||||||
|
|
||||||
// ConnectLocalServer needs to be called AFTER RegisterClientMessages
|
|
||||||
// (https://github.com/vis2k/Mirror/pull/1249/)
|
|
||||||
NetworkClient.ConnectLocalServer();
|
|
||||||
|
|
||||||
OnStartClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This stops both the client and the server that the manager is using.
|
|
||||||
/// </summary>
|
|
||||||
public void StopHost()
|
|
||||||
{
|
|
||||||
OnStopHost();
|
|
||||||
|
|
||||||
// TODO try to move DisconnectLocalServer into StopClient(), and
|
|
||||||
// then call StopClient() before StopServer(). needs testing!.
|
|
||||||
|
|
||||||
// DisconnectLocalServer needs to be called so that the host client
|
|
||||||
// receives a DisconnectMessage too.
|
|
||||||
// fixes: https://github.com/vis2k/Mirror/issues/1515
|
|
||||||
NetworkClient.DisconnectLocalServer();
|
|
||||||
|
|
||||||
StopClient();
|
|
||||||
StopServer();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stops the server that the manager is using.
|
/// Stops the server that the manager is using.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -761,7 +617,6 @@ public static void Shutdown()
|
|||||||
startPositionIndex = 0;
|
startPositionIndex = 0;
|
||||||
clientReadyConnection = null;
|
clientReadyConnection = null;
|
||||||
|
|
||||||
singleton.StopHost();
|
|
||||||
singleton = null;
|
singleton = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -945,13 +800,8 @@ void FinishLoadScene()
|
|||||||
Debug.Log("FinishLoadScene: resuming handlers after scene was loading.");
|
Debug.Log("FinishLoadScene: resuming handlers after scene was loading.");
|
||||||
Transport.activeTransport.enabled = true;
|
Transport.activeTransport.enabled = true;
|
||||||
|
|
||||||
// host mode?
|
|
||||||
if (mode == NetworkManagerMode.Host)
|
|
||||||
{
|
|
||||||
FinishLoadSceneHost();
|
|
||||||
}
|
|
||||||
// server-only mode?
|
// server-only mode?
|
||||||
else if (mode == NetworkManagerMode.ServerOnly)
|
if (mode == NetworkManagerMode.ServerOnly)
|
||||||
{
|
{
|
||||||
FinishLoadSceneServerOnly();
|
FinishLoadSceneServerOnly();
|
||||||
}
|
}
|
||||||
@ -964,58 +814,6 @@ void FinishLoadScene()
|
|||||||
// do nothing then.
|
// do nothing then.
|
||||||
}
|
}
|
||||||
|
|
||||||
// finish load scene part for host mode. makes code easier and is
|
|
||||||
// necessary for FinishStartHost later.
|
|
||||||
// (the 3 things have to happen in that exact order)
|
|
||||||
void FinishLoadSceneHost()
|
|
||||||
{
|
|
||||||
// debug message is very important. if we ever break anything then
|
|
||||||
// it's very obvious to notice.
|
|
||||||
Debug.Log("Finished loading scene in host mode.");
|
|
||||||
|
|
||||||
if (clientReadyConnection != null)
|
|
||||||
{
|
|
||||||
OnClientConnect(clientReadyConnection);
|
|
||||||
clientLoadedScene = true;
|
|
||||||
clientReadyConnection = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// do we need to finish a StartHost() call?
|
|
||||||
// then call FinishStartHost and let it take care of spawning etc.
|
|
||||||
if (finishStartHostPending)
|
|
||||||
{
|
|
||||||
finishStartHostPending = false;
|
|
||||||
FinishStartHost();
|
|
||||||
|
|
||||||
// call OnServerSceneChanged
|
|
||||||
OnServerSceneChanged(networkSceneName);
|
|
||||||
|
|
||||||
// DO NOT call OnClientSceneChanged here.
|
|
||||||
// the scene change happened because StartHost loaded the
|
|
||||||
// server's online scene. it has nothing to do with the client.
|
|
||||||
// this was not meant as a client scene load, so don't call it.
|
|
||||||
//
|
|
||||||
// otherwise AddPlayer would be called twice:
|
|
||||||
// -> once for client OnConnected
|
|
||||||
// -> once in OnClientSceneChanged
|
|
||||||
}
|
|
||||||
// otherwise we just changed a scene in host mode
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// spawn server objects
|
|
||||||
NetworkServer.SpawnObjects();
|
|
||||||
|
|
||||||
// call OnServerSceneChanged
|
|
||||||
OnServerSceneChanged(networkSceneName);
|
|
||||||
|
|
||||||
if (NetworkClient.isConnected)
|
|
||||||
{
|
|
||||||
// let client know that we changed scene
|
|
||||||
OnClientSceneChanged(NetworkClient.connection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// finish load scene part for server-only. . makes code easier and is
|
// finish load scene part for server-only. . makes code easier and is
|
||||||
// necessary for FinishStartServer later.
|
// necessary for FinishStartServer later.
|
||||||
void FinishLoadSceneServerOnly()
|
void FinishLoadSceneServerOnly()
|
||||||
@ -1320,13 +1118,6 @@ public virtual void OnServerAddPlayer(NetworkConnection conn)
|
|||||||
NetworkServer.AddPlayerForConnection(conn, player);
|
NetworkServer.AddPlayerForConnection(conn, player);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated 5/2/2020
|
|
||||||
/// <summary>
|
|
||||||
/// Obsolete: Removed as a security risk. Use <see cref="NetworkServer.RemovePlayerForConnection(NetworkConnection, bool)">NetworkServer.RemovePlayerForConnection</see> instead.
|
|
||||||
/// </summary>
|
|
||||||
[EditorBrowsable(EditorBrowsableState.Never), Obsolete("Removed as a security risk. Use NetworkServer.RemovePlayerForConnection(NetworkConnection conn, bool keepAuthority = false) instead", true)]
|
|
||||||
public virtual void OnServerRemovePlayer(NetworkConnection conn, NetworkIdentity player) { }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called on the server when a network error occurs for a client connection.
|
/// Called on the server when a network error occurs for a client connection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -1441,12 +1232,6 @@ public virtual void OnClientSceneChanged(NetworkConnection conn)
|
|||||||
// their functionality, users would need override all the versions. Instead these callbacks are invoked
|
// their functionality, users would need override all the versions. Instead these callbacks are invoked
|
||||||
// from all versions, so users only need to implement this one case.
|
// from all versions, so users only need to implement this one case.
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This is invoked when a host is started.
|
|
||||||
/// <para>StartHost has multiple signatures, but they all cause this hook to be called.</para>
|
|
||||||
/// </summary>
|
|
||||||
public virtual void OnStartHost() { }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is invoked when a server is started - including when a host is started.
|
/// This is invoked when a server is started - including when a host is started.
|
||||||
/// <para>StartServer has multiple signatures, but they all cause this hook to be called.</para>
|
/// <para>StartServer has multiple signatures, but they all cause this hook to be called.</para>
|
||||||
@ -1468,11 +1253,6 @@ public virtual void OnStopServer() { }
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void OnStopClient() { }
|
public virtual void OnStopClient() { }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This is called when a host is stopped.
|
|
||||||
/// </summary>
|
|
||||||
public virtual void OnStopHost() { }
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,15 +76,6 @@ void StartButtons()
|
|||||||
{
|
{
|
||||||
if (!NetworkClient.active)
|
if (!NetworkClient.active)
|
||||||
{
|
{
|
||||||
// Server + Client
|
|
||||||
if (Application.platform != RuntimePlatform.WebGLPlayer)
|
|
||||||
{
|
|
||||||
if (GUILayout.Button("Host (Server + Client)"))
|
|
||||||
{
|
|
||||||
manager.StartHost();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Client + IP
|
// Client + IP
|
||||||
GUILayout.BeginHorizontal();
|
GUILayout.BeginHorizontal();
|
||||||
if (GUILayout.Button("Client"))
|
if (GUILayout.Button("Client"))
|
||||||
@ -131,16 +122,8 @@ void StatusLabels()
|
|||||||
|
|
||||||
void StopButtons()
|
void StopButtons()
|
||||||
{
|
{
|
||||||
// stop host if host mode
|
|
||||||
if (NetworkServer.active && NetworkClient.isConnected)
|
|
||||||
{
|
|
||||||
if (GUILayout.Button("Stop Host"))
|
|
||||||
{
|
|
||||||
manager.StopHost();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// stop client if client-only
|
// stop client if client-only
|
||||||
else if (NetworkClient.isConnected)
|
if (NetworkClient.isConnected)
|
||||||
{
|
{
|
||||||
if (GUILayout.Button("Stop Client"))
|
if (GUILayout.Button("Stop Client"))
|
||||||
{
|
{
|
||||||
|
@ -20,17 +20,6 @@ public static class NetworkServer
|
|||||||
static bool initialized;
|
static bool initialized;
|
||||||
static int maxConnections;
|
static int maxConnections;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The connection to the host mode client (if any).
|
|
||||||
/// </summary>
|
|
||||||
public static NetworkConnectionToClient localConnection { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>True is a local client is currently active on the server.</para>
|
|
||||||
/// <para>This will be true for "Hosts" on hosted server games.</para>
|
|
||||||
/// </summary>
|
|
||||||
public static bool localClientActive => localConnection != null;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of local connections on the server.
|
/// A list of local connections on the server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -202,46 +191,6 @@ public static bool RemoveConnection(int connectionId)
|
|||||||
return connections.Remove(connectionId);
|
return connections.Remove(connectionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// called by LocalClient to add itself. dont call directly.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="conn"></param>
|
|
||||||
internal static void SetLocalConnection(ULocalConnectionToClient conn)
|
|
||||||
{
|
|
||||||
if (localConnection != null)
|
|
||||||
{
|
|
||||||
Debug.LogError("Local Connection already exists");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
localConnection = conn;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void RemoveLocalConnection()
|
|
||||||
{
|
|
||||||
if (localConnection != null)
|
|
||||||
{
|
|
||||||
localConnection.Disconnect();
|
|
||||||
localConnection.Dispose();
|
|
||||||
localConnection = null;
|
|
||||||
}
|
|
||||||
RemoveConnection(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ActivateHostScene()
|
|
||||||
{
|
|
||||||
foreach (NetworkIdentity identity in NetworkIdentity.spawned.Values)
|
|
||||||
{
|
|
||||||
if (!identity.isClient)
|
|
||||||
{
|
|
||||||
// Debug.Log("ActivateHostScene " + identity.netId + " " + identity);
|
|
||||||
|
|
||||||
identity.OnStartClient();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// this is like SendToReady - but it doesn't check the ready flag on the connection.
|
/// this is like SendToReady - but it doesn't check the ready flag on the connection.
|
||||||
/// this is used for ObjectDestroy messages.
|
/// this is used for ObjectDestroy messages.
|
||||||
@ -269,12 +218,7 @@ static void SendToObservers<T>(NetworkIdentity identity, T msg, int channelId =
|
|||||||
connectionIdsCache.Clear();
|
connectionIdsCache.Clear();
|
||||||
foreach (KeyValuePair<int, NetworkConnection> kvp in identity.observers)
|
foreach (KeyValuePair<int, NetworkConnection> kvp in identity.observers)
|
||||||
{
|
{
|
||||||
// use local connection directly because it doesn't send via transport
|
connectionIdsCache.Add(kvp.Key);
|
||||||
if (kvp.Value is ULocalConnectionToClient)
|
|
||||||
kvp.Value.Send(segment);
|
|
||||||
// gather all internet connections
|
|
||||||
else
|
|
||||||
connectionIdsCache.Add(kvp.Key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// send to all internet connections at once
|
// send to all internet connections at once
|
||||||
@ -315,20 +259,12 @@ public static bool SendToAll<T>(T msg, int channelId = Channels.DefaultReliable,
|
|||||||
// avoid allocations, allow for multicast, etc.
|
// avoid allocations, allow for multicast, etc.
|
||||||
connectionIdsCache.Clear();
|
connectionIdsCache.Clear();
|
||||||
bool result = true;
|
bool result = true;
|
||||||
int count = 0;
|
|
||||||
foreach (KeyValuePair<int, NetworkConnectionToClient> kvp in connections)
|
foreach (KeyValuePair<int, NetworkConnectionToClient> kvp in connections)
|
||||||
{
|
{
|
||||||
if (sendToReadyOnly && !kvp.Value.isReady)
|
if (sendToReadyOnly && !kvp.Value.isReady)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
count++;
|
connectionIdsCache.Add(kvp.Key);
|
||||||
|
|
||||||
// use local connection directly because it doesn't send via transport
|
|
||||||
if (kvp.Value is ULocalConnectionToClient)
|
|
||||||
result &= kvp.Value.Send(segment);
|
|
||||||
// gather all internet connections
|
|
||||||
else
|
|
||||||
connectionIdsCache.Add(kvp.Key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// send to all internet connections at once
|
// send to all internet connections at once
|
||||||
@ -388,20 +324,12 @@ public static bool SendToReady<T>(NetworkIdentity identity, T msg, bool includeO
|
|||||||
// avoid allocations, allow for multicast, etc.
|
// avoid allocations, allow for multicast, etc.
|
||||||
connectionIdsCache.Clear();
|
connectionIdsCache.Clear();
|
||||||
bool result = true;
|
bool result = true;
|
||||||
int count = 0;
|
|
||||||
foreach (KeyValuePair<int, NetworkConnection> kvp in identity.observers)
|
foreach (KeyValuePair<int, NetworkConnection> kvp in identity.observers)
|
||||||
{
|
{
|
||||||
bool isOwner = kvp.Value == identity.connectionToClient;
|
bool isOwner = kvp.Value == identity.connectionToClient;
|
||||||
if ((!isOwner || includeOwner) && kvp.Value.isReady)
|
if ((!isOwner || includeOwner) && kvp.Value.isReady)
|
||||||
{
|
{
|
||||||
count++;
|
connectionIdsCache.Add(kvp.Key);
|
||||||
|
|
||||||
// use local connection directly because it doesn't send via transport
|
|
||||||
if (kvp.Value is ULocalConnectionToClient)
|
|
||||||
result &= kvp.Value.Send(segment);
|
|
||||||
// gather all internet connections
|
|
||||||
else
|
|
||||||
connectionIdsCache.Add(kvp.Key);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,8 +364,6 @@ public static bool SendToReady<T>(NetworkIdentity identity, T msg, int channelId
|
|||||||
public static void DisconnectAll()
|
public static void DisconnectAll()
|
||||||
{
|
{
|
||||||
DisconnectAllConnections();
|
DisconnectAllConnections();
|
||||||
localConnection = null;
|
|
||||||
|
|
||||||
active = false;
|
active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -450,9 +376,7 @@ public static void DisconnectAllConnections()
|
|||||||
foreach (NetworkConnection conn in connections.Values)
|
foreach (NetworkConnection conn in connections.Values)
|
||||||
{
|
{
|
||||||
conn.Disconnect();
|
conn.Disconnect();
|
||||||
// call OnDisconnected unless local player in host mode
|
OnDisconnected(conn);
|
||||||
if (conn.connectionId != NetworkConnection.LocalConnectionId)
|
|
||||||
OnDisconnected(conn);
|
|
||||||
conn.Dispose();
|
conn.Dispose();
|
||||||
}
|
}
|
||||||
connections.Clear();
|
connections.Clear();
|
||||||
@ -464,7 +388,7 @@ public static void DisconnectAllConnections()
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static bool NoConnections()
|
public static bool NoConnections()
|
||||||
{
|
{
|
||||||
return connections.Count == 0 || (connections.Count == 1 && localConnection != null);
|
return connections.Count == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -799,13 +723,6 @@ public static bool AddPlayerForConnection(NetworkConnection conn, GameObject pla
|
|||||||
// Set the connection on the NetworkIdentity on the server, NetworkIdentity.SetLocalPlayer is not called on the server (it is on clients)
|
// Set the connection on the NetworkIdentity on the server, NetworkIdentity.SetLocalPlayer is not called on the server (it is on clients)
|
||||||
identity.SetClientOwner(conn);
|
identity.SetClientOwner(conn);
|
||||||
|
|
||||||
// special case, we are in host mode, set hasAuthority to true so that all overrides see it
|
|
||||||
if (conn is ULocalConnectionToClient)
|
|
||||||
{
|
|
||||||
identity.hasAuthority = true;
|
|
||||||
ClientScene.InternalAddPlayer(identity);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set ready if not set yet
|
// set ready if not set yet
|
||||||
SetClientReady(conn);
|
SetClientReady(conn);
|
||||||
|
|
||||||
@ -854,13 +771,6 @@ internal static bool InternalReplacePlayerForConnection(NetworkConnection conn,
|
|||||||
// Set the connection on the NetworkIdentity on the server, NetworkIdentity.SetLocalPlayer is not called on the server (it is on clients)
|
// Set the connection on the NetworkIdentity on the server, NetworkIdentity.SetLocalPlayer is not called on the server (it is on clients)
|
||||||
identity.SetClientOwner(conn);
|
identity.SetClientOwner(conn);
|
||||||
|
|
||||||
// special case, we are in host mode, set hasAuthority to true so that all overrides see it
|
|
||||||
if (conn is ULocalConnectionToClient)
|
|
||||||
{
|
|
||||||
identity.hasAuthority = true;
|
|
||||||
ClientScene.InternalAddPlayer(identity);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add connection to observers AFTER the playerController was set.
|
// add connection to observers AFTER the playerController was set.
|
||||||
// by definition, there is nothing to observe if there is no player
|
// by definition, there is nothing to observe if there is no player
|
||||||
// controller.
|
// controller.
|
||||||
@ -1038,11 +948,6 @@ internal static void SpawnObject(GameObject obj, NetworkConnection ownerConnecti
|
|||||||
|
|
||||||
identity.connectionToClient = (NetworkConnectionToClient)ownerConnection;
|
identity.connectionToClient = (NetworkConnectionToClient)ownerConnection;
|
||||||
|
|
||||||
// special case to make sure hasAuthority is set
|
|
||||||
// on start server in host mode
|
|
||||||
if (ownerConnection is ULocalConnectionToClient)
|
|
||||||
identity.hasAuthority = true;
|
|
||||||
|
|
||||||
identity.OnStartServer();
|
identity.OnStartServer();
|
||||||
|
|
||||||
// Debug.Log("SpawnObject instance ID " + identity.netId + " asset ID " + identity.assetId);
|
// Debug.Log("SpawnObject instance ID " + identity.netId + " asset ID " + identity.assetId);
|
||||||
@ -1218,11 +1123,6 @@ static void DestroyObject(NetworkIdentity identity, bool destroyServerObject)
|
|||||||
SendToObservers(identity, msg);
|
SendToObservers(identity, msg);
|
||||||
|
|
||||||
identity.ClearObservers();
|
identity.ClearObservers();
|
||||||
if (NetworkClient.active && localClientActive)
|
|
||||||
{
|
|
||||||
identity.OnStopClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
identity.OnStopServer();
|
identity.OnStopServer();
|
||||||
|
|
||||||
// when unspawning, dont destroy the server's object
|
// when unspawning, dont destroy the server's object
|
||||||
|
@ -27,16 +27,5 @@ public abstract class NetworkVisibility : NetworkBehaviour
|
|||||||
/// <param name="observers">The new set of observers for this object.</param>
|
/// <param name="observers">The new set of observers for this object.</param>
|
||||||
/// <param name="initialize">True if the set of observers is being built for the first time.</param>
|
/// <param name="initialize">True if the set of observers is being built for the first time.</param>
|
||||||
public abstract void OnRebuildObservers(HashSet<NetworkConnection> observers, bool initialize);
|
public abstract void OnRebuildObservers(HashSet<NetworkConnection> observers, bool initialize);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Callback used by the visibility system for objects on a host.
|
|
||||||
/// <para>Objects on a host (with a local client) cannot be disabled or destroyed when they are not visible to the local client. So this function is called to allow custom code to hide these objects. A typical implementation will disable renderer components on the object. This is only called on local clients on a host.</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="visible">New visibility state.</param>
|
|
||||||
public virtual void OnSetHostVisibility(bool visible)
|
|
||||||
{
|
|
||||||
foreach (Renderer rend in GetComponentsInChildren<Renderer>())
|
|
||||||
rend.enabled = visible;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,136 +0,0 @@
|
|||||||
using System;
|
|
||||||
using NUnit.Framework;
|
|
||||||
|
|
||||||
namespace Mirror.Tests.RemoteAttrributeTest
|
|
||||||
{
|
|
||||||
class VirtualClientRpc : NetworkBehaviour
|
|
||||||
{
|
|
||||||
public event Action<int> onVirtualSendInt;
|
|
||||||
|
|
||||||
[ClientRpc]
|
|
||||||
public virtual void RpcSendInt(int someInt)
|
|
||||||
{
|
|
||||||
onVirtualSendInt?.Invoke(someInt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class VirtualNoOverrideClientRpc : VirtualClientRpc
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class VirtualOverrideClientRpc : VirtualClientRpc
|
|
||||||
{
|
|
||||||
public event Action<int> onOverrideSendInt;
|
|
||||||
|
|
||||||
[ClientRpc]
|
|
||||||
public override void RpcSendInt(int someInt)
|
|
||||||
{
|
|
||||||
onOverrideSendInt?.Invoke(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
|
|
||||||
{
|
|
||||||
[Test]
|
|
||||||
public void VirtualRpcIsCalled()
|
|
||||||
{
|
|
||||||
VirtualClientRpc hostBehaviour = CreateHostObject<VirtualClientRpc>(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]
|
|
||||||
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]
|
|
||||||
public void OverrideVirtualRpcIsCalled()
|
|
||||||
{
|
|
||||||
VirtualOverrideClientRpc hostBehaviour = CreateHostObject<VirtualOverrideClientRpc>(true);
|
|
||||||
|
|
||||||
const int someInt = 20;
|
|
||||||
|
|
||||||
int virtualCallCount = 0;
|
|
||||||
int overrideCallCount = 0;
|
|
||||||
hostBehaviour.onVirtualSendInt += incomingInt =>
|
|
||||||
{
|
|
||||||
virtualCallCount++;
|
|
||||||
};
|
|
||||||
hostBehaviour.onOverrideSendInt += incomingInt =>
|
|
||||||
{
|
|
||||||
overrideCallCount++;
|
|
||||||
Assert.That(incomingInt, Is.EqualTo(someInt));
|
|
||||||
};
|
|
||||||
|
|
||||||
hostBehaviour.RpcSendInt(someInt);
|
|
||||||
ProcessMessages();
|
|
||||||
Assert.That(virtualCallCount, Is.EqualTo(0));
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 9759f0eddb9731c4b881ac30bacc0de0
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,86 +0,0 @@
|
|||||||
using System;
|
|
||||||
using NUnit.Framework;
|
|
||||||
|
|
||||||
namespace Mirror.Tests.RemoteAttrributeTest
|
|
||||||
{
|
|
||||||
class ClientRpcBehaviour : NetworkBehaviour
|
|
||||||
{
|
|
||||||
public event Action<int> onSendInt;
|
|
||||||
|
|
||||||
[ClientRpc]
|
|
||||||
public void SendInt(int someInt)
|
|
||||||
{
|
|
||||||
onSendInt?.Invoke(someInt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ExcludeOwnerBehaviour : NetworkBehaviour
|
|
||||||
{
|
|
||||||
public event Action<int> onSendInt;
|
|
||||||
|
|
||||||
[ClientRpc(excludeOwner = true)]
|
|
||||||
public void RpcSendInt(int someInt)
|
|
||||||
{
|
|
||||||
onSendInt?.Invoke(someInt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ClientRpcTest : RemoteTestBase
|
|
||||||
{
|
|
||||||
[Test]
|
|
||||||
public void RpcIsCalled()
|
|
||||||
{
|
|
||||||
ClientRpcBehaviour hostBehaviour = CreateHostObject<ClientRpcBehaviour>(true);
|
|
||||||
|
|
||||||
const int someInt = 20;
|
|
||||||
|
|
||||||
int callCount = 0;
|
|
||||||
hostBehaviour.onSendInt += incomingInt =>
|
|
||||||
{
|
|
||||||
callCount++;
|
|
||||||
Assert.That(incomingInt, Is.EqualTo(someInt));
|
|
||||||
};
|
|
||||||
hostBehaviour.SendInt(someInt);
|
|
||||||
ProcessMessages();
|
|
||||||
Assert.That(callCount, Is.EqualTo(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void RpcIsCalledForNotOwnerd()
|
|
||||||
{
|
|
||||||
bool owner = false;
|
|
||||||
ExcludeOwnerBehaviour hostBehaviour = CreateHostObject<ExcludeOwnerBehaviour>(owner);
|
|
||||||
|
|
||||||
const int someInt = 20;
|
|
||||||
|
|
||||||
int callCount = 0;
|
|
||||||
hostBehaviour.onSendInt += incomingInt =>
|
|
||||||
{
|
|
||||||
callCount++;
|
|
||||||
Assert.That(incomingInt, Is.EqualTo(someInt));
|
|
||||||
};
|
|
||||||
hostBehaviour.RpcSendInt(someInt);
|
|
||||||
ProcessMessages();
|
|
||||||
Assert.That(callCount, Is.EqualTo(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void RpcNotCalledForOwnerd()
|
|
||||||
{
|
|
||||||
bool owner = true;
|
|
||||||
ExcludeOwnerBehaviour hostBehaviour = CreateHostObject<ExcludeOwnerBehaviour>(owner);
|
|
||||||
|
|
||||||
const int someInt = 20;
|
|
||||||
|
|
||||||
int callCount = 0;
|
|
||||||
hostBehaviour.onSendInt += incomingInt =>
|
|
||||||
{
|
|
||||||
callCount++;
|
|
||||||
Assert.That(incomingInt, Is.EqualTo(someInt));
|
|
||||||
};
|
|
||||||
hostBehaviour.RpcSendInt(someInt);
|
|
||||||
ProcessMessages();
|
|
||||||
Assert.That(callCount, Is.EqualTo(0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 2928376e56382b646975dd00b68c2287
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,185 +0,0 @@
|
|||||||
using System;
|
|
||||||
using NUnit.Framework;
|
|
||||||
|
|
||||||
namespace Mirror.Tests.RemoteAttrributeTest
|
|
||||||
{
|
|
||||||
class VirtualCommand : NetworkBehaviour
|
|
||||||
{
|
|
||||||
public event Action<int> onVirtualSendInt;
|
|
||||||
|
|
||||||
[Command]
|
|
||||||
public virtual void CmdSendInt(int someInt)
|
|
||||||
{
|
|
||||||
onVirtualSendInt?.Invoke(someInt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class VirtualNoOverrideCommand : VirtualCommand
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class VirtualOverrideCommand : VirtualCommand
|
|
||||||
{
|
|
||||||
public event Action<int> onOverrideSendInt;
|
|
||||||
|
|
||||||
[Command]
|
|
||||||
public override void CmdSendInt(int someInt)
|
|
||||||
{
|
|
||||||
onOverrideSendInt?.Invoke(someInt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class VirtualOverrideCommandWithBase : VirtualCommand
|
|
||||||
{
|
|
||||||
public event Action<int> onOverrideSendInt;
|
|
||||||
|
|
||||||
[Command]
|
|
||||||
public override void CmdSendInt(int someInt)
|
|
||||||
{
|
|
||||||
base.CmdSendInt(someInt);
|
|
||||||
onOverrideSendInt?.Invoke(someInt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// test for 2 overrides
|
|
||||||
/// </summary>
|
|
||||||
class VirtualOverrideCommandWithBase2 : VirtualOverrideCommandWithBase
|
|
||||||
{
|
|
||||||
public event Action<int> onOverrideSendInt2;
|
|
||||||
|
|
||||||
[Command]
|
|
||||||
public override void CmdSendInt(int someInt)
|
|
||||||
{
|
|
||||||
base.CmdSendInt(someInt);
|
|
||||||
onOverrideSendInt2?.Invoke(someInt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CommandOverrideTest : RemoteTestBase
|
|
||||||
{
|
|
||||||
[Test]
|
|
||||||
public void VirtualCommandIsCalled()
|
|
||||||
{
|
|
||||||
VirtualCommand hostBehaviour = CreateHostObject<VirtualCommand>(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]
|
|
||||||
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]
|
|
||||||
public void OverrideVirtualCommandIsCalled()
|
|
||||||
{
|
|
||||||
VirtualOverrideCommand hostBehaviour = CreateHostObject<VirtualOverrideCommand>(true);
|
|
||||||
|
|
||||||
const int someInt = 20;
|
|
||||||
|
|
||||||
int virtualCallCount = 0;
|
|
||||||
int overrideCallCount = 0;
|
|
||||||
hostBehaviour.onVirtualSendInt += incomingInt =>
|
|
||||||
{
|
|
||||||
virtualCallCount++;
|
|
||||||
};
|
|
||||||
hostBehaviour.onOverrideSendInt += incomingInt =>
|
|
||||||
{
|
|
||||||
overrideCallCount++;
|
|
||||||
Assert.That(incomingInt, Is.EqualTo(someInt));
|
|
||||||
};
|
|
||||||
|
|
||||||
hostBehaviour.CmdSendInt(someInt);
|
|
||||||
ProcessMessages();
|
|
||||||
Assert.That(virtualCallCount, Is.EqualTo(0));
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void OverrideVirtualWithBaseCallsAllMethodsThatCallBase()
|
|
||||||
{
|
|
||||||
VirtualOverrideCommandWithBase2 hostBehaviour = CreateHostObject<VirtualOverrideCommandWithBase2>(true);
|
|
||||||
|
|
||||||
const int someInt = 20;
|
|
||||||
|
|
||||||
int virtualCallCount = 0;
|
|
||||||
int overrideCallCount = 0;
|
|
||||||
int override2CallCount = 0;
|
|
||||||
hostBehaviour.onVirtualSendInt += incomingInt =>
|
|
||||||
{
|
|
||||||
virtualCallCount++;
|
|
||||||
Assert.That(incomingInt, Is.EqualTo(someInt));
|
|
||||||
};
|
|
||||||
hostBehaviour.onOverrideSendInt += incomingInt =>
|
|
||||||
{
|
|
||||||
overrideCallCount++;
|
|
||||||
Assert.That(incomingInt, Is.EqualTo(someInt));
|
|
||||||
};
|
|
||||||
hostBehaviour.onOverrideSendInt2 += incomingInt =>
|
|
||||||
{
|
|
||||||
override2CallCount++;
|
|
||||||
Assert.That(incomingInt, Is.EqualTo(someInt));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
hostBehaviour.CmdSendInt(someInt);
|
|
||||||
ProcessMessages();
|
|
||||||
Assert.That(virtualCallCount, Is.EqualTo(1));
|
|
||||||
Assert.That(overrideCallCount, Is.EqualTo(1));
|
|
||||||
Assert.That(override2CallCount, Is.EqualTo(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 881c801c26e90df43b3558a23c96e0ea
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,170 +0,0 @@
|
|||||||
using System;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.TestTools;
|
|
||||||
|
|
||||||
namespace Mirror.Tests.RemoteAttrributeTest
|
|
||||||
{
|
|
||||||
class AuthorityBehaviour : NetworkBehaviour
|
|
||||||
{
|
|
||||||
public event Action<int> onSendInt;
|
|
||||||
|
|
||||||
[Command]
|
|
||||||
public void SendInt(int someInt)
|
|
||||||
{
|
|
||||||
onSendInt?.Invoke(someInt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class IgnoreAuthorityBehaviour : NetworkBehaviour
|
|
||||||
{
|
|
||||||
public event Action<int> onSendInt;
|
|
||||||
|
|
||||||
[Command(ignoreAuthority = true)]
|
|
||||||
public void CmdSendInt(int someInt)
|
|
||||||
{
|
|
||||||
onSendInt?.Invoke(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]
|
|
||||||
public void CommandIsSentWithAuthority()
|
|
||||||
{
|
|
||||||
AuthorityBehaviour hostBehaviour = CreateHostObject<AuthorityBehaviour>(true);
|
|
||||||
|
|
||||||
const int someInt = 20;
|
|
||||||
|
|
||||||
int callCount = 0;
|
|
||||||
hostBehaviour.onSendInt += incomingInt =>
|
|
||||||
{
|
|
||||||
callCount++;
|
|
||||||
Assert.That(incomingInt, Is.EqualTo(someInt));
|
|
||||||
};
|
|
||||||
hostBehaviour.SendInt(someInt);
|
|
||||||
ProcessMessages();
|
|
||||||
Assert.That(callCount, Is.EqualTo(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void WarningForCommandSentWithoutAuthority()
|
|
||||||
{
|
|
||||||
AuthorityBehaviour hostBehaviour = CreateHostObject<AuthorityBehaviour>(false);
|
|
||||||
|
|
||||||
const int someInt = 20;
|
|
||||||
|
|
||||||
int callCount = 0;
|
|
||||||
hostBehaviour.onSendInt += incomingInt =>
|
|
||||||
{
|
|
||||||
callCount++;
|
|
||||||
};
|
|
||||||
LogAssert.Expect(LogType.Warning, $"Trying to send command for object without authority. {typeof(AuthorityBehaviour).ToString()}.{nameof(AuthorityBehaviour.SendInt)}");
|
|
||||||
hostBehaviour.SendInt(someInt);
|
|
||||||
ProcessMessages();
|
|
||||||
Assert.That(callCount, Is.Zero);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void CommandIsSentWithAuthorityWhenIgnoringAuthority()
|
|
||||||
{
|
|
||||||
IgnoreAuthorityBehaviour hostBehaviour = CreateHostObject<IgnoreAuthorityBehaviour>(true);
|
|
||||||
|
|
||||||
const int someInt = 20;
|
|
||||||
|
|
||||||
int callCount = 0;
|
|
||||||
hostBehaviour.onSendInt += incomingInt =>
|
|
||||||
{
|
|
||||||
callCount++;
|
|
||||||
Assert.That(incomingInt, Is.EqualTo(someInt));
|
|
||||||
};
|
|
||||||
hostBehaviour.CmdSendInt(someInt);
|
|
||||||
ProcessMessages();
|
|
||||||
Assert.That(callCount, Is.EqualTo(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void CommandIsSentWithoutAuthorityWhenIgnoringAuthority()
|
|
||||||
{
|
|
||||||
IgnoreAuthorityBehaviour hostBehaviour = CreateHostObject<IgnoreAuthorityBehaviour>(false);
|
|
||||||
|
|
||||||
const int someInt = 20;
|
|
||||||
|
|
||||||
int callCount = 0;
|
|
||||||
hostBehaviour.onSendInt += incomingInt =>
|
|
||||||
{
|
|
||||||
callCount++;
|
|
||||||
Assert.That(incomingInt, Is.EqualTo(someInt));
|
|
||||||
};
|
|
||||||
hostBehaviour.CmdSendInt(someInt);
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 1dd3f8a95eee6f74997bc8abcd43a401
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,53 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Mirror.Tests.RemoteAttrributeTest;
|
|
||||||
using NUnit.Framework;
|
|
||||||
|
|
||||||
namespace Mirror.Tests.GeneratedWriterTests
|
|
||||||
{
|
|
||||||
public class BaseData
|
|
||||||
{
|
|
||||||
public bool toggle;
|
|
||||||
}
|
|
||||||
public class SomeOtherData : BaseData
|
|
||||||
{
|
|
||||||
public int usefulNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DataSenderBehaviour : NetworkBehaviour
|
|
||||||
{
|
|
||||||
public event Action<SomeOtherData> onData;
|
|
||||||
[Command]
|
|
||||||
public void CmdSendData(SomeOtherData otherData)
|
|
||||||
{
|
|
||||||
onData?.Invoke(otherData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class FieldsInBaseClasses : RemoteTestBase
|
|
||||||
{
|
|
||||||
[Test]
|
|
||||||
public void WriterShouldIncludeFieldsInBaseClass()
|
|
||||||
{
|
|
||||||
DataSenderBehaviour hostBehaviour = CreateHostObject<DataSenderBehaviour>(true);
|
|
||||||
|
|
||||||
const bool toggle = true;
|
|
||||||
const int usefulNumber = 10;
|
|
||||||
|
|
||||||
int callCount = 0;
|
|
||||||
hostBehaviour.onData += data =>
|
|
||||||
{
|
|
||||||
callCount++;
|
|
||||||
Assert.That(data.usefulNumber, Is.EqualTo(usefulNumber));
|
|
||||||
Assert.That(data.toggle, Is.EqualTo(toggle));
|
|
||||||
};
|
|
||||||
hostBehaviour.CmdSendData(new SomeOtherData
|
|
||||||
{
|
|
||||||
usefulNumber = usefulNumber,
|
|
||||||
toggle = toggle
|
|
||||||
});
|
|
||||||
|
|
||||||
ProcessMessages();
|
|
||||||
Assert.That(callCount, Is.EqualTo(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 518288ffe7c7215458a98466131fc7af
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,142 +0,0 @@
|
|||||||
using System;
|
|
||||||
using NUnit.Framework;
|
|
||||||
|
|
||||||
namespace Mirror.Tests
|
|
||||||
{
|
|
||||||
public class LocalConnectionBufferTest
|
|
||||||
{
|
|
||||||
readonly LocalConnectionBuffer buffer = new LocalConnectionBuffer();
|
|
||||||
|
|
||||||
[TearDown]
|
|
||||||
public void TearDown()
|
|
||||||
{
|
|
||||||
buffer.ResetBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void BufferHasPacketsAfterWriter()
|
|
||||||
{
|
|
||||||
using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
|
|
||||||
{
|
|
||||||
writer.WriteString("Some Message");
|
|
||||||
|
|
||||||
buffer.Write(writer.ToArraySegment());
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.IsTrue(buffer.HasPackets());
|
|
||||||
}
|
|
||||||
[Test]
|
|
||||||
public void BufferHasNoPacketsAfterWriteAndReading()
|
|
||||||
{
|
|
||||||
using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
|
|
||||||
{
|
|
||||||
writer.WriteString("Some Message");
|
|
||||||
|
|
||||||
buffer.Write(writer.ToArraySegment());
|
|
||||||
}
|
|
||||||
ArraySegment<byte> package = buffer.GetNextPacket();
|
|
||||||
|
|
||||||
|
|
||||||
Assert.IsFalse(buffer.HasPackets());
|
|
||||||
}
|
|
||||||
[Test]
|
|
||||||
public void BufferCanWriteAndReadPackages()
|
|
||||||
{
|
|
||||||
const string expectedMessage = "Some Message";
|
|
||||||
const float expectedValue = 46.8f;
|
|
||||||
using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
|
|
||||||
{
|
|
||||||
writer.WriteString(expectedMessage);
|
|
||||||
writer.WriteSingle(expectedValue);
|
|
||||||
|
|
||||||
buffer.Write(writer.ToArraySegment());
|
|
||||||
}
|
|
||||||
ArraySegment<byte> package = buffer.GetNextPacket();
|
|
||||||
|
|
||||||
string message;
|
|
||||||
float value;
|
|
||||||
using (PooledNetworkReader reader = NetworkReaderPool.GetReader(package))
|
|
||||||
{
|
|
||||||
message = reader.ReadString();
|
|
||||||
value = reader.ReadSingle();
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.That(message, Is.EqualTo(expectedMessage));
|
|
||||||
Assert.That(value, Is.EqualTo(expectedValue));
|
|
||||||
}
|
|
||||||
[Test]
|
|
||||||
public void BufferReturnsMutliplePacketsInTheOrderTheyWereWriten()
|
|
||||||
{
|
|
||||||
const string expectedMessage1 = "first Message";
|
|
||||||
const string expectedMessage2 = "second Message";
|
|
||||||
using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
|
|
||||||
{
|
|
||||||
writer.WriteString(expectedMessage1);
|
|
||||||
|
|
||||||
buffer.Write(writer.ToArraySegment());
|
|
||||||
}
|
|
||||||
|
|
||||||
using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
|
|
||||||
{
|
|
||||||
writer.WriteString(expectedMessage2);
|
|
||||||
|
|
||||||
buffer.Write(writer.ToArraySegment());
|
|
||||||
}
|
|
||||||
|
|
||||||
string message1;
|
|
||||||
string message2;
|
|
||||||
ArraySegment<byte> package1 = buffer.GetNextPacket();
|
|
||||||
|
|
||||||
using (PooledNetworkReader reader = NetworkReaderPool.GetReader(package1))
|
|
||||||
{
|
|
||||||
message1 = reader.ReadString();
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.IsTrue(buffer.HasPackets());
|
|
||||||
ArraySegment<byte> package2 = buffer.GetNextPacket();
|
|
||||||
|
|
||||||
using (PooledNetworkReader reader = NetworkReaderPool.GetReader(package2))
|
|
||||||
{
|
|
||||||
message2 = reader.ReadString();
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.That(message1, Is.EqualTo(expectedMessage1));
|
|
||||||
Assert.That(message2, Is.EqualTo(expectedMessage2));
|
|
||||||
}
|
|
||||||
[Test]
|
|
||||||
public void BufferCanWriteReadMorePackageAfterCallingReset()
|
|
||||||
{
|
|
||||||
const string expectedMessage = "Some Message";
|
|
||||||
const float expectedValue = 46.8f;
|
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++)
|
|
||||||
{
|
|
||||||
using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
|
|
||||||
{
|
|
||||||
writer.WriteInt32(i);
|
|
||||||
writer.WriteString(expectedMessage);
|
|
||||||
writer.WriteSingle(expectedValue);
|
|
||||||
|
|
||||||
buffer.Write(writer.ToArraySegment());
|
|
||||||
}
|
|
||||||
ArraySegment<byte> package = buffer.GetNextPacket();
|
|
||||||
|
|
||||||
int index;
|
|
||||||
string message;
|
|
||||||
float value;
|
|
||||||
using (PooledNetworkReader reader = NetworkReaderPool.GetReader(package))
|
|
||||||
{
|
|
||||||
index = reader.ReadInt32();
|
|
||||||
message = reader.ReadString();
|
|
||||||
value = reader.ReadSingle();
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.That(index, Is.EqualTo(i));
|
|
||||||
Assert.That(message, Is.EqualTo(expectedMessage));
|
|
||||||
Assert.That(value, Is.EqualTo(expectedValue));
|
|
||||||
|
|
||||||
buffer.ResetBuffer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: e035d8111975b864099f87f21c5518ff
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,110 +0,0 @@
|
|||||||
using System;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using UnityEngine.TestTools;
|
|
||||||
|
|
||||||
namespace Mirror.Tests
|
|
||||||
{
|
|
||||||
public class LocalConnectionTest
|
|
||||||
{
|
|
||||||
|
|
||||||
/*class MyMessage : MessageBase
|
|
||||||
{
|
|
||||||
public int id;
|
|
||||||
public string name;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
ULocalConnectionToClient connectionToClient;
|
|
||||||
ULocalConnectionToServer connectionToServer;
|
|
||||||
|
|
||||||
[SetUp]
|
|
||||||
public void SetUpConnections()
|
|
||||||
{
|
|
||||||
connectionToServer = new ULocalConnectionToServer();
|
|
||||||
connectionToClient = new ULocalConnectionToClient();
|
|
||||||
|
|
||||||
connectionToClient.connectionToServer = connectionToServer;
|
|
||||||
connectionToServer.connectionToClient = connectionToClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
[TearDown]
|
|
||||||
public void Disconnect()
|
|
||||||
{
|
|
||||||
connectionToServer.Disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*[Test]
|
|
||||||
public void ServerToClientTest()
|
|
||||||
{
|
|
||||||
Assert.That(connectionToClient.address, Is.EqualTo("localhost"));
|
|
||||||
|
|
||||||
MyMessage myMessage = new MyMessage()
|
|
||||||
{
|
|
||||||
id = 3,
|
|
||||||
name = "hello"
|
|
||||||
};
|
|
||||||
|
|
||||||
bool invoked = false;
|
|
||||||
|
|
||||||
void handler(NetworkConnection conn, NetworkReader reader, int channelId)
|
|
||||||
{
|
|
||||||
MyMessage received = msg.ReadMessage<MyMessage>();
|
|
||||||
Assert.That(received.id, Is.EqualTo(3));
|
|
||||||
Assert.That(received.name, Is.EqualTo("hello"));
|
|
||||||
invoked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Dictionary<int, NetworkMessageDelegate> handlers = new Dictionary<int, NetworkMessageDelegate>();
|
|
||||||
handlers.Add(MessagePacker.GetId<MyMessage>(), handler);
|
|
||||||
|
|
||||||
connectionToClient.SetHandlers(handlers);
|
|
||||||
connectionToServer.Send(myMessage);
|
|
||||||
|
|
||||||
connectionToServer.Update();
|
|
||||||
|
|
||||||
Assert.True(invoked, "handler should have been invoked");
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*[Test]
|
|
||||||
public void ClientToServerTest()
|
|
||||||
{
|
|
||||||
Assert.That(connectionToServer.address, Is.EqualTo("localhost"));
|
|
||||||
|
|
||||||
MyMessage myMessage = new MyMessage()
|
|
||||||
{
|
|
||||||
id = 3,
|
|
||||||
name = "hello"
|
|
||||||
};
|
|
||||||
|
|
||||||
bool invoked = false;
|
|
||||||
|
|
||||||
void handler(NetworkConnection conn, NetworkReader reader, int channelId)
|
|
||||||
{
|
|
||||||
MyMessage received = msg.ReadMessage<MyMessage>();
|
|
||||||
Assert.That(received.id, Is.EqualTo(3));
|
|
||||||
Assert.That(received.name, Is.EqualTo("hello"));
|
|
||||||
invoked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Dictionary<int, NetworkMessageDelegate> handlers = new Dictionary<int, NetworkMessageDelegate>();
|
|
||||||
handlers.Add(MessagePacker.GetId<MyMessage>(), handler);
|
|
||||||
|
|
||||||
connectionToServer.SetHandlers(handlers);
|
|
||||||
connectionToClient.Send(myMessage);
|
|
||||||
|
|
||||||
connectionToServer.Update();
|
|
||||||
|
|
||||||
Assert.True(invoked, "handler should have been invoked");
|
|
||||||
}*/
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ClientToServerFailTest()
|
|
||||||
{
|
|
||||||
// error log is expected
|
|
||||||
LogAssert.ignoreFailingMessages = true;
|
|
||||||
bool result = connectionToServer.Send(new ArraySegment<byte>(new byte[0]));
|
|
||||||
LogAssert.ignoreFailingMessages = false;
|
|
||||||
|
|
||||||
Assert.That(result, Is.False);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 405841e2a21c64d7585d5c71d06ffff2
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -175,7 +175,6 @@ public void TearDown()
|
|||||||
// DestroyImmediate is called internally, giving an error in Editor
|
// DestroyImmediate is called internally, giving an error in Editor
|
||||||
identity.isServer = false;
|
identity.isServer = false;
|
||||||
GameObject.DestroyImmediate(gameObject);
|
GameObject.DestroyImmediate(gameObject);
|
||||||
NetworkServer.RemoveLocalConnection();
|
|
||||||
|
|
||||||
NetworkIdentity.spawned.Clear();
|
NetworkIdentity.spawned.Clear();
|
||||||
}
|
}
|
||||||
@ -217,20 +216,6 @@ public void HasIdentitysNetId()
|
|||||||
Assert.That(emptyBehaviour.netId, Is.EqualTo(42));
|
Assert.That(emptyBehaviour.netId, Is.EqualTo(42));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void HasIdentitysConnectionToServer()
|
|
||||||
{
|
|
||||||
identity.connectionToServer = new ULocalConnectionToServer();
|
|
||||||
Assert.That(emptyBehaviour.connectionToServer, Is.EqualTo(identity.connectionToServer));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void HasIdentitysConnectionToClient()
|
|
||||||
{
|
|
||||||
identity.connectionToClient = new ULocalConnectionToClient();
|
|
||||||
Assert.That(emptyBehaviour.connectionToClient, Is.EqualTo(identity.connectionToClient));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void ComponentIndex()
|
public void ComponentIndex()
|
||||||
{
|
{
|
||||||
@ -250,288 +235,6 @@ public void OnCheckObserverTrueByDefault()
|
|||||||
Assert.That(identity.OnCheckObserver(null), Is.True);
|
Assert.That(identity.OnCheckObserver(null), Is.True);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void SendCommandInternal()
|
|
||||||
{
|
|
||||||
// transport is needed by server and client.
|
|
||||||
// it needs to be on a gameobject because client.connect enables it,
|
|
||||||
// which throws a NRE if not on a gameobject
|
|
||||||
GameObject transportGO = new GameObject();
|
|
||||||
Transport.activeTransport = transportGO.AddComponent<MemoryTransport>();
|
|
||||||
|
|
||||||
// we need to start a server and connect a client in order to be
|
|
||||||
// able to send commands
|
|
||||||
// message handlers
|
|
||||||
NetworkServer.RegisterHandler<ConnectMessage>((conn, msg) => { }, false);
|
|
||||||
NetworkServer.RegisterHandler<DisconnectMessage>((conn, msg) => { }, false);
|
|
||||||
NetworkServer.RegisterHandler<ErrorMessage>((conn, msg) => { }, false);
|
|
||||||
NetworkServer.RegisterHandler<SpawnMessage>((conn, msg) => { }, false);
|
|
||||||
NetworkServer.Listen(1);
|
|
||||||
Assert.That(NetworkServer.active, Is.True);
|
|
||||||
|
|
||||||
// add command component
|
|
||||||
NetworkBehaviourSendCommandInternalComponent comp = gameObject.AddComponent<NetworkBehaviourSendCommandInternalComponent>();
|
|
||||||
Assert.That(comp.called, Is.EqualTo(0));
|
|
||||||
|
|
||||||
// create a connection from client to server and from server to client
|
|
||||||
ULocalConnectionToClient connection = new ULocalConnectionToClient
|
|
||||||
{
|
|
||||||
isReady = true,
|
|
||||||
// commands require authentication
|
|
||||||
isAuthenticated = true
|
|
||||||
};
|
|
||||||
connection.connectionToServer = new ULocalConnectionToServer
|
|
||||||
{
|
|
||||||
isReady = true,
|
|
||||||
// commands require authentication
|
|
||||||
isAuthenticated = true
|
|
||||||
};
|
|
||||||
connection.connectionToServer.connectionToClient = connection;
|
|
||||||
identity.connectionToClient = connection;
|
|
||||||
|
|
||||||
// calling command before client is connected shouldn't work
|
|
||||||
// error log is expected
|
|
||||||
LogAssert.ignoreFailingMessages = true;
|
|
||||||
comp.CallSendCommandInternal();
|
|
||||||
LogAssert.ignoreFailingMessages = false;
|
|
||||||
Assert.That(comp.called, Is.EqualTo(0));
|
|
||||||
|
|
||||||
// connect client
|
|
||||||
NetworkClient.Connect("localhost");
|
|
||||||
Assert.That(NetworkClient.active, Is.True);
|
|
||||||
|
|
||||||
// calling command before we have authority should fail
|
|
||||||
// error log is expected
|
|
||||||
LogAssert.ignoreFailingMessages = true;
|
|
||||||
comp.CallSendCommandInternal();
|
|
||||||
LogAssert.ignoreFailingMessages = false;
|
|
||||||
Assert.That(comp.called, Is.EqualTo(0));
|
|
||||||
|
|
||||||
// give authority so we can call commands
|
|
||||||
identity.netId = 42;
|
|
||||||
identity.hasAuthority = true;
|
|
||||||
Assert.That(identity.hasAuthority, Is.True);
|
|
||||||
|
|
||||||
// isClient needs to be true, otherwise we can't call commands
|
|
||||||
identity.isClient = true;
|
|
||||||
|
|
||||||
// register our connection at the server so that it sets up the
|
|
||||||
// connection's handlers
|
|
||||||
NetworkServer.AddConnection(connection);
|
|
||||||
|
|
||||||
// register the command delegate, otherwise it's not found
|
|
||||||
int registeredHash = RemoteCallHelper.RegisterDelegate(typeof(NetworkBehaviourSendCommandInternalComponent),
|
|
||||||
nameof(NetworkBehaviourSendCommandInternalComponent.CommandGenerated),
|
|
||||||
MirrorInvokeType.Command,
|
|
||||||
NetworkBehaviourSendCommandInternalComponent.CommandGenerated,
|
|
||||||
false);
|
|
||||||
|
|
||||||
// identity needs to be in spawned dict, otherwise command handler
|
|
||||||
// won't find it
|
|
||||||
NetworkIdentity.spawned[identity.netId] = identity;
|
|
||||||
|
|
||||||
// calling command before clientscene has ready connection shouldn't work
|
|
||||||
// error log is expected
|
|
||||||
LogAssert.ignoreFailingMessages = true;
|
|
||||||
comp.CallSendCommandInternal();
|
|
||||||
LogAssert.ignoreFailingMessages = false;
|
|
||||||
Assert.That(comp.called, Is.EqualTo(0));
|
|
||||||
|
|
||||||
// clientscene.readyconnection needs to be set for commands
|
|
||||||
ClientScene.Ready(connection.connectionToServer);
|
|
||||||
|
|
||||||
// call command
|
|
||||||
comp.CallSendCommandInternal();
|
|
||||||
Assert.That(comp.called, Is.EqualTo(1));
|
|
||||||
|
|
||||||
// clean up
|
|
||||||
RemoteCallHelper.RemoveDelegate(registeredHash);
|
|
||||||
// clear clientscene.readyconnection
|
|
||||||
ClientScene.Shutdown();
|
|
||||||
NetworkClient.Shutdown();
|
|
||||||
NetworkServer.Shutdown();
|
|
||||||
Transport.activeTransport = null;
|
|
||||||
GameObject.DestroyImmediate(transportGO);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void SendRPCInternal()
|
|
||||||
{
|
|
||||||
// add rpc component
|
|
||||||
NetworkBehaviourSendRPCInternalComponent comp = gameObject.AddComponent<NetworkBehaviourSendRPCInternalComponent>();
|
|
||||||
Assert.That(comp.called, Is.EqualTo(0));
|
|
||||||
|
|
||||||
// transport is needed by server and client.
|
|
||||||
// it needs to be on a gameobject because client.connect enables it,
|
|
||||||
// which throws a NRE if not on a gameobject
|
|
||||||
GameObject transportGO = new GameObject();
|
|
||||||
Transport.activeTransport = transportGO.AddComponent<MemoryTransport>();
|
|
||||||
|
|
||||||
// calling rpc before server is active shouldn't work
|
|
||||||
LogAssert.Expect(LogType.Error, "RPC Function " + nameof(NetworkBehaviourSendRPCInternalComponent.RPCGenerated) + " called on Client.");
|
|
||||||
comp.CallSendRPCInternal();
|
|
||||||
Assert.That(comp.called, Is.EqualTo(0));
|
|
||||||
|
|
||||||
// we need to start a server and connect a client in order to be
|
|
||||||
// able to send commands
|
|
||||||
// message handlers
|
|
||||||
NetworkServer.RegisterHandler<ConnectMessage>((conn, msg) => { }, false);
|
|
||||||
NetworkServer.RegisterHandler<DisconnectMessage>((conn, msg) => { }, false);
|
|
||||||
NetworkServer.RegisterHandler<ErrorMessage>((conn, msg) => { }, false);
|
|
||||||
NetworkServer.RegisterHandler<SpawnMessage>((conn, msg) => { }, false);
|
|
||||||
NetworkServer.Listen(1);
|
|
||||||
Assert.That(NetworkServer.active, Is.True);
|
|
||||||
|
|
||||||
// connect host client
|
|
||||||
NetworkClient.ConnectHost();
|
|
||||||
Assert.That(NetworkClient.active, Is.True);
|
|
||||||
|
|
||||||
// get the host connection which already has client->server and
|
|
||||||
// server->client set up
|
|
||||||
ULocalConnectionToServer connectionToServer = (ULocalConnectionToServer)NetworkClient.connection;
|
|
||||||
|
|
||||||
// set host connection as ready and authenticated
|
|
||||||
connectionToServer.isReady = true;
|
|
||||||
connectionToServer.isAuthenticated = true;
|
|
||||||
connectionToServer.connectionToClient.isReady = true;
|
|
||||||
connectionToServer.connectionToClient.isAuthenticated = true;
|
|
||||||
connectionToServer.connectionToClient.identity = identity;
|
|
||||||
|
|
||||||
// calling rpc before isServer is true shouldn't work
|
|
||||||
LogAssert.Expect(LogType.Warning, "ClientRpc " + nameof(NetworkBehaviourSendRPCInternalComponent.RPCGenerated) + " called on un-spawned object: " + gameObject.name);
|
|
||||||
comp.CallSendRPCInternal();
|
|
||||||
Assert.That(comp.called, Is.EqualTo(0));
|
|
||||||
|
|
||||||
// we need an observer because sendrpc sends to ready observers
|
|
||||||
// creates observers
|
|
||||||
identity.OnStartServer();
|
|
||||||
identity.observers[connectionToServer.connectionToClient.connectionId] = connectionToServer.connectionToClient;
|
|
||||||
|
|
||||||
// isServer needs to be true, otherwise we can't call rpcs
|
|
||||||
Assert.That(comp.isServer, Is.True);
|
|
||||||
|
|
||||||
// register the command delegate, otherwise it's not found
|
|
||||||
int registeredHash = RemoteCallHelper.RegisterDelegate(typeof(NetworkBehaviourSendRPCInternalComponent),
|
|
||||||
nameof(NetworkBehaviourSendRPCInternalComponent.RPCGenerated),
|
|
||||||
MirrorInvokeType.ClientRpc,
|
|
||||||
NetworkBehaviourSendRPCInternalComponent.RPCGenerated);
|
|
||||||
|
|
||||||
// identity needs to be in spawned dict, otherwise rpc handler
|
|
||||||
// won't find it
|
|
||||||
NetworkIdentity.spawned[identity.netId] = identity;
|
|
||||||
|
|
||||||
// call rpc
|
|
||||||
comp.CallSendRPCInternal();
|
|
||||||
|
|
||||||
// update client's connection so that pending messages are processed
|
|
||||||
connectionToServer.Update();
|
|
||||||
|
|
||||||
// rpc should have been called now
|
|
||||||
Assert.That(comp.called, Is.EqualTo(1));
|
|
||||||
|
|
||||||
// clean up
|
|
||||||
RemoteCallHelper.RemoveDelegate(registeredHash);
|
|
||||||
// clear clientscene.readyconnection
|
|
||||||
ClientScene.Shutdown();
|
|
||||||
NetworkServer.RemoveLocalConnection();
|
|
||||||
NetworkClient.Shutdown();
|
|
||||||
NetworkServer.Shutdown();
|
|
||||||
Transport.activeTransport = null;
|
|
||||||
GameObject.DestroyImmediate(transportGO);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void SendTargetRPCInternal()
|
|
||||||
{
|
|
||||||
// add rpc component
|
|
||||||
NetworkBehaviourSendTargetRPCInternalComponent comp = gameObject.AddComponent<NetworkBehaviourSendTargetRPCInternalComponent>();
|
|
||||||
Assert.That(comp.called, Is.EqualTo(0));
|
|
||||||
|
|
||||||
// transport is needed by server and client.
|
|
||||||
// it needs to be on a gameobject because client.connect enables it,
|
|
||||||
// which throws a NRE if not on a gameobject
|
|
||||||
GameObject transportGO = new GameObject();
|
|
||||||
Transport.activeTransport = transportGO.AddComponent<MemoryTransport>();
|
|
||||||
|
|
||||||
// calling rpc before server is active shouldn't work
|
|
||||||
LogAssert.Expect(LogType.Error, "TargetRPC Function " + nameof(NetworkBehaviourSendTargetRPCInternalComponent.TargetRPCGenerated) + " called on client.");
|
|
||||||
comp.CallSendTargetRPCInternal(null);
|
|
||||||
Assert.That(comp.called, Is.EqualTo(0));
|
|
||||||
|
|
||||||
// we need to start a server and connect a client in order to be
|
|
||||||
// able to send commands
|
|
||||||
// message handlers
|
|
||||||
NetworkServer.RegisterHandler<ConnectMessage>((conn, msg) => { }, false);
|
|
||||||
NetworkServer.RegisterHandler<DisconnectMessage>((conn, msg) => { }, false);
|
|
||||||
NetworkServer.RegisterHandler<ErrorMessage>((conn, msg) => { }, false);
|
|
||||||
NetworkServer.RegisterHandler<SpawnMessage>((conn, msg) => { }, false);
|
|
||||||
NetworkServer.Listen(1);
|
|
||||||
Assert.That(NetworkServer.active, Is.True);
|
|
||||||
|
|
||||||
// connect host client
|
|
||||||
NetworkClient.ConnectHost();
|
|
||||||
Assert.That(NetworkClient.active, Is.True);
|
|
||||||
|
|
||||||
// get the host connection which already has client->server and
|
|
||||||
// server->client set up
|
|
||||||
ULocalConnectionToServer connectionToServer = (ULocalConnectionToServer)NetworkClient.connection;
|
|
||||||
|
|
||||||
// set host connection as ready and authenticated
|
|
||||||
connectionToServer.isReady = true;
|
|
||||||
connectionToServer.isAuthenticated = true;
|
|
||||||
connectionToServer.connectionToClient.isReady = true;
|
|
||||||
connectionToServer.connectionToClient.isAuthenticated = true;
|
|
||||||
connectionToServer.connectionToClient.identity = identity;
|
|
||||||
|
|
||||||
// calling rpc before isServer is true shouldn't work
|
|
||||||
LogAssert.Expect(LogType.Warning, "TargetRpc " + nameof(NetworkBehaviourSendTargetRPCInternalComponent.TargetRPCGenerated) + " called on un-spawned object: " + gameObject.name);
|
|
||||||
comp.CallSendTargetRPCInternal(null);
|
|
||||||
Assert.That(comp.called, Is.EqualTo(0));
|
|
||||||
|
|
||||||
// call OnStartServer so isServer is true
|
|
||||||
identity.OnStartServer();
|
|
||||||
|
|
||||||
// calling rpc on connectionToServer shouldn't work
|
|
||||||
LogAssert.Expect(LogType.Error, "TargetRPC Function " + nameof(NetworkBehaviourSendTargetRPCInternalComponent.TargetRPCGenerated) + " called on connection to server");
|
|
||||||
comp.CallSendTargetRPCInternal(new NetworkConnectionToServer());
|
|
||||||
Assert.That(comp.called, Is.EqualTo(0));
|
|
||||||
|
|
||||||
// set proper connection to client
|
|
||||||
identity.connectionToClient = connectionToServer.connectionToClient;
|
|
||||||
|
|
||||||
// isServer needs to be true, otherwise we can't call rpcs
|
|
||||||
Assert.That(comp.isServer, Is.True);
|
|
||||||
|
|
||||||
// register the command delegate, otherwise it's not found
|
|
||||||
int registeredHash = RemoteCallHelper.RegisterDelegate(typeof(NetworkBehaviourSendTargetRPCInternalComponent),
|
|
||||||
nameof(NetworkBehaviourSendTargetRPCInternalComponent.TargetRPCGenerated),
|
|
||||||
MirrorInvokeType.ClientRpc,
|
|
||||||
NetworkBehaviourSendTargetRPCInternalComponent.TargetRPCGenerated);
|
|
||||||
|
|
||||||
// identity needs to be in spawned dict, otherwise rpc handler
|
|
||||||
// won't find it
|
|
||||||
NetworkIdentity.spawned[identity.netId] = identity;
|
|
||||||
|
|
||||||
// call rpc
|
|
||||||
comp.CallSendTargetRPCInternal(null);
|
|
||||||
|
|
||||||
// update client's connection so that pending messages are processed
|
|
||||||
connectionToServer.Update();
|
|
||||||
|
|
||||||
// rpc should have been called now
|
|
||||||
Assert.That(comp.called, Is.EqualTo(1));
|
|
||||||
|
|
||||||
// clean up
|
|
||||||
RemoteCallHelper.RemoveDelegate(registeredHash);
|
|
||||||
// clear clientscene.readyconnection
|
|
||||||
ClientScene.Shutdown();
|
|
||||||
NetworkServer.RemoveLocalConnection();
|
|
||||||
NetworkClient.Shutdown();
|
|
||||||
NetworkServer.Shutdown();
|
|
||||||
Transport.activeTransport = null;
|
|
||||||
GameObject.DestroyImmediate(transportGO);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void RegisterDelegateDoesntOverwrite()
|
public void RegisterDelegateDoesntOverwrite()
|
||||||
{
|
{
|
||||||
@ -1064,31 +767,6 @@ public void OnStartLocalPlayer()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// we need to inherit from networkbehaviour to test protected functions
|
|
||||||
public class NetworkBehaviourHookGuardTester : NetworkBehaviour
|
|
||||||
{
|
|
||||||
[Test]
|
|
||||||
public void HookGuard()
|
|
||||||
{
|
|
||||||
// set hook guard for some bits
|
|
||||||
for (int i = 0; i < 10; ++i)
|
|
||||||
{
|
|
||||||
ulong bit = 1ul << i;
|
|
||||||
|
|
||||||
// should be false by default
|
|
||||||
Assert.That(getSyncVarHookGuard(bit), Is.False);
|
|
||||||
|
|
||||||
// set true
|
|
||||||
setSyncVarHookGuard(bit, true);
|
|
||||||
Assert.That(getSyncVarHookGuard(bit), Is.True);
|
|
||||||
|
|
||||||
// set false again
|
|
||||||
setSyncVarHookGuard(bit, false);
|
|
||||||
Assert.That(getSyncVarHookGuard(bit), Is.False);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// we need to inherit from networkbehaviour to test protected functions
|
// we need to inherit from networkbehaviour to test protected functions
|
||||||
public class NetworkBehaviourInitSyncObjectTester : NetworkBehaviour
|
public class NetworkBehaviourInitSyncObjectTester : NetworkBehaviour
|
||||||
{
|
{
|
||||||
|
@ -35,21 +35,6 @@ public void TearDown()
|
|||||||
Transport.activeTransport = null;
|
Transport.activeTransport = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void serverIp()
|
|
||||||
{
|
|
||||||
NetworkClient.ConnectHost();
|
|
||||||
Assert.That(NetworkClient.serverIp, Is.EqualTo("localhost"));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void isConnected()
|
|
||||||
{
|
|
||||||
Assert.That(NetworkClient.isConnected, Is.False);
|
|
||||||
NetworkClient.ConnectHost();
|
|
||||||
Assert.That(NetworkClient.isConnected, Is.True);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void ConnectUri()
|
public void ConnectUri()
|
||||||
{
|
{
|
||||||
@ -59,18 +44,6 @@ public void ConnectUri()
|
|||||||
Assert.That(NetworkClient.isConnected, Is.True);
|
Assert.That(NetworkClient.isConnected, Is.True);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void DisconnectInHostMode()
|
|
||||||
{
|
|
||||||
NetworkClient.ConnectHost();
|
|
||||||
Assert.That(NetworkClient.isConnected, Is.True);
|
|
||||||
Assert.That(NetworkServer.localConnection, !Is.Null);
|
|
||||||
|
|
||||||
NetworkClient.Disconnect();
|
|
||||||
Assert.That(NetworkClient.isConnected, Is.False);
|
|
||||||
Assert.That(NetworkServer.localConnection, Is.Null);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void Send()
|
public void Send()
|
||||||
{
|
{
|
||||||
|
@ -121,33 +121,6 @@ public override void OnStopServer()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SetHostVisibilityExceptionNetworkBehaviour : NetworkVisibility
|
|
||||||
{
|
|
||||||
public int called;
|
|
||||||
public bool valuePassed;
|
|
||||||
public override void OnRebuildObservers(HashSet<NetworkConnection> observers, bool initialize) { }
|
|
||||||
public override bool OnCheckObserver(NetworkConnection conn) { return true; }
|
|
||||||
public override void OnSetHostVisibility(bool visible)
|
|
||||||
{
|
|
||||||
++called;
|
|
||||||
valuePassed = visible;
|
|
||||||
throw new Exception("some exception");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class SetHostVisibilityNetworkBehaviour : NetworkVisibility
|
|
||||||
{
|
|
||||||
public int called;
|
|
||||||
public override void OnRebuildObservers(HashSet<NetworkConnection> observers, bool initialize) { }
|
|
||||||
public override bool OnCheckObserver(NetworkConnection conn) { return true; }
|
|
||||||
public override void OnSetHostVisibility(bool visible)
|
|
||||||
{
|
|
||||||
++called;
|
|
||||||
base.OnSetHostVisibility(visible);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class CheckObserverExceptionNetworkBehaviour : NetworkVisibility
|
class CheckObserverExceptionNetworkBehaviour : NetworkVisibility
|
||||||
{
|
{
|
||||||
public int called;
|
public int called;
|
||||||
@ -159,7 +132,6 @@ public override bool OnCheckObserver(NetworkConnection conn)
|
|||||||
valuePassed = conn;
|
valuePassed = conn;
|
||||||
throw new Exception("some exception");
|
throw new Exception("some exception");
|
||||||
}
|
}
|
||||||
public override void OnSetHostVisibility(bool visible) { }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class CheckObserverTrueNetworkBehaviour : NetworkVisibility
|
class CheckObserverTrueNetworkBehaviour : NetworkVisibility
|
||||||
@ -171,7 +143,6 @@ public override bool OnCheckObserver(NetworkConnection conn)
|
|||||||
++called;
|
++called;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
public override void OnSetHostVisibility(bool visible) { }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class CheckObserverFalseNetworkBehaviour : NetworkVisibility
|
class CheckObserverFalseNetworkBehaviour : NetworkVisibility
|
||||||
@ -183,7 +154,6 @@ public override bool OnCheckObserver(NetworkConnection conn)
|
|||||||
++called;
|
++called;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
public override void OnSetHostVisibility(bool visible) { }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SerializeTest1NetworkBehaviour : NetworkBehaviour
|
class SerializeTest1NetworkBehaviour : NetworkBehaviour
|
||||||
@ -250,20 +220,12 @@ public override void OnRebuildObservers(HashSet<NetworkConnection> observers, bo
|
|||||||
{
|
{
|
||||||
observers.Add(observer);
|
observers.Add(observer);
|
||||||
}
|
}
|
||||||
public override void OnSetHostVisibility(bool visible) { }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class RebuildEmptyObserversNetworkBehaviour : NetworkVisibility
|
class RebuildEmptyObserversNetworkBehaviour : NetworkVisibility
|
||||||
{
|
{
|
||||||
public override bool OnCheckObserver(NetworkConnection conn) { return true; }
|
public override bool OnCheckObserver(NetworkConnection conn) { return true; }
|
||||||
public override void OnRebuildObservers(HashSet<NetworkConnection> observers, bool initialize) { }
|
public override void OnRebuildObservers(HashSet<NetworkConnection> observers, bool initialize) { }
|
||||||
public int hostVisibilityCalled;
|
|
||||||
public bool hostVisibilityValue;
|
|
||||||
public override void OnSetHostVisibility(bool visible)
|
|
||||||
{
|
|
||||||
++hostVisibilityCalled;
|
|
||||||
hostVisibilityValue = visible;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class IsClientServerCheckComponent : NetworkBehaviour
|
class IsClientServerCheckComponent : NetworkBehaviour
|
||||||
@ -389,42 +351,6 @@ public void ServerMode_IsFlags_Test()
|
|||||||
NetworkIdentity.spawned.Clear();
|
NetworkIdentity.spawned.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// check isClient/isServer/isLocalPlayer in host mode
|
|
||||||
[Test]
|
|
||||||
public void HostMode_IsFlags_Test()
|
|
||||||
{
|
|
||||||
// start the server
|
|
||||||
NetworkServer.Listen(1000);
|
|
||||||
|
|
||||||
// start the client
|
|
||||||
NetworkClient.ConnectHost();
|
|
||||||
|
|
||||||
// add component
|
|
||||||
IsClientServerCheckComponent component = gameObject.AddComponent<IsClientServerCheckComponent>();
|
|
||||||
|
|
||||||
// set is as local player
|
|
||||||
ClientScene.InternalAddPlayer(identity);
|
|
||||||
|
|
||||||
// spawn it
|
|
||||||
NetworkServer.Spawn(gameObject);
|
|
||||||
|
|
||||||
// OnStartServer should have been called. check the flags.
|
|
||||||
Assert.That(component.OnStartServer_isClient, Is.EqualTo(true));
|
|
||||||
Assert.That(component.OnStartServer_isLocalPlayer, Is.EqualTo(true));
|
|
||||||
Assert.That(component.OnStartServer_isServer, Is.EqualTo(true));
|
|
||||||
|
|
||||||
// stop the client
|
|
||||||
NetworkClient.Shutdown();
|
|
||||||
NetworkServer.RemoveLocalConnection();
|
|
||||||
ClientScene.Shutdown();
|
|
||||||
|
|
||||||
// stop the server
|
|
||||||
NetworkServer.Shutdown();
|
|
||||||
|
|
||||||
// clean up
|
|
||||||
NetworkIdentity.spawned.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void GetSetAssetId()
|
public void GetSetAssetId()
|
||||||
{
|
{
|
||||||
@ -486,23 +412,6 @@ public void SetAssetId_DoesNotGiveErrorIfBothOldAndNewAreEmpty()
|
|||||||
Assert.That(identity.assetId, Is.EqualTo(Guid.Empty));
|
Assert.That(identity.assetId, Is.EqualTo(Guid.Empty));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void SetClientOwner()
|
|
||||||
{
|
|
||||||
// SetClientOwner
|
|
||||||
ULocalConnectionToClient original = new ULocalConnectionToClient();
|
|
||||||
identity.SetClientOwner(original);
|
|
||||||
Assert.That(identity.connectionToClient, Is.EqualTo(original));
|
|
||||||
|
|
||||||
// setting it when it's already set shouldn't overwrite the original
|
|
||||||
ULocalConnectionToClient overwrite = new ULocalConnectionToClient();
|
|
||||||
// will log a warning
|
|
||||||
LogAssert.ignoreFailingMessages = true;
|
|
||||||
identity.SetClientOwner(overwrite);
|
|
||||||
Assert.That(identity.connectionToClient, Is.EqualTo(original));
|
|
||||||
LogAssert.ignoreFailingMessages = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void RemoveObserverInternal()
|
public void RemoveObserverInternal()
|
||||||
{
|
{
|
||||||
@ -650,119 +559,6 @@ public void OnStopAuthorityCallsComponentsAndCatchesExceptions()
|
|||||||
LogAssert.ignoreFailingMessages = false;
|
LogAssert.ignoreFailingMessages = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void AssignAndRemoveClientAuthority()
|
|
||||||
{
|
|
||||||
// test the callback too
|
|
||||||
int callbackCalled = 0;
|
|
||||||
NetworkConnection callbackConnection = null;
|
|
||||||
NetworkIdentity callbackIdentity = null;
|
|
||||||
bool callbackState = false;
|
|
||||||
NetworkIdentity.clientAuthorityCallback += (conn, networkIdentity, state) =>
|
|
||||||
{
|
|
||||||
++callbackCalled;
|
|
||||||
callbackConnection = conn;
|
|
||||||
callbackIdentity = identity;
|
|
||||||
callbackState = state;
|
|
||||||
};
|
|
||||||
|
|
||||||
// create a connection
|
|
||||||
ULocalConnectionToClient owner = new ULocalConnectionToClient();
|
|
||||||
owner.isReady = true;
|
|
||||||
// add client handlers
|
|
||||||
owner.connectionToServer = new ULocalConnectionToServer();
|
|
||||||
int spawnCalled = 0;
|
|
||||||
owner.connectionToServer.SetHandlers(new Dictionary<int, NetworkMessageDelegate>{
|
|
||||||
{ MessagePacker.GetId<SpawnMessage>(), ((conn, reader, channelId) => ++spawnCalled) }
|
|
||||||
});
|
|
||||||
|
|
||||||
// assigning authority should only work on server.
|
|
||||||
// if isServer is false because server isn't running yet then it
|
|
||||||
// should fail.
|
|
||||||
// error log is expected
|
|
||||||
LogAssert.ignoreFailingMessages = true;
|
|
||||||
bool result = identity.AssignClientAuthority(owner);
|
|
||||||
LogAssert.ignoreFailingMessages = false;
|
|
||||||
Assert.That(result, Is.False);
|
|
||||||
|
|
||||||
// server is needed
|
|
||||||
NetworkServer.Listen(1);
|
|
||||||
|
|
||||||
// call OnStartServer so that isServer is true
|
|
||||||
identity.OnStartServer();
|
|
||||||
Assert.That(identity.isServer, Is.True);
|
|
||||||
|
|
||||||
// assign authority
|
|
||||||
result = identity.AssignClientAuthority(owner);
|
|
||||||
Assert.That(result, Is.True);
|
|
||||||
Assert.That(identity.connectionToClient, Is.EqualTo(owner));
|
|
||||||
Assert.That(callbackCalled, Is.EqualTo(1));
|
|
||||||
Assert.That(callbackConnection, Is.EqualTo(owner));
|
|
||||||
Assert.That(callbackIdentity, Is.EqualTo(identity));
|
|
||||||
Assert.That(callbackState, Is.EqualTo(true));
|
|
||||||
|
|
||||||
// assigning authority should respawn the object with proper authority
|
|
||||||
// on the client. that's the best way to sync the new state right now.
|
|
||||||
// process pending messages
|
|
||||||
owner.connectionToServer.Update();
|
|
||||||
Assert.That(spawnCalled, Is.EqualTo(1));
|
|
||||||
|
|
||||||
// shouldn't be able to assign authority while already owned by
|
|
||||||
// another connection
|
|
||||||
// error log is expected
|
|
||||||
LogAssert.ignoreFailingMessages = true;
|
|
||||||
result = identity.AssignClientAuthority(new NetworkConnectionToClient(43));
|
|
||||||
LogAssert.ignoreFailingMessages = false;
|
|
||||||
Assert.That(result, Is.False);
|
|
||||||
Assert.That(identity.connectionToClient, Is.EqualTo(owner));
|
|
||||||
Assert.That(callbackCalled, Is.EqualTo(1));
|
|
||||||
|
|
||||||
// someone might try to remove authority by assigning null.
|
|
||||||
// make sure this fails.
|
|
||||||
// error log is expected
|
|
||||||
LogAssert.ignoreFailingMessages = true;
|
|
||||||
result = identity.AssignClientAuthority(null);
|
|
||||||
LogAssert.ignoreFailingMessages = false;
|
|
||||||
Assert.That(result, Is.False);
|
|
||||||
|
|
||||||
// removing authority while not isServer shouldn't work.
|
|
||||||
// only allow it on server.
|
|
||||||
identity.isServer = false;
|
|
||||||
|
|
||||||
// error log is expected
|
|
||||||
LogAssert.ignoreFailingMessages = true;
|
|
||||||
identity.RemoveClientAuthority();
|
|
||||||
LogAssert.ignoreFailingMessages = false;
|
|
||||||
Assert.That(identity.connectionToClient, Is.EqualTo(owner));
|
|
||||||
Assert.That(callbackCalled, Is.EqualTo(1));
|
|
||||||
|
|
||||||
// enable isServer again
|
|
||||||
identity.isServer = true;
|
|
||||||
|
|
||||||
// removing authority for the main player object shouldn't work
|
|
||||||
// set connection's player object
|
|
||||||
owner.identity = identity;
|
|
||||||
// error log is expected
|
|
||||||
LogAssert.ignoreFailingMessages = true;
|
|
||||||
identity.RemoveClientAuthority();
|
|
||||||
LogAssert.ignoreFailingMessages = false;
|
|
||||||
Assert.That(identity.connectionToClient, Is.EqualTo(owner));
|
|
||||||
Assert.That(callbackCalled, Is.EqualTo(1));
|
|
||||||
|
|
||||||
// removing authority for a non-main-player object should work
|
|
||||||
owner.identity = null;
|
|
||||||
identity.RemoveClientAuthority();
|
|
||||||
Assert.That(identity.connectionToClient, Is.Null);
|
|
||||||
Assert.That(callbackCalled, Is.EqualTo(2));
|
|
||||||
// the one that was removed
|
|
||||||
Assert.That(callbackConnection, Is.EqualTo(owner));
|
|
||||||
Assert.That(callbackIdentity, Is.EqualTo(identity));
|
|
||||||
Assert.That(callbackState, Is.EqualTo(false));
|
|
||||||
|
|
||||||
// clean up
|
|
||||||
NetworkServer.Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void NotifyAuthorityCallsOnStartStopAuthority()
|
public void NotifyAuthorityCallsOnStartStopAuthority()
|
||||||
{
|
{
|
||||||
@ -811,33 +607,6 @@ public void NotifyAuthorityCallsOnStartStopAuthority()
|
|||||||
Assert.That(compStop.called, Is.EqualTo(1));
|
Assert.That(compStop.called, Is.EqualTo(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void OnSetHostVisibilityCallsComponentsAndCatchesExceptions()
|
|
||||||
{
|
|
||||||
// add component
|
|
||||||
SetHostVisibilityExceptionNetworkBehaviour comp = gameObject.AddComponent<SetHostVisibilityExceptionNetworkBehaviour>();
|
|
||||||
|
|
||||||
// make sure that comp.OnSetHostVisibility was called and make sure that
|
|
||||||
// the exception was caught and not thrown in here.
|
|
||||||
// an exception in OnSetHostVisibility should be caught, so that one
|
|
||||||
// component's exception doesn't stop all other components from
|
|
||||||
// being initialized
|
|
||||||
// (an error log is expected though)
|
|
||||||
LogAssert.ignoreFailingMessages = true;
|
|
||||||
|
|
||||||
// should catch the exception internally and not throw it
|
|
||||||
identity.OnSetHostVisibility(true);
|
|
||||||
Assert.That(comp.called, Is.EqualTo(1));
|
|
||||||
Assert.That(comp.valuePassed, Is.True);
|
|
||||||
|
|
||||||
// should catch the exception internally and not throw it
|
|
||||||
identity.OnSetHostVisibility(false);
|
|
||||||
Assert.That(comp.called, Is.EqualTo(2));
|
|
||||||
Assert.That(comp.valuePassed, Is.False);
|
|
||||||
|
|
||||||
LogAssert.ignoreFailingMessages = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnStartServer in host mode should set isClient=true
|
// OnStartServer in host mode should set isClient=true
|
||||||
[Test]
|
[Test]
|
||||||
public void OnStartServerInHostModeSetsIsClientTrue()
|
public void OnStartServerInHostModeSetsIsClientTrue()
|
||||||
@ -1367,83 +1136,6 @@ public void HandleRpc()
|
|||||||
RemoteCallHelper.RemoveDelegate(registeredHash);
|
RemoteCallHelper.RemoveDelegate(registeredHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ServerUpdate()
|
|
||||||
{
|
|
||||||
// add components
|
|
||||||
SerializeTest1NetworkBehaviour compA = gameObject.AddComponent<SerializeTest1NetworkBehaviour>();
|
|
||||||
// test value
|
|
||||||
compA.value = 1337;
|
|
||||||
// set syncInterval so IsDirty passes the interval check
|
|
||||||
compA.syncInterval = 0;
|
|
||||||
// one needs to sync to owner
|
|
||||||
compA.syncMode = SyncMode.Owner;
|
|
||||||
SerializeTest2NetworkBehaviour compB = gameObject.AddComponent<SerializeTest2NetworkBehaviour>();
|
|
||||||
// test value
|
|
||||||
compB.value = "test";
|
|
||||||
// set syncInterval so IsDirty passes the interval check
|
|
||||||
compB.syncInterval = 0;
|
|
||||||
// one needs to sync to owner
|
|
||||||
compB.syncMode = SyncMode.Observers;
|
|
||||||
|
|
||||||
// call OnStartServer once so observers are created
|
|
||||||
identity.OnStartServer();
|
|
||||||
|
|
||||||
// set it dirty
|
|
||||||
compA.SetDirtyBit(ulong.MaxValue);
|
|
||||||
compB.SetDirtyBit(ulong.MaxValue);
|
|
||||||
Assert.That(compA.IsDirty(), Is.True);
|
|
||||||
Assert.That(compB.IsDirty(), Is.True);
|
|
||||||
|
|
||||||
// calling update without observers should clear all dirty bits.
|
|
||||||
// it would be spawned on new observers anyway.
|
|
||||||
identity.ServerUpdate();
|
|
||||||
Assert.That(compA.IsDirty(), Is.False);
|
|
||||||
Assert.That(compB.IsDirty(), Is.False);
|
|
||||||
|
|
||||||
// add an owner connection that will receive the updates
|
|
||||||
ULocalConnectionToClient owner = new ULocalConnectionToClient();
|
|
||||||
// for syncing
|
|
||||||
owner.isReady = true;
|
|
||||||
// add a client to server connection + handler to receive syncs
|
|
||||||
owner.connectionToServer = new ULocalConnectionToServer();
|
|
||||||
int ownerCalled = 0;
|
|
||||||
owner.connectionToServer.SetHandlers(new Dictionary<int, NetworkMessageDelegate>
|
|
||||||
{
|
|
||||||
{ MessagePacker.GetId<UpdateVarsMessage>(), ((conn, reader, channelId) => ++ownerCalled) }
|
|
||||||
});
|
|
||||||
identity.connectionToClient = owner;
|
|
||||||
|
|
||||||
// add an observer connection that will receive the updates
|
|
||||||
ULocalConnectionToClient observer = new ULocalConnectionToClient();
|
|
||||||
// we only sync to ready observers
|
|
||||||
observer.isReady = true;
|
|
||||||
// add a client to server connection + handler to receive syncs
|
|
||||||
observer.connectionToServer = new ULocalConnectionToServer();
|
|
||||||
int observerCalled = 0;
|
|
||||||
observer.connectionToServer.SetHandlers(new Dictionary<int, NetworkMessageDelegate>
|
|
||||||
{
|
|
||||||
{ MessagePacker.GetId<UpdateVarsMessage>(), ((conn, reader, channelId) => ++observerCalled) }
|
|
||||||
});
|
|
||||||
identity.observers[observer.connectionId] = observer;
|
|
||||||
|
|
||||||
// set components dirty again
|
|
||||||
compA.SetDirtyBit(ulong.MaxValue);
|
|
||||||
compB.SetDirtyBit(ulong.MaxValue);
|
|
||||||
|
|
||||||
// calling update should serialize all components and send them to
|
|
||||||
// owner/observers
|
|
||||||
identity.ServerUpdate();
|
|
||||||
|
|
||||||
// update connections once so that messages are processed
|
|
||||||
owner.connectionToServer.Update();
|
|
||||||
observer.connectionToServer.Update();
|
|
||||||
|
|
||||||
// was it received on the clients?
|
|
||||||
Assert.That(ownerCalled, Is.EqualTo(1));
|
|
||||||
Assert.That(observerCalled, Is.EqualTo(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void GetNewObservers()
|
public void GetNewObservers()
|
||||||
{
|
{
|
||||||
@ -1479,78 +1171,6 @@ public void GetNewObserversFalseIfNoComponents()
|
|||||||
Assert.That(result, Is.False);
|
Assert.That(result, Is.False);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void AddAllReadyServerConnectionsToObservers()
|
|
||||||
{
|
|
||||||
// add some server connections
|
|
||||||
NetworkServer.connections[12] = new NetworkConnectionToClient(12) { isReady = true };
|
|
||||||
NetworkServer.connections[13] = new NetworkConnectionToClient(13) { isReady = false };
|
|
||||||
|
|
||||||
// add a host connection
|
|
||||||
ULocalConnectionToClient localConnection = new ULocalConnectionToClient();
|
|
||||||
localConnection.connectionToServer = new ULocalConnectionToServer();
|
|
||||||
localConnection.isReady = true;
|
|
||||||
NetworkServer.SetLocalConnection(localConnection);
|
|
||||||
|
|
||||||
// call OnStartServer so that observers dict is created
|
|
||||||
identity.OnStartServer();
|
|
||||||
|
|
||||||
// add all to observers. should have the two ready connections then.
|
|
||||||
identity.AddAllReadyServerConnectionsToObservers();
|
|
||||||
Assert.That(identity.observers.Count, Is.EqualTo(2));
|
|
||||||
Assert.That(identity.observers.ContainsKey(12));
|
|
||||||
Assert.That(identity.observers.ContainsKey(NetworkServer.localConnection.connectionId));
|
|
||||||
|
|
||||||
// clean up
|
|
||||||
NetworkServer.RemoveLocalConnection();
|
|
||||||
NetworkServer.Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
// RebuildObservers should always add the own ready connection
|
|
||||||
// (if any). fixes https://github.com/vis2k/Mirror/issues/692
|
|
||||||
[Test]
|
|
||||||
public void RebuildObserversAddsOwnReadyPlayer()
|
|
||||||
{
|
|
||||||
// add at least one observers component, otherwise it will just add
|
|
||||||
// all server connections
|
|
||||||
gameObject.AddComponent<RebuildEmptyObserversNetworkBehaviour>();
|
|
||||||
|
|
||||||
// add own player connection
|
|
||||||
ULocalConnectionToClient connection = new ULocalConnectionToClient();
|
|
||||||
connection.connectionToServer = new ULocalConnectionToServer();
|
|
||||||
connection.isReady = true;
|
|
||||||
identity.connectionToClient = connection;
|
|
||||||
|
|
||||||
// call OnStartServer so that observers dict is created
|
|
||||||
identity.OnStartServer();
|
|
||||||
|
|
||||||
// rebuild should at least add own ready player
|
|
||||||
identity.RebuildObservers(true);
|
|
||||||
Assert.That(identity.observers.ContainsKey(identity.connectionToClient.connectionId));
|
|
||||||
}
|
|
||||||
|
|
||||||
// RebuildObservers should always add the own ready connection
|
|
||||||
// (if any). fixes https://github.com/vis2k/Mirror/issues/692
|
|
||||||
[Test]
|
|
||||||
public void RebuildObserversOnlyAddsOwnPlayerIfReady()
|
|
||||||
{
|
|
||||||
// add at least one observers component, otherwise it will just add
|
|
||||||
// all server connections
|
|
||||||
gameObject.AddComponent<RebuildEmptyObserversNetworkBehaviour>();
|
|
||||||
|
|
||||||
// add own player connection that isn't ready
|
|
||||||
ULocalConnectionToClient connection = new ULocalConnectionToClient();
|
|
||||||
connection.connectionToServer = new ULocalConnectionToServer();
|
|
||||||
identity.connectionToClient = connection;
|
|
||||||
|
|
||||||
// call OnStartServer so that observers dict is created
|
|
||||||
identity.OnStartServer();
|
|
||||||
|
|
||||||
// rebuild shouldn't add own player because conn wasn't set ready
|
|
||||||
identity.RebuildObservers(true);
|
|
||||||
Assert.That(!identity.observers.ContainsKey(identity.connectionToClient.connectionId));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void RebuildObserversAddsReadyConnectionsIfImplemented()
|
public void RebuildObserversAddsReadyConnectionsIfImplemented()
|
||||||
{
|
{
|
||||||
@ -1673,35 +1293,6 @@ public void RebuildObserversAddRemoveAndVisListTest()
|
|||||||
NetworkServer.Shutdown();
|
NetworkServer.Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void RebuildObserversSetsHostVisibility()
|
|
||||||
{
|
|
||||||
// set local connection for host mode
|
|
||||||
ULocalConnectionToClient localConnection = new ULocalConnectionToClient();
|
|
||||||
localConnection.connectionToServer = new ULocalConnectionToServer();
|
|
||||||
localConnection.isReady = true;
|
|
||||||
NetworkServer.SetLocalConnection(localConnection);
|
|
||||||
|
|
||||||
// add at least one observers component, otherwise it will just add
|
|
||||||
// all server connections
|
|
||||||
RebuildEmptyObserversNetworkBehaviour comp = gameObject.AddComponent<RebuildEmptyObserversNetworkBehaviour>();
|
|
||||||
Assert.That(comp.hostVisibilityCalled, Is.EqualTo(0));
|
|
||||||
|
|
||||||
// call OnStartServer so that observers dict is created
|
|
||||||
identity.OnStartServer();
|
|
||||||
|
|
||||||
// rebuild will result in 0 observers. it won't contain host
|
|
||||||
// connection so it should call OnSetHostVisibility(false)
|
|
||||||
identity.RebuildObservers(true);
|
|
||||||
Assert.That(identity.observers.Count, Is.EqualTo(0));
|
|
||||||
Assert.That(comp.hostVisibilityCalled, Is.EqualTo(1));
|
|
||||||
Assert.That(comp.hostVisibilityValue, Is.False);
|
|
||||||
|
|
||||||
// clean up
|
|
||||||
NetworkServer.RemoveLocalConnection();
|
|
||||||
NetworkServer.Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void RebuildObserversReturnsIfNull()
|
public void RebuildObserversReturnsIfNull()
|
||||||
{
|
{
|
||||||
@ -1774,18 +1365,5 @@ public void GetDirtyComponentsMaskShouldReturnZeroWhenNoDirtyComponents()
|
|||||||
|
|
||||||
Assert.That(mask, Is.EqualTo(0UL));
|
Assert.That(mask, Is.EqualTo(0UL));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void OnSetHostVisibilityBaseTest()
|
|
||||||
{
|
|
||||||
SpriteRenderer renderer;
|
|
||||||
|
|
||||||
renderer = gameObject.AddComponent<SpriteRenderer>();
|
|
||||||
SetHostVisibilityNetworkBehaviour comp = gameObject.AddComponent<SetHostVisibilityNetworkBehaviour>();
|
|
||||||
comp.OnSetHostVisibility(false);
|
|
||||||
|
|
||||||
Assert.That(comp.called, Is.EqualTo(1));
|
|
||||||
Assert.That(renderer.enabled, Is.False);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
using NUnit.Framework;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Mirror.Tests
|
|
||||||
{
|
|
||||||
class NetworkManagerOnServerDisconnect : NetworkManager
|
|
||||||
{
|
|
||||||
public int called;
|
|
||||||
public override void OnServerDisconnect(NetworkConnection conn) { ++called; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestFixture]
|
|
||||||
public class NetworkManagerStopHostOnServerDisconnectTest
|
|
||||||
{
|
|
||||||
GameObject gameObject;
|
|
||||||
NetworkManagerOnServerDisconnect manager;
|
|
||||||
|
|
||||||
[SetUp]
|
|
||||||
public void SetUp()
|
|
||||||
{
|
|
||||||
gameObject = new GameObject();
|
|
||||||
manager = gameObject.AddComponent<NetworkManagerOnServerDisconnect>();
|
|
||||||
}
|
|
||||||
|
|
||||||
[TearDown]
|
|
||||||
public void TearDown()
|
|
||||||
{
|
|
||||||
GameObject.DestroyImmediate(gameObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
// test to prevent https://github.com/vis2k/Mirror/issues/1515
|
|
||||||
[Test]
|
|
||||||
public void StopHostCallsOnServerDisconnectForHostClient()
|
|
||||||
{
|
|
||||||
// OnServerDisconnect is always called when a client disconnects.
|
|
||||||
// it should also be called for the host client when we stop the host
|
|
||||||
Assert.That(manager.called, Is.EqualTo(0));
|
|
||||||
manager.StartHost();
|
|
||||||
manager.StopHost();
|
|
||||||
Assert.That(manager.called, Is.EqualTo(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 2f583081473a64b92b971678e571382a
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,6 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using Mirror.RemoteCalls;
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.TestTools;
|
using UnityEngine.TestTools;
|
||||||
@ -262,58 +260,6 @@ public void ConnectDuplicateConnectionIdsTest()
|
|||||||
Assert.That(NetworkServer.connections[42], Is.EqualTo(original));
|
Assert.That(NetworkServer.connections[42], Is.EqualTo(original));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void SetLocalConnectionTest()
|
|
||||||
{
|
|
||||||
// listen
|
|
||||||
NetworkServer.Listen(1);
|
|
||||||
|
|
||||||
// set local connection
|
|
||||||
ULocalConnectionToClient localConnection = new ULocalConnectionToClient();
|
|
||||||
NetworkServer.SetLocalConnection(localConnection);
|
|
||||||
Assert.That(NetworkServer.localConnection, Is.EqualTo(localConnection));
|
|
||||||
|
|
||||||
// try to overwrite it, which should not work
|
|
||||||
// (it will show an error message, which is expected)
|
|
||||||
LogAssert.ignoreFailingMessages = true;
|
|
||||||
ULocalConnectionToClient overwrite = new ULocalConnectionToClient();
|
|
||||||
NetworkServer.SetLocalConnection(overwrite);
|
|
||||||
Assert.That(NetworkServer.localConnection, Is.EqualTo(localConnection));
|
|
||||||
LogAssert.ignoreFailingMessages = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void RemoveLocalConnectionTest()
|
|
||||||
{
|
|
||||||
// listen
|
|
||||||
NetworkServer.Listen(1);
|
|
||||||
|
|
||||||
// set local connection
|
|
||||||
ULocalConnectionToClient localConnection = new ULocalConnectionToClient();
|
|
||||||
NetworkServer.SetLocalConnection(localConnection);
|
|
||||||
Assert.That(NetworkServer.localConnection, Is.EqualTo(localConnection));
|
|
||||||
|
|
||||||
// local connection needs a server connection because
|
|
||||||
// RemoveLocalConnection calls localConnection.Disconnect
|
|
||||||
localConnection.connectionToServer = new ULocalConnectionToServer();
|
|
||||||
|
|
||||||
// remove local connection
|
|
||||||
NetworkServer.RemoveLocalConnection();
|
|
||||||
Assert.That(NetworkServer.localConnection, Is.Null);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void LocalClientActiveTest()
|
|
||||||
{
|
|
||||||
// listen
|
|
||||||
NetworkServer.Listen(1);
|
|
||||||
Assert.That(NetworkServer.localClientActive, Is.False);
|
|
||||||
|
|
||||||
// set local connection
|
|
||||||
NetworkServer.SetLocalConnection(new ULocalConnectionToClient());
|
|
||||||
Assert.That(NetworkServer.localClientActive, Is.True);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void AddConnectionTest()
|
public void AddConnectionTest()
|
||||||
{
|
{
|
||||||
@ -403,34 +349,6 @@ public void DisconnectAllConnectionsTest()
|
|||||||
Assert.That(NetworkServer.connections.Count, Is.EqualTo(0));
|
Assert.That(NetworkServer.connections.Count, Is.EqualTo(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void DisconnectAllTest()
|
|
||||||
{
|
|
||||||
// message handlers
|
|
||||||
NetworkServer.RegisterHandler<ConnectMessage>((conn, msg) => { }, false);
|
|
||||||
NetworkServer.RegisterHandler<DisconnectMessage>((conn, msg) => { }, false);
|
|
||||||
NetworkServer.RegisterHandler<ErrorMessage>((conn, msg) => { }, false);
|
|
||||||
|
|
||||||
// listen
|
|
||||||
NetworkServer.Listen(1);
|
|
||||||
Assert.That(NetworkServer.connections.Count, Is.EqualTo(0));
|
|
||||||
|
|
||||||
// set local connection
|
|
||||||
ULocalConnectionToClient localConnection = new ULocalConnectionToClient();
|
|
||||||
NetworkServer.SetLocalConnection(localConnection);
|
|
||||||
Assert.That(NetworkServer.localConnection, Is.EqualTo(localConnection));
|
|
||||||
|
|
||||||
// add connection
|
|
||||||
NetworkConnectionToClient conn42 = new NetworkConnectionToClient(42);
|
|
||||||
NetworkServer.AddConnection(conn42);
|
|
||||||
Assert.That(NetworkServer.connections.Count, Is.EqualTo(1));
|
|
||||||
|
|
||||||
// disconnect all connections and local connection
|
|
||||||
NetworkServer.DisconnectAll();
|
|
||||||
Assert.That(NetworkServer.connections.Count, Is.EqualTo(0));
|
|
||||||
Assert.That(NetworkServer.localConnection, Is.Null);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void OnDataReceivedTest()
|
public void OnDataReceivedTest()
|
||||||
{
|
{
|
||||||
@ -517,247 +435,6 @@ public void OnDataReceivedInvalidConnectionIdTest()
|
|||||||
Assert.That(connectionReceived, Is.Null);
|
Assert.That(connectionReceived, Is.Null);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void SetClientReadyAndNotReadyTest()
|
|
||||||
{
|
|
||||||
ULocalConnectionToClient connection = new ULocalConnectionToClient();
|
|
||||||
connection.connectionToServer = new ULocalConnectionToServer();
|
|
||||||
Assert.That(connection.isReady, Is.False);
|
|
||||||
|
|
||||||
NetworkServer.SetClientReady(connection);
|
|
||||||
Assert.That(connection.isReady, Is.True);
|
|
||||||
|
|
||||||
NetworkServer.SetClientNotReady(connection);
|
|
||||||
Assert.That(connection.isReady, Is.False);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void SetAllClientsNotReadyTest()
|
|
||||||
{
|
|
||||||
// add first ready client
|
|
||||||
ULocalConnectionToClient first = new ULocalConnectionToClient();
|
|
||||||
first.connectionToServer = new ULocalConnectionToServer();
|
|
||||||
first.isReady = true;
|
|
||||||
NetworkServer.connections[42] = first;
|
|
||||||
|
|
||||||
// add second ready client
|
|
||||||
ULocalConnectionToClient second = new ULocalConnectionToClient();
|
|
||||||
second.connectionToServer = new ULocalConnectionToServer();
|
|
||||||
second.isReady = true;
|
|
||||||
NetworkServer.connections[43] = second;
|
|
||||||
|
|
||||||
// set all not ready
|
|
||||||
NetworkServer.SetAllClientsNotReady();
|
|
||||||
Assert.That(first.isReady, Is.False);
|
|
||||||
Assert.That(second.isReady, Is.False);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ReadyMessageSetsClientReadyTest()
|
|
||||||
{
|
|
||||||
// listen
|
|
||||||
NetworkServer.Listen(1);
|
|
||||||
Assert.That(NetworkServer.connections.Count, Is.EqualTo(0));
|
|
||||||
|
|
||||||
// add connection
|
|
||||||
ULocalConnectionToClient connection = new ULocalConnectionToClient();
|
|
||||||
connection.connectionToServer = new ULocalConnectionToServer();
|
|
||||||
NetworkServer.AddConnection(connection);
|
|
||||||
|
|
||||||
// set as authenticated, otherwise readymessage is rejected
|
|
||||||
connection.isAuthenticated = true;
|
|
||||||
|
|
||||||
// serialize a ready message into an arraysegment
|
|
||||||
ReadyMessage message = new ReadyMessage();
|
|
||||||
NetworkWriter writer = new NetworkWriter();
|
|
||||||
MessagePacker.Pack(message, writer);
|
|
||||||
ArraySegment<byte> segment = writer.ToArraySegment();
|
|
||||||
|
|
||||||
// call transport.OnDataReceived with the message
|
|
||||||
// -> calls NetworkServer.OnClientReadyMessage
|
|
||||||
// -> calls SetClientReady(conn)
|
|
||||||
Transport.activeTransport.OnServerDataReceived.Invoke(0, segment, 0);
|
|
||||||
|
|
||||||
// ready?
|
|
||||||
Assert.That(connection.isReady, Is.True);
|
|
||||||
}
|
|
||||||
|
|
||||||
// this runs a command all the way:
|
|
||||||
// byte[]->transport->server->identity->component
|
|
||||||
[Test]
|
|
||||||
public void CommandMessageCallsCommandTest()
|
|
||||||
{
|
|
||||||
// listen
|
|
||||||
NetworkServer.Listen(1);
|
|
||||||
Assert.That(NetworkServer.connections.Count, Is.EqualTo(0));
|
|
||||||
|
|
||||||
// add connection
|
|
||||||
ULocalConnectionToClient connection = new ULocalConnectionToClient();
|
|
||||||
connection.connectionToServer = new ULocalConnectionToServer();
|
|
||||||
NetworkServer.AddConnection(connection);
|
|
||||||
|
|
||||||
// set as authenticated, otherwise removeplayer is rejected
|
|
||||||
connection.isAuthenticated = true;
|
|
||||||
|
|
||||||
// add an identity with two networkbehaviour components
|
|
||||||
GameObject go = new GameObject();
|
|
||||||
NetworkIdentity identity = go.AddComponent<NetworkIdentity>();
|
|
||||||
identity.netId = 42;
|
|
||||||
// for authority check
|
|
||||||
identity.connectionToClient = connection;
|
|
||||||
CommandTestNetworkBehaviour comp0 = go.AddComponent<CommandTestNetworkBehaviour>();
|
|
||||||
Assert.That(comp0.called, Is.EqualTo(0));
|
|
||||||
CommandTestNetworkBehaviour comp1 = go.AddComponent<CommandTestNetworkBehaviour>();
|
|
||||||
Assert.That(comp1.called, Is.EqualTo(0));
|
|
||||||
connection.identity = identity;
|
|
||||||
|
|
||||||
// register the command delegate, otherwise it's not found
|
|
||||||
int registeredHash = RemoteCallHelper.RegisterDelegate(typeof(CommandTestNetworkBehaviour),
|
|
||||||
nameof(CommandTestNetworkBehaviour.CommandGenerated),
|
|
||||||
MirrorInvokeType.Command,
|
|
||||||
CommandTestNetworkBehaviour.CommandGenerated,
|
|
||||||
false);
|
|
||||||
|
|
||||||
// identity needs to be in spawned dict, otherwise command handler
|
|
||||||
// won't find it
|
|
||||||
NetworkIdentity.spawned[identity.netId] = identity;
|
|
||||||
|
|
||||||
// serialize a removeplayer message into an arraysegment
|
|
||||||
CommandMessage message = new CommandMessage
|
|
||||||
{
|
|
||||||
componentIndex = 0,
|
|
||||||
functionHash = RemoteCallHelper.GetMethodHash(typeof(CommandTestNetworkBehaviour), nameof(CommandTestNetworkBehaviour.CommandGenerated)),
|
|
||||||
netId = identity.netId,
|
|
||||||
payload = new ArraySegment<byte>(new byte[0])
|
|
||||||
};
|
|
||||||
NetworkWriter writer = new NetworkWriter();
|
|
||||||
MessagePacker.Pack(message, writer);
|
|
||||||
ArraySegment<byte> segment = writer.ToArraySegment();
|
|
||||||
|
|
||||||
// call transport.OnDataReceived with the message
|
|
||||||
// -> calls NetworkServer.OnRemovePlayerMessage
|
|
||||||
// -> destroys conn.identity and sets it to null
|
|
||||||
Transport.activeTransport.OnServerDataReceived.Invoke(0, segment, 0);
|
|
||||||
|
|
||||||
// was the command called in the first component, not in the second one?
|
|
||||||
Assert.That(comp0.called, Is.EqualTo(1));
|
|
||||||
Assert.That(comp1.called, Is.EqualTo(0));
|
|
||||||
|
|
||||||
// send another command for the second component
|
|
||||||
comp0.called = 0;
|
|
||||||
message.componentIndex = 1;
|
|
||||||
writer = new NetworkWriter();
|
|
||||||
MessagePacker.Pack(message, writer);
|
|
||||||
segment = writer.ToArraySegment();
|
|
||||||
Transport.activeTransport.OnServerDataReceived.Invoke(0, segment, 0);
|
|
||||||
|
|
||||||
// was the command called in the second component, not in the first one?
|
|
||||||
Assert.That(comp0.called, Is.EqualTo(0));
|
|
||||||
Assert.That(comp1.called, Is.EqualTo(1));
|
|
||||||
|
|
||||||
// sending a command without authority should fail
|
|
||||||
// (= if connectionToClient is not what we received the data on)
|
|
||||||
// set wrong authority
|
|
||||||
identity.connectionToClient = new ULocalConnectionToClient();
|
|
||||||
comp0.called = 0;
|
|
||||||
comp1.called = 0;
|
|
||||||
Transport.activeTransport.OnServerDataReceived.Invoke(0, segment, 0);
|
|
||||||
Assert.That(comp0.called, Is.EqualTo(0));
|
|
||||||
Assert.That(comp1.called, Is.EqualTo(0));
|
|
||||||
// restore authority
|
|
||||||
identity.connectionToClient = connection;
|
|
||||||
|
|
||||||
// sending a component with wrong netId should fail
|
|
||||||
// wrong netid
|
|
||||||
message.netId += 1;
|
|
||||||
writer = new NetworkWriter();
|
|
||||||
// need to serialize the message again with wrong netid
|
|
||||||
MessagePacker.Pack(message, writer);
|
|
||||||
ArraySegment<byte> segmentWrongNetId = writer.ToArraySegment();
|
|
||||||
comp0.called = 0;
|
|
||||||
comp1.called = 0;
|
|
||||||
Transport.activeTransport.OnServerDataReceived.Invoke(0, segmentWrongNetId, 0);
|
|
||||||
Assert.That(comp0.called, Is.EqualTo(0));
|
|
||||||
Assert.That(comp1.called, Is.EqualTo(0));
|
|
||||||
|
|
||||||
// clean up
|
|
||||||
NetworkIdentity.spawned.Clear();
|
|
||||||
RemoteCallHelper.RemoveDelegate(registeredHash);
|
|
||||||
NetworkServer.Shutdown();
|
|
||||||
// destroy the test gameobject AFTER server was stopped.
|
|
||||||
// otherwise isServer is true in OnDestroy, which means it would try
|
|
||||||
// to call Destroy(go). but we need to use DestroyImmediate in
|
|
||||||
// Editor
|
|
||||||
GameObject.DestroyImmediate(go);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ActivateHostSceneCallsOnStartClient()
|
|
||||||
{
|
|
||||||
// add an identity with a networkbehaviour to .spawned
|
|
||||||
GameObject go = new GameObject();
|
|
||||||
NetworkIdentity identity = go.AddComponent<NetworkIdentity>();
|
|
||||||
identity.netId = 42;
|
|
||||||
// for authority check
|
|
||||||
//identity.connectionToClient = connection;
|
|
||||||
OnStartClientTestNetworkBehaviour comp = go.AddComponent<OnStartClientTestNetworkBehaviour>();
|
|
||||||
Assert.That(comp.called, Is.EqualTo(0));
|
|
||||||
//connection.identity = identity;
|
|
||||||
NetworkIdentity.spawned[identity.netId] = identity;
|
|
||||||
|
|
||||||
// ActivateHostScene
|
|
||||||
NetworkServer.ActivateHostScene();
|
|
||||||
|
|
||||||
// was OnStartClient called for all .spawned networkidentities?
|
|
||||||
Assert.That(comp.called, Is.EqualTo(1));
|
|
||||||
|
|
||||||
// clean up
|
|
||||||
NetworkIdentity.spawned.Clear();
|
|
||||||
NetworkServer.Shutdown();
|
|
||||||
// destroy the test gameobject AFTER server was stopped.
|
|
||||||
// otherwise isServer is true in OnDestroy, which means it would try
|
|
||||||
// to call Destroy(go). but we need to use DestroyImmediate in
|
|
||||||
// Editor
|
|
||||||
GameObject.DestroyImmediate(go);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void SendToAllTest()
|
|
||||||
{
|
|
||||||
// message handlers
|
|
||||||
NetworkServer.RegisterHandler<ConnectMessage>((conn, msg) => { }, false);
|
|
||||||
NetworkServer.RegisterHandler<DisconnectMessage>((conn, msg) => { }, false);
|
|
||||||
NetworkServer.RegisterHandler<ErrorMessage>((conn, msg) => { }, false);
|
|
||||||
|
|
||||||
// listen
|
|
||||||
NetworkServer.Listen(1);
|
|
||||||
Assert.That(NetworkServer.connections.Count, Is.EqualTo(0));
|
|
||||||
|
|
||||||
// add connection
|
|
||||||
ULocalConnectionToClient connection = new ULocalConnectionToClient();
|
|
||||||
connection.connectionToServer = new ULocalConnectionToServer();
|
|
||||||
// set a client handler
|
|
||||||
int called = 0;
|
|
||||||
connection.connectionToServer.SetHandlers(new Dictionary<int, NetworkMessageDelegate>()
|
|
||||||
{
|
|
||||||
{ MessagePacker.GetId<TestMessage1>(), ((conn, reader, channelId) => ++called) }
|
|
||||||
});
|
|
||||||
NetworkServer.AddConnection(connection);
|
|
||||||
|
|
||||||
// create a message
|
|
||||||
TestMessage1 message = new TestMessage1 { IntValue = 1, DoubleValue = 2, StringValue = "3" };
|
|
||||||
|
|
||||||
// send it to all
|
|
||||||
bool result = NetworkServer.SendToAll(message);
|
|
||||||
Assert.That(result, Is.True);
|
|
||||||
|
|
||||||
// update local connection once so that the incoming queue is processed
|
|
||||||
connection.connectionToServer.Update();
|
|
||||||
|
|
||||||
// was it send to and handled by the connection?
|
|
||||||
Assert.That(called, Is.EqualTo(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void RegisterUnregisterClearHandlerTest()
|
public void RegisterUnregisterClearHandlerTest()
|
||||||
{
|
{
|
||||||
@ -821,52 +498,6 @@ public void RegisterUnregisterClearHandlerTest()
|
|||||||
Assert.That(variant2Called, Is.EqualTo(1));
|
Assert.That(variant2Called, Is.EqualTo(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void SendToClientOfPlayer()
|
|
||||||
{
|
|
||||||
// message handlers
|
|
||||||
NetworkServer.RegisterHandler<ConnectMessage>((conn, msg) => { }, false);
|
|
||||||
NetworkServer.RegisterHandler<DisconnectMessage>((conn, msg) => { }, false);
|
|
||||||
NetworkServer.RegisterHandler<ErrorMessage>((conn, msg) => { }, false);
|
|
||||||
|
|
||||||
// listen
|
|
||||||
NetworkServer.Listen(1);
|
|
||||||
Assert.That(NetworkServer.connections.Count, Is.EqualTo(0));
|
|
||||||
|
|
||||||
// add connection
|
|
||||||
ULocalConnectionToClient connection = new ULocalConnectionToClient();
|
|
||||||
connection.connectionToServer = new ULocalConnectionToServer();
|
|
||||||
// set a client handler
|
|
||||||
int called = 0;
|
|
||||||
connection.connectionToServer.SetHandlers(new Dictionary<int, NetworkMessageDelegate>()
|
|
||||||
{
|
|
||||||
{ MessagePacker.GetId<TestMessage1>(), ((conn, reader, channelId) => ++called) }
|
|
||||||
});
|
|
||||||
NetworkServer.AddConnection(connection);
|
|
||||||
|
|
||||||
// create a message
|
|
||||||
TestMessage1 message = new TestMessage1 { IntValue = 1, DoubleValue = 2, StringValue = "3" };
|
|
||||||
|
|
||||||
// create a gameobject and networkidentity
|
|
||||||
NetworkIdentity identity = new GameObject().AddComponent<NetworkIdentity>();
|
|
||||||
identity.connectionToClient = connection;
|
|
||||||
|
|
||||||
// send it to that player
|
|
||||||
NetworkServer.SendToClientOfPlayer(identity, message);
|
|
||||||
|
|
||||||
// update local connection once so that the incoming queue is processed
|
|
||||||
connection.connectionToServer.Update();
|
|
||||||
|
|
||||||
// was it send to and handled by the connection?
|
|
||||||
Assert.That(called, Is.EqualTo(1));
|
|
||||||
|
|
||||||
// clean up
|
|
||||||
NetworkServer.Shutdown();
|
|
||||||
// destroy GO after shutdown, otherwise isServer is true in OnDestroy and it tries to call
|
|
||||||
// GameObject.Destroy (but we need DestroyImmediate in Editor)
|
|
||||||
GameObject.DestroyImmediate(identity.gameObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void GetNetworkIdentityShouldFindNetworkIdentity()
|
public void GetNetworkIdentityShouldFindNetworkIdentity()
|
||||||
{
|
{
|
||||||
@ -899,103 +530,6 @@ public void GetNetworkIdentityErrorIfNotFound()
|
|||||||
GameObject.DestroyImmediate(goWithout);
|
GameObject.DestroyImmediate(goWithout);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ShowForConnection()
|
|
||||||
{
|
|
||||||
// message handlers
|
|
||||||
NetworkServer.RegisterHandler<ConnectMessage>((conn, msg) => { }, false);
|
|
||||||
NetworkServer.RegisterHandler<DisconnectMessage>((conn, msg) => { }, false);
|
|
||||||
NetworkServer.RegisterHandler<ErrorMessage>((conn, msg) => { }, false);
|
|
||||||
|
|
||||||
// listen
|
|
||||||
NetworkServer.Listen(1);
|
|
||||||
Assert.That(NetworkServer.connections.Count, Is.EqualTo(0));
|
|
||||||
|
|
||||||
// add connection
|
|
||||||
ULocalConnectionToClient connection = new ULocalConnectionToClient();
|
|
||||||
// required for ShowForConnection
|
|
||||||
connection.isReady = true;
|
|
||||||
connection.connectionToServer = new ULocalConnectionToServer();
|
|
||||||
// set a client handler
|
|
||||||
int called = 0;
|
|
||||||
connection.connectionToServer.SetHandlers(new Dictionary<int, NetworkMessageDelegate>()
|
|
||||||
{
|
|
||||||
{ MessagePacker.GetId<SpawnMessage>(), ((conn, reader, channelId) => ++called) }
|
|
||||||
});
|
|
||||||
NetworkServer.AddConnection(connection);
|
|
||||||
|
|
||||||
// create a gameobject and networkidentity and some unique values
|
|
||||||
NetworkIdentity identity = new GameObject().AddComponent<NetworkIdentity>();
|
|
||||||
identity.connectionToClient = connection;
|
|
||||||
|
|
||||||
// call ShowForConnection
|
|
||||||
NetworkServer.ShowForConnection(identity, connection);
|
|
||||||
|
|
||||||
// update local connection once so that the incoming queue is processed
|
|
||||||
connection.connectionToServer.Update();
|
|
||||||
|
|
||||||
// was it sent to and handled by the connection?
|
|
||||||
Assert.That(called, Is.EqualTo(1));
|
|
||||||
|
|
||||||
// it shouldn't send it if connection isn't ready, so try that too
|
|
||||||
connection.isReady = false;
|
|
||||||
NetworkServer.ShowForConnection(identity, connection);
|
|
||||||
connection.connectionToServer.Update();
|
|
||||||
// not 2 but 1 like before?
|
|
||||||
Assert.That(called, Is.EqualTo(1));
|
|
||||||
|
|
||||||
// clean up
|
|
||||||
NetworkServer.Shutdown();
|
|
||||||
// destroy GO after shutdown, otherwise isServer is true in OnDestroy and it tries to call
|
|
||||||
// GameObject.Destroy (but we need DestroyImmediate in Editor)
|
|
||||||
GameObject.DestroyImmediate(identity.gameObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void HideForConnection()
|
|
||||||
{
|
|
||||||
// message handlers
|
|
||||||
NetworkServer.RegisterHandler<ConnectMessage>((conn, msg) => { }, false);
|
|
||||||
NetworkServer.RegisterHandler<DisconnectMessage>((conn, msg) => { }, false);
|
|
||||||
NetworkServer.RegisterHandler<ErrorMessage>((conn, msg) => { }, false);
|
|
||||||
|
|
||||||
// listen
|
|
||||||
NetworkServer.Listen(1);
|
|
||||||
Assert.That(NetworkServer.connections.Count, Is.EqualTo(0));
|
|
||||||
|
|
||||||
// add connection
|
|
||||||
ULocalConnectionToClient connection = new ULocalConnectionToClient();
|
|
||||||
// required for ShowForConnection
|
|
||||||
connection.isReady = true;
|
|
||||||
connection.connectionToServer = new ULocalConnectionToServer();
|
|
||||||
// set a client handler
|
|
||||||
int called = 0;
|
|
||||||
connection.connectionToServer.SetHandlers(new Dictionary<int, NetworkMessageDelegate>()
|
|
||||||
{
|
|
||||||
{ MessagePacker.GetId<ObjectHideMessage>(), ((conn, reader, channelId) => ++called) }
|
|
||||||
});
|
|
||||||
NetworkServer.AddConnection(connection);
|
|
||||||
|
|
||||||
// create a gameobject and networkidentity
|
|
||||||
NetworkIdentity identity = new GameObject().AddComponent<NetworkIdentity>();
|
|
||||||
identity.connectionToClient = connection;
|
|
||||||
|
|
||||||
// call HideForConnection
|
|
||||||
NetworkServer.HideForConnection(identity, connection);
|
|
||||||
|
|
||||||
// update local connection once so that the incoming queue is processed
|
|
||||||
connection.connectionToServer.Update();
|
|
||||||
|
|
||||||
// was it sent to and handled by the connection?
|
|
||||||
Assert.That(called, Is.EqualTo(1));
|
|
||||||
|
|
||||||
// clean up
|
|
||||||
NetworkServer.Shutdown();
|
|
||||||
// destroy GO after shutdown, otherwise isServer is true in OnDestroy and it tries to call
|
|
||||||
// GameObject.Destroy (but we need DestroyImmediate in Editor)
|
|
||||||
GameObject.DestroyImmediate(identity.gameObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void ValidateSceneObject()
|
public void ValidateSceneObject()
|
||||||
{
|
{
|
||||||
@ -1101,10 +635,6 @@ public void ShutdownCleanupTest()
|
|||||||
NetworkServer.Listen(1);
|
NetworkServer.Listen(1);
|
||||||
Assert.That(NetworkServer.active, Is.True);
|
Assert.That(NetworkServer.active, Is.True);
|
||||||
|
|
||||||
// set local connection
|
|
||||||
NetworkServer.SetLocalConnection(new ULocalConnectionToClient());
|
|
||||||
Assert.That(NetworkServer.localClientActive, Is.True);
|
|
||||||
|
|
||||||
// connect
|
// connect
|
||||||
Transport.activeTransport.OnServerConnected.Invoke(42);
|
Transport.activeTransport.OnServerConnected.Invoke(42);
|
||||||
Assert.That(NetworkServer.connections.Count, Is.EqualTo(1));
|
Assert.That(NetworkServer.connections.Count, Is.EqualTo(1));
|
||||||
@ -1115,8 +645,6 @@ public void ShutdownCleanupTest()
|
|||||||
// state cleared?
|
// state cleared?
|
||||||
Assert.That(NetworkServer.connections.Count, Is.EqualTo(0));
|
Assert.That(NetworkServer.connections.Count, Is.EqualTo(0));
|
||||||
Assert.That(NetworkServer.active, Is.False);
|
Assert.That(NetworkServer.active, Is.False);
|
||||||
Assert.That(NetworkServer.localConnection, Is.Null);
|
|
||||||
Assert.That(NetworkServer.localClientActive, Is.False);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -1143,7 +671,6 @@ public void SendCalledWhileNotActive_ShouldGiveWarning(string functionName)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void NoConnectionsTest_WithNoConnection()
|
public void NoConnectionsTest_WithNoConnection()
|
||||||
{
|
{
|
||||||
@ -1161,42 +688,5 @@ public void NoConnectionsTest_WithConnections()
|
|||||||
|
|
||||||
NetworkServer.connections.Clear();
|
NetworkServer.connections.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void NoConnectionsTest_WithHostOnly()
|
|
||||||
{
|
|
||||||
ULocalConnectionToServer connectionToServer = new ULocalConnectionToServer();
|
|
||||||
ULocalConnectionToClient connectionToClient = new ULocalConnectionToClient();
|
|
||||||
connectionToServer.connectionToClient = connectionToClient;
|
|
||||||
connectionToClient.connectionToServer = connectionToServer;
|
|
||||||
|
|
||||||
NetworkServer.SetLocalConnection(connectionToClient);
|
|
||||||
NetworkServer.connections.Add(0, connectionToClient);
|
|
||||||
|
|
||||||
Assert.That(NetworkServer.NoConnections(), Is.True);
|
|
||||||
Assert.That(NetworkServer.connections.Count, Is.EqualTo(1));
|
|
||||||
|
|
||||||
NetworkServer.connections.Clear();
|
|
||||||
NetworkServer.RemoveLocalConnection();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void NoConnectionsTest_WithHostAndConnection()
|
|
||||||
{
|
|
||||||
ULocalConnectionToServer connectionToServer = new ULocalConnectionToServer();
|
|
||||||
ULocalConnectionToClient connectionToClient = new ULocalConnectionToClient();
|
|
||||||
connectionToServer.connectionToClient = connectionToClient;
|
|
||||||
connectionToClient.connectionToServer = connectionToServer;
|
|
||||||
|
|
||||||
NetworkServer.SetLocalConnection(connectionToClient);
|
|
||||||
NetworkServer.connections.Add(0, connectionToClient);
|
|
||||||
NetworkServer.connections.Add(1, null);
|
|
||||||
|
|
||||||
Assert.That(NetworkServer.NoConnections(), Is.False);
|
|
||||||
Assert.That(NetworkServer.connections.Count, Is.EqualTo(2));
|
|
||||||
|
|
||||||
NetworkServer.connections.Clear();
|
|
||||||
NetworkServer.RemoveLocalConnection();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,89 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Mirror.Tests.RemoteAttrributeTest
|
|
||||||
{
|
|
||||||
public class RemoteTestBase
|
|
||||||
{
|
|
||||||
List<GameObject> spawned = new List<GameObject>();
|
|
||||||
|
|
||||||
[SetUp]
|
|
||||||
public void Setup()
|
|
||||||
{
|
|
||||||
Transport.activeTransport = new GameObject().AddComponent<MemoryTransport>();
|
|
||||||
|
|
||||||
// start server/client
|
|
||||||
NetworkServer.Listen(1);
|
|
||||||
NetworkClient.ConnectHost();
|
|
||||||
NetworkServer.SpawnObjects();
|
|
||||||
NetworkServer.ActivateHostScene();
|
|
||||||
NetworkClient.ConnectLocalServer();
|
|
||||||
|
|
||||||
NetworkServer.localConnection.isAuthenticated = true;
|
|
||||||
NetworkClient.connection.isAuthenticated = true;
|
|
||||||
|
|
||||||
ClientScene.Ready(NetworkClient.connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TearDown]
|
|
||||||
public void TearDown()
|
|
||||||
{
|
|
||||||
// stop server/client
|
|
||||||
NetworkClient.DisconnectLocalServer();
|
|
||||||
|
|
||||||
NetworkClient.Disconnect();
|
|
||||||
NetworkClient.Shutdown();
|
|
||||||
|
|
||||||
NetworkServer.Shutdown();
|
|
||||||
|
|
||||||
// destroy left over objects
|
|
||||||
foreach (GameObject item in spawned)
|
|
||||||
{
|
|
||||||
if (item != null)
|
|
||||||
{
|
|
||||||
GameObject.DestroyImmediate(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spawned.Clear();
|
|
||||||
|
|
||||||
NetworkIdentity.spawned.Clear();
|
|
||||||
|
|
||||||
GameObject.DestroyImmediate(Transport.activeTransport.gameObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected T CreateHostObject<T>(bool spawnWithAuthority) where T : NetworkBehaviour
|
|
||||||
{
|
|
||||||
GameObject gameObject = new GameObject();
|
|
||||||
spawned.Add(gameObject);
|
|
||||||
|
|
||||||
gameObject.AddComponent<NetworkIdentity>();
|
|
||||||
|
|
||||||
T behaviour = gameObject.AddComponent<T>();
|
|
||||||
|
|
||||||
// spawn outwith authority
|
|
||||||
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
|
|
||||||
{
|
|
||||||
NetworkServer.Spawn(gameObject);
|
|
||||||
}
|
|
||||||
ProcessMessages();
|
|
||||||
|
|
||||||
Debug.Assert(behaviour.hasAuthority == spawnWithAuthority, $"Behaviour Had Wrong Authority when spawned, This means that the test is broken and will give the wrong results");
|
|
||||||
|
|
||||||
return behaviour;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static void ProcessMessages()
|
|
||||||
{
|
|
||||||
// run update so message are processed
|
|
||||||
NetworkServer.Update();
|
|
||||||
NetworkClient.Update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 45bb26f0ce04fb749ac83a28d7590ebc
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,136 +0,0 @@
|
|||||||
using System;
|
|
||||||
using NUnit.Framework;
|
|
||||||
|
|
||||||
namespace Mirror.Tests.RemoteAttrributeTest
|
|
||||||
{
|
|
||||||
class VirtualTargetRpc : NetworkBehaviour
|
|
||||||
{
|
|
||||||
public event Action<int> onVirtualSendInt;
|
|
||||||
|
|
||||||
[TargetRpc]
|
|
||||||
public virtual void TargetSendInt(int someInt)
|
|
||||||
{
|
|
||||||
onVirtualSendInt?.Invoke(someInt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class VirtualNoOverrideTargetRpc : VirtualTargetRpc
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class VirtualOverrideTargetRpc : VirtualTargetRpc
|
|
||||||
{
|
|
||||||
public event Action<int> onOverrideSendInt;
|
|
||||||
|
|
||||||
[TargetRpc]
|
|
||||||
public override void TargetSendInt(int someInt)
|
|
||||||
{
|
|
||||||
onOverrideSendInt?.Invoke(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
|
|
||||||
{
|
|
||||||
[Test]
|
|
||||||
public void VirtualRpcIsCalled()
|
|
||||||
{
|
|
||||||
VirtualTargetRpc hostBehaviour = CreateHostObject<VirtualTargetRpc>(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]
|
|
||||||
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]
|
|
||||||
public void OverrideVirtualRpcIsCalled()
|
|
||||||
{
|
|
||||||
VirtualOverrideTargetRpc hostBehaviour = CreateHostObject<VirtualOverrideTargetRpc>(true);
|
|
||||||
|
|
||||||
const int someInt = 20;
|
|
||||||
|
|
||||||
int virtualCallCount = 0;
|
|
||||||
int overrideCallCount = 0;
|
|
||||||
hostBehaviour.onVirtualSendInt += incomingInt =>
|
|
||||||
{
|
|
||||||
virtualCallCount++;
|
|
||||||
};
|
|
||||||
hostBehaviour.onOverrideSendInt += incomingInt =>
|
|
||||||
{
|
|
||||||
overrideCallCount++;
|
|
||||||
Assert.That(incomingInt, Is.EqualTo(someInt));
|
|
||||||
};
|
|
||||||
|
|
||||||
hostBehaviour.TargetSendInt(someInt);
|
|
||||||
ProcessMessages();
|
|
||||||
Assert.That(virtualCallCount, Is.EqualTo(0));
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 56e76b5f8b5fe2d40ade963d179ef76e
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,37 +0,0 @@
|
|||||||
using System;
|
|
||||||
using NUnit.Framework;
|
|
||||||
|
|
||||||
namespace Mirror.Tests.RemoteAttrributeTest
|
|
||||||
{
|
|
||||||
class TargetRpcBehaviour : NetworkBehaviour
|
|
||||||
{
|
|
||||||
public event Action<int> onSendInt;
|
|
||||||
|
|
||||||
[TargetRpc]
|
|
||||||
public void SendInt(int someInt)
|
|
||||||
{
|
|
||||||
onSendInt?.Invoke(someInt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TargetRpcTest : RemoteTestBase
|
|
||||||
{
|
|
||||||
[Test]
|
|
||||||
public void RpcIsCalled()
|
|
||||||
{
|
|
||||||
TargetRpcBehaviour hostBehaviour = CreateHostObject<TargetRpcBehaviour>(true);
|
|
||||||
|
|
||||||
const int someInt = 20;
|
|
||||||
|
|
||||||
int callCount = 0;
|
|
||||||
hostBehaviour.onSendInt += incomingInt =>
|
|
||||||
{
|
|
||||||
callCount++;
|
|
||||||
Assert.That(incomingInt, Is.EqualTo(someInt));
|
|
||||||
};
|
|
||||||
hostBehaviour.SendInt(someInt);
|
|
||||||
ProcessMessages();
|
|
||||||
Assert.That(callCount, Is.EqualTo(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 53f71b8db0a8bac448b45ee86a0d355a
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -85,66 +85,6 @@ public IEnumerator LocalPlayerIsSetToNullAfterDestroyMessage()
|
|||||||
// wait a frame for destroy to happen
|
// wait a frame for destroy to happen
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
// use "is null" here to avoid unity == check
|
|
||||||
Assert.IsTrue(ClientScene.localPlayer is null, "local player should be set to c# null");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public class ClientSceneTest_LocalPlayer_asHost : HostSetup
|
|
||||||
{
|
|
||||||
[UnityTest]
|
|
||||||
public IEnumerator LocalPlayerIsSetToNullAfterNetworkDestroy()
|
|
||||||
{
|
|
||||||
const uint netId = 1000;
|
|
||||||
|
|
||||||
GameObject go = new GameObject();
|
|
||||||
|
|
||||||
NetworkIdentity identity = go.AddComponent<NetworkIdentity>();
|
|
||||||
|
|
||||||
SpawnMessage msg = new SpawnMessage
|
|
||||||
{
|
|
||||||
netId = netId,
|
|
||||||
isLocalPlayer = true,
|
|
||||||
isOwner = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
NetworkIdentity.spawned[msg.netId] = identity;
|
|
||||||
ClientScene.OnHostClientSpawn(msg);
|
|
||||||
|
|
||||||
NetworkServer.Destroy(identity.gameObject);
|
|
||||||
|
|
||||||
// wait a frame for destroy to happen
|
|
||||||
yield return null;
|
|
||||||
|
|
||||||
// use "is null" here to avoid unity == check
|
|
||||||
Assert.IsTrue(ClientScene.localPlayer is null, "local player should be set to c# null");
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnityTest]
|
|
||||||
public IEnumerator LocalPlayerIsSetToNullAfterNetworkUnspawn()
|
|
||||||
{
|
|
||||||
const uint netId = 1000;
|
|
||||||
|
|
||||||
GameObject go = new GameObject();
|
|
||||||
|
|
||||||
NetworkIdentity identity = go.AddComponent<NetworkIdentity>();
|
|
||||||
|
|
||||||
SpawnMessage msg = new SpawnMessage
|
|
||||||
{
|
|
||||||
netId = netId,
|
|
||||||
isLocalPlayer = true,
|
|
||||||
isOwner = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
NetworkIdentity.spawned[msg.netId] = identity;
|
|
||||||
ClientScene.OnHostClientSpawn(msg);
|
|
||||||
|
|
||||||
NetworkServer.UnSpawn(identity.gameObject);
|
|
||||||
|
|
||||||
// wait a frame for destroy to happen
|
|
||||||
yield return null;
|
|
||||||
|
|
||||||
// use "is null" here to avoid unity == check
|
// use "is null" here to avoid unity == check
|
||||||
Assert.IsTrue(ClientScene.localPlayer is null, "local player should be set to c# null");
|
Assert.IsTrue(ClientScene.localPlayer is null, "local player should be set to c# null");
|
||||||
}
|
}
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
using System.Collections;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.TestTools;
|
|
||||||
|
|
||||||
namespace Mirror.Tests.Runtime
|
|
||||||
{
|
|
||||||
public class HostSetup
|
|
||||||
{
|
|
||||||
protected GameObject networkManagerGo;
|
|
||||||
protected NetworkManager manager;
|
|
||||||
protected MemoryTransport transport;
|
|
||||||
|
|
||||||
protected GameObject playerGO;
|
|
||||||
protected NetworkIdentity identity;
|
|
||||||
|
|
||||||
[UnitySetUp]
|
|
||||||
public IEnumerator SetupHost()
|
|
||||||
{
|
|
||||||
networkManagerGo = new GameObject();
|
|
||||||
transport = networkManagerGo.AddComponent<MemoryTransport>();
|
|
||||||
manager = networkManagerGo.AddComponent<NetworkManager>();
|
|
||||||
Transport.activeTransport = transport;
|
|
||||||
|
|
||||||
playerGO = new GameObject();
|
|
||||||
identity = playerGO.AddComponent<NetworkIdentity>();
|
|
||||||
identity.assetId = System.Guid.NewGuid();
|
|
||||||
|
|
||||||
manager.playerPrefab = playerGO;
|
|
||||||
manager.autoStartServerBuild = false;
|
|
||||||
|
|
||||||
yield return null;
|
|
||||||
|
|
||||||
manager.StartHost();
|
|
||||||
}
|
|
||||||
|
|
||||||
[TearDown]
|
|
||||||
public void ShutdownHost()
|
|
||||||
{
|
|
||||||
Object.DestroyImmediate(playerGO);
|
|
||||||
manager.StopHost();
|
|
||||||
Object.DestroyImmediate(networkManagerGo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: ed9f33fa2d684c64cb12abd81ecdc849
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,82 +0,0 @@
|
|||||||
using System.Collections;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.TestTools;
|
|
||||||
|
|
||||||
namespace Mirror.Tests.Runtime
|
|
||||||
{
|
|
||||||
[TestFixture]
|
|
||||||
public class NetworkServerWithHostRuntimeTest
|
|
||||||
{
|
|
||||||
[UnitySetUp]
|
|
||||||
public IEnumerator UnitySetUp()
|
|
||||||
{
|
|
||||||
Transport.activeTransport = new GameObject().AddComponent<MemoryTransport>();
|
|
||||||
|
|
||||||
// start server and wait 1 frame
|
|
||||||
NetworkServer.Listen(1);
|
|
||||||
yield return null;
|
|
||||||
|
|
||||||
// connection host and wait 1 frame
|
|
||||||
NetworkClient.ConnectHost();
|
|
||||||
NetworkClient.ConnectLocalServer();
|
|
||||||
yield return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
[TearDown]
|
|
||||||
public void TearDown()
|
|
||||||
{
|
|
||||||
NetworkClient.DisconnectLocalServer();
|
|
||||||
NetworkClient.Disconnect();
|
|
||||||
NetworkClient.Shutdown();
|
|
||||||
|
|
||||||
if (NetworkServer.active)
|
|
||||||
{
|
|
||||||
NetworkServer.Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Transport.activeTransport != null)
|
|
||||||
{
|
|
||||||
GameObject.Destroy(Transport.activeTransport.gameObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[UnityTest]
|
|
||||||
public IEnumerator DisconnectTimeoutTest()
|
|
||||||
{
|
|
||||||
// Set high ping frequency so no NetworkPingMessage is generated
|
|
||||||
NetworkTime.PingFrequency = 5f;
|
|
||||||
|
|
||||||
// Set a short timeout for this test and enable disconnectInactiveConnections
|
|
||||||
NetworkServer.disconnectInactiveTimeout = 1f;
|
|
||||||
NetworkServer.disconnectInactiveConnections = true;
|
|
||||||
|
|
||||||
GameObject remotePlayer = new GameObject("RemotePlayer", typeof(NetworkIdentity));
|
|
||||||
const int remoteConnectionId = 1;
|
|
||||||
const int localConnectionId = 0;
|
|
||||||
NetworkConnectionToClient remoteConnection = new NetworkConnectionToClient(remoteConnectionId);
|
|
||||||
NetworkServer.OnConnected(remoteConnection);
|
|
||||||
NetworkServer.AddPlayerForConnection(remoteConnection, remotePlayer);
|
|
||||||
|
|
||||||
// There's a host player from HostSetup + remotePlayer
|
|
||||||
Assert.That(NetworkServer.connections.Count, Is.EqualTo(2));
|
|
||||||
Assert.IsTrue(NetworkServer.connections.ContainsKey(localConnectionId));
|
|
||||||
Assert.IsTrue(NetworkServer.connections.ContainsKey(remoteConnectionId));
|
|
||||||
|
|
||||||
// wait 2 seconds for remoteConnection to timeout as idle
|
|
||||||
float endTime = Time.time + 2f;
|
|
||||||
while (Time.time < endTime)
|
|
||||||
{
|
|
||||||
yield return null;
|
|
||||||
NetworkServer.Update();
|
|
||||||
}
|
|
||||||
|
|
||||||
// host client connection should still be alive
|
|
||||||
Assert.That(NetworkServer.connections.Count, Is.EqualTo(1));
|
|
||||||
Assert.That(NetworkServer.localConnection, Is.Not.Null);
|
|
||||||
Assert.IsTrue(NetworkServer.connections.ContainsKey(localConnectionId));
|
|
||||||
Assert.IsFalse(NetworkServer.connections.ContainsKey(remoteConnectionId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b913e4ff0bb966d4982795271eeedeaf
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,74 +0,0 @@
|
|||||||
using System.Collections;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using UnityEditor.SceneManagement;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.SceneManagement;
|
|
||||||
using UnityEngine.TestTools;
|
|
||||||
|
|
||||||
namespace Mirror.Tests.Runtime
|
|
||||||
{
|
|
||||||
public class SceneObjectSpawningTests
|
|
||||||
{
|
|
||||||
const string ScenePath = "Assets/Mirror/Tests/Runtime/Scenes/SceneObjectSpawningTestsScene.unity";
|
|
||||||
readonly Regex errorMessage = new Regex(".*Don't call Instantiate for NetworkIdentities that were in the scene since the beginning \\(aka scene objects\\).*");
|
|
||||||
|
|
||||||
NetworkIdentity sceneObject;
|
|
||||||
|
|
||||||
[UnitySetUp]
|
|
||||||
public IEnumerator Setup()
|
|
||||||
{
|
|
||||||
// load scene
|
|
||||||
yield return EditorSceneManager.LoadSceneAsyncInPlayMode(ScenePath, new LoadSceneParameters { loadSceneMode = LoadSceneMode.Additive });
|
|
||||||
Scene scene = SceneManager.GetSceneByPath(ScenePath);
|
|
||||||
SceneManager.SetActiveScene(scene);
|
|
||||||
|
|
||||||
// wait for networkmanager to awake
|
|
||||||
yield return null;
|
|
||||||
|
|
||||||
NetworkManager.singleton.StartHost();
|
|
||||||
// wait for start host
|
|
||||||
yield return null;
|
|
||||||
|
|
||||||
sceneObject = GameObject.Find("SceneNetworkIdentity").GetComponent<NetworkIdentity>();
|
|
||||||
Debug.Assert(sceneObject != null, $"Could not find 'SceneNetworkIdentity' in Scene:{ScenePath}");
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnityTearDown]
|
|
||||||
public IEnumerator TearDown()
|
|
||||||
{
|
|
||||||
NetworkManager.Shutdown();
|
|
||||||
|
|
||||||
// unload scene
|
|
||||||
Scene scene = SceneManager.GetSceneByPath(ScenePath);
|
|
||||||
yield return SceneManager.UnloadSceneAsync(scene);
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnityTest]
|
|
||||||
public IEnumerator CallingInstantiateOnASceneObjectGivesAHelpfulError()
|
|
||||||
{
|
|
||||||
// make sure sceneobject has a sceneId
|
|
||||||
Assert.That(sceneObject.sceneId, Is.Not.Zero);
|
|
||||||
yield return null;
|
|
||||||
|
|
||||||
LogAssert.Expect(LogType.Error, errorMessage);
|
|
||||||
GameObject clone = GameObject.Instantiate(sceneObject.gameObject);
|
|
||||||
NetworkServer.Spawn(clone);
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnityTest]
|
|
||||||
public IEnumerator CallingInstantiateOnASceneObjectMutlipleTimesGivesAHelpfulErrorEachTime()
|
|
||||||
{
|
|
||||||
// make sure sceneobject has a sceneId
|
|
||||||
Assert.That(sceneObject.sceneId, Is.Not.Zero);
|
|
||||||
yield return null;
|
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++)
|
|
||||||
{
|
|
||||||
LogAssert.Expect(LogType.Error, errorMessage);
|
|
||||||
GameObject clone = GameObject.Instantiate(sceneObject.gameObject);
|
|
||||||
NetworkServer.Spawn(clone);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: a5922dcacabc9594591a0a328b735087
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
Loading…
Reference in New Issue
Block a user