internal bool InternalReplacePlayerForConnection(INetworkConnection conn, NetworkClient client, GameObject player, bool keepAuthority) { NetworkIdentity identity = player.GetComponent <NetworkIdentity>(); if (identity is null) { logger.LogError("ReplacePlayer: playerGameObject has no NetworkIdentity. Please add a NetworkIdentity to " + player); return(false); } if (identity.ConnectionToClient != null && identity.ConnectionToClient != conn) { logger.LogError("Cannot replace player for connection. New player is already owned by a different connection" + player); return(false); } //NOTE: there can be an existing player logger.Log("NetworkServer ReplacePlayer"); NetworkIdentity previousPlayer = conn.Identity; conn.Identity = identity; identity.Client = client; // Set the connection on the NetworkIdentity on the server, NetworkIdentity.SetLocalPlayer is not called on the server (it is on clients) identity.SetClientOwner(conn); // special case, we are in host mode, set hasAuthority to true so that all overrides see it if (conn == Server.LocalConnection) { identity.HasAuthority = true; Server.LocalClient.Connection.Identity = identity; } // add connection to observers AFTER the playerController was set. // by definition, there is nothing to observe if there is no player // controller. // // IMPORTANT: do this in AddPlayerForConnection & ReplacePlayerForConnection! SpawnObserversForConnection(conn); if (logger.LogEnabled()) { logger.Log("Replacing playerGameObject object netId: " + player.GetComponent <NetworkIdentity>().NetId + " asset ID " + player.GetComponent <NetworkIdentity>().AssetId); } Respawn(identity); if (!keepAuthority) { previousPlayer.RemoveClientAuthority(); } return(true); }
/// <summary> /// This replaces the player object for a connection with a different player object. The old player object is not destroyed. /// <para>If a connection already has a player object, this can be used to replace that object with a different player object. This does NOT change the ready state of the connection, so it can safely be used while changing scenes.</para> /// </summary> /// <param name="player">Connection which is adding the player.</param> /// <param name="client">Client associated to the player.</param> /// <param name="character">Player object spawned for the player.</param> /// <param name="keepAuthority">Does the previous player remain attached to this connection?</param> /// <returns></returns> public void ReplaceCharacter(INetworkPlayer player, GameObject character, bool keepAuthority = false) { NetworkIdentity identity = character.GetComponent <NetworkIdentity>(); if (identity is null) { throw new ArgumentException("ReplacePlayer: playerGameObject has no NetworkIdentity. Please add a NetworkIdentity to " + character); } if (identity.ConnectionToClient != null && identity.ConnectionToClient != player) { throw new ArgumentException("Cannot replace player for connection. New player is already owned by a different connection" + character); } //NOTE: there can be an existing player logger.Log("NetworkServer ReplacePlayer"); NetworkIdentity previousPlayer = player.Identity; player.Identity = identity; // Set the connection on the NetworkIdentity on the server, NetworkIdentity.SetLocalPlayer is not called on the server (it is on clients) identity.SetClientOwner(player); // special case, we are in host mode, set hasAuthority to true so that all overrides see it if (player == Server.LocalPlayer) { identity.HasAuthority = true; Server.LocalClient.Player.Identity = identity; } // add connection to observers AFTER the playerController was set. // by definition, there is nothing to observe if there is no player // controller. // // IMPORTANT: do this in AddCharacter & ReplaceCharacter! SpawnObserversForConnection(player); if (logger.LogEnabled()) { logger.Log("Replacing playerGameObject object netId: " + character.GetComponent <NetworkIdentity>().NetId + " asset ID " + character.GetComponent <NetworkIdentity>().AssetId); } Respawn(identity); if (!keepAuthority) { previousPlayer.RemoveClientAuthority(); } }
/// <summary> /// This replaces the player object for a connection with a different player object. The old player object is not destroyed. /// <para>If a connection already has a player object, this can be used to replace that object with a different player object. This does NOT change the ready state of the connection, so it can safely be used while changing scenes.</para> /// </summary> /// <param name="player">Connection which is adding the player.</param> /// <param name="identity">Player object spawned for the player.</param> /// <param name="keepAuthority">Does the previous player remain attached to this connection?</param> /// <returns></returns> public void ReplaceCharacter(INetworkPlayer player, NetworkIdentity identity, bool keepAuthority = false) { if (identity.Owner != null && identity.Owner != player) { throw new ArgumentException($"Cannot replace player for connection. New player is already owned by a different connection {identity}"); } if (!player.HasCharacter) { throw new InvalidOperationException($"ReplaceCharacter can only be called if Player already has a charater"); } //NOTE: there can be an existing player logger.Log("NetworkServer ReplacePlayer"); NetworkIdentity previousCharacter = player.Identity; player.Identity = identity; // Set the connection on the NetworkIdentity on the server, NetworkIdentity.SetLocalPlayer is not called on the server (it is on clients) identity.SetClientOwner(player); // special case, we are in host mode, set hasAuthority to true so that all overrides see it if (player == Server.LocalPlayer) { identity.HasAuthority = true; Server.LocalClient.Player.Identity = identity; } // add connection to observers AFTER the playerController was set. // by definition, there is nothing to observe if there is no player // controller. // // IMPORTANT: do this in AddCharacter & ReplaceCharacter! SpawnVisibleObjectForPlayer(player); if (logger.LogEnabled()) { logger.Log($"Replacing playerGameObject object netId: {identity.NetId} asset ID {identity.PrefabHash:X}"); } Respawn(identity); if (!keepAuthority) { previousCharacter.RemoveClientAuthority(); } }