Remove Host Mode

This commit is contained in:
vis2k 2020-09-28 11:38:39 +02:00
parent f82d7c7abc
commit 139950ea4e
46 changed files with 26 additions and 3643 deletions

View File

@ -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));

View File

@ -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");

View File

@ -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);

View File

@ -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();
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: a88758df7db2043d6a9d926e0b6d4191
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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)
{ {

View File

@ -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);
} }

View File

@ -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>();

View File

@ -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>

View File

@ -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
} }
} }

View File

@ -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"))
{ {

View File

@ -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

View File

@ -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;
}
} }
} }

View File

@ -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));
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 9759f0eddb9731c4b881ac30bacc0de0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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));
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 2928376e56382b646975dd00b68c2287
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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));
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 881c801c26e90df43b3558a23c96e0ea
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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));
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 1dd3f8a95eee6f74997bc8abcd43a401
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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));
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 518288ffe7c7215458a98466131fc7af
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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();
}
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: e035d8111975b864099f87f21c5518ff
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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);
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 405841e2a21c64d7585d5c71d06ffff2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
{ {

View File

@ -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()
{ {

View File

@ -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);
}
} }
} }

View File

@ -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));
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 2f583081473a64b92b971678e571382a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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();
}
} }
} }

View File

@ -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();
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 45bb26f0ce04fb749ac83a28d7590ebc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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));
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 56e76b5f8b5fe2d40ade963d179ef76e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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));
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 53f71b8db0a8bac448b45ee86a0d355a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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");
} }

View File

@ -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);
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: ed9f33fa2d684c64cb12abd81ecdc849
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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));
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: b913e4ff0bb966d4982795271eeedeaf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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);
}
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: a5922dcacabc9594591a0a328b735087
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: