mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 02:50:32 +00:00
feat(NetworkServer): Improved ReplacePlayerForConnection (#3885)
- ReplacePlayerOptions: KeepAuthority, KeepActive, Unspawn, Destroy - NetworkServer tests updated - Examples updated and work correctly Eliminates need to make a coroutine to replace & destroy player.
This commit is contained in:
parent
46010ca49c
commit
d8c7c1e815
@ -146,7 +146,7 @@ void SceneLoadedForPlayer(NetworkConnectionToClient conn, GameObject roomPlayer)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// replace room player with game player
|
// replace room player with game player
|
||||||
NetworkServer.ReplacePlayerForConnection(conn, gamePlayer, true);
|
NetworkServer.ReplacePlayerForConnection(conn, gamePlayer, ReplacePlayerOptions.KeepAuthority);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void CallOnClientEnterRoom()
|
internal void CallOnClientEnterRoom()
|
||||||
@ -342,7 +342,7 @@ public override void ServerChangeScene(string newSceneName)
|
|||||||
{
|
{
|
||||||
// re-add the room object
|
// re-add the room object
|
||||||
roomPlayer.GetComponent<NetworkRoomPlayer>().readyToBegin = false;
|
roomPlayer.GetComponent<NetworkRoomPlayer>().readyToBegin = false;
|
||||||
NetworkServer.ReplacePlayerForConnection(identity.connectionToClient, roomPlayer.gameObject);
|
NetworkServer.ReplacePlayerForConnection(identity.connectionToClient, roomPlayer.gameObject, ReplacePlayerOptions.KeepAuthority);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,18 @@
|
|||||||
|
|
||||||
namespace Mirror
|
namespace Mirror
|
||||||
{
|
{
|
||||||
|
public enum ReplacePlayerOptions
|
||||||
|
{
|
||||||
|
/// <summary>Player Object remains active on server and clients. Ownership is not removed</summary>
|
||||||
|
KeepAuthority,
|
||||||
|
/// <summary>Player Object remains active on server and clients. Only ownership is removed</summary>
|
||||||
|
KeepActive,
|
||||||
|
/// <summary>Player Object is unspawned on clients but remains on server</summary>
|
||||||
|
Unspawn,
|
||||||
|
/// <summary>Player Object is destroyed on server and clients</summary>
|
||||||
|
Destroy
|
||||||
|
}
|
||||||
|
|
||||||
public enum RemovePlayerOptions
|
public enum RemovePlayerOptions
|
||||||
{
|
{
|
||||||
/// <summary>Player Object remains active on server and clients. Only ownership is removed</summary>
|
/// <summary>Player Object remains active on server and clients. Only ownership is removed</summary>
|
||||||
@ -1100,10 +1112,36 @@ public static bool AddPlayerForConnection(NetworkConnectionToClient conn, GameOb
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Replaces connection's player object. The old object is not destroyed.</summary>
|
// Deprecated 2024-008-09
|
||||||
// This does NOT change the ready state of the connection, so it can
|
[Obsolete("Use ReplacePlayerForConnection(NetworkConnectionToClient conn, GameObject player, uint assetId, ReplacePlayerOptions replacePlayerOptions) instead")]
|
||||||
// safely be used while changing scenes.
|
public static bool ReplacePlayerForConnection(NetworkConnectionToClient conn, GameObject player, uint assetId, bool keepAuthority = false)
|
||||||
|
{
|
||||||
|
if (GetNetworkIdentity(player, out NetworkIdentity identity))
|
||||||
|
identity.assetId = assetId;
|
||||||
|
|
||||||
|
return ReplacePlayerForConnection(conn, player, keepAuthority ? ReplacePlayerOptions.KeepAuthority : ReplacePlayerOptions.KeepActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated 2024-008-09
|
||||||
|
[Obsolete("Use ReplacePlayerForConnection(NetworkConnectionToClient conn, GameObject player, ReplacePlayerOptions replacePlayerOptions) instead")]
|
||||||
public static bool ReplacePlayerForConnection(NetworkConnectionToClient conn, GameObject player, bool keepAuthority = false)
|
public static bool ReplacePlayerForConnection(NetworkConnectionToClient conn, GameObject player, bool keepAuthority = false)
|
||||||
|
{
|
||||||
|
return ReplacePlayerForConnection(conn, player, keepAuthority ? ReplacePlayerOptions.KeepAuthority : ReplacePlayerOptions.KeepActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Replaces connection's player object. The old object is not destroyed.</summary>
|
||||||
|
// This does NOT change the ready state of the connection, so it can safely be used while changing scenes.
|
||||||
|
public static bool ReplacePlayerForConnection(NetworkConnectionToClient conn, GameObject player, uint assetId, ReplacePlayerOptions replacePlayerOptions)
|
||||||
|
{
|
||||||
|
if (GetNetworkIdentity(player, out NetworkIdentity identity))
|
||||||
|
identity.assetId = assetId;
|
||||||
|
|
||||||
|
return ReplacePlayerForConnection(conn, player, replacePlayerOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Replaces connection's player object. The old object is not destroyed.</summary>
|
||||||
|
// This does NOT change the ready state of the connection, so it can safely be used while changing scenes.
|
||||||
|
public static bool ReplacePlayerForConnection(NetworkConnectionToClient conn, GameObject player, ReplacePlayerOptions replacePlayerOptions)
|
||||||
{
|
{
|
||||||
if (!player.TryGetComponent(out NetworkIdentity identity))
|
if (!player.TryGetComponent(out NetworkIdentity identity))
|
||||||
{
|
{
|
||||||
@ -1145,33 +1183,28 @@ public static bool ReplacePlayerForConnection(NetworkConnectionToClient conn, Ga
|
|||||||
|
|
||||||
Respawn(identity);
|
Respawn(identity);
|
||||||
|
|
||||||
if (keepAuthority)
|
switch (replacePlayerOptions)
|
||||||
{
|
{
|
||||||
// This needs to be sent to clear isLocalPlayer on
|
case ReplacePlayerOptions.KeepAuthority:
|
||||||
// client while keeping hasAuthority true
|
// This needs to be sent to clear isLocalPlayer on
|
||||||
SendChangeOwnerMessage(previousPlayer, conn);
|
// client while keeping hasAuthority true
|
||||||
}
|
SendChangeOwnerMessage(previousPlayer, conn);
|
||||||
else
|
break;
|
||||||
{
|
case ReplacePlayerOptions.KeepActive:
|
||||||
// This clears both isLocalPlayer and hasAuthority on client
|
// This clears both isLocalPlayer and hasAuthority on client
|
||||||
previousPlayer.RemoveClientAuthority();
|
previousPlayer.RemoveClientAuthority();
|
||||||
|
break;
|
||||||
|
case ReplacePlayerOptions.Unspawn:
|
||||||
|
UnSpawn(previousPlayer.gameObject);
|
||||||
|
break;
|
||||||
|
case ReplacePlayerOptions.Destroy:
|
||||||
|
Destroy(previousPlayer.gameObject);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Replaces connection's player object. The old object is not destroyed.</summary>
|
|
||||||
// This does NOT change the ready state of the connection, so it can
|
|
||||||
// safely be used while changing scenes.
|
|
||||||
public static bool ReplacePlayerForConnection(NetworkConnectionToClient conn, GameObject player, uint assetId, bool keepAuthority = false)
|
|
||||||
{
|
|
||||||
if (GetNetworkIdentity(player, out NetworkIdentity identity))
|
|
||||||
{
|
|
||||||
identity.assetId = assetId;
|
|
||||||
}
|
|
||||||
return ReplacePlayerForConnection(conn, player, keepAuthority);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Removes the player object from the connection</summary>
|
/// <summary>Removes the player object from the connection</summary>
|
||||||
// destroyServerObject: Indicates whether the server object should be destroyed
|
// destroyServerObject: Indicates whether the server object should be destroyed
|
||||||
// Deprecated 2024-06-06
|
// Deprecated 2024-06-06
|
||||||
|
@ -113,8 +113,7 @@ void OnReplaceCharacterMessage(NetworkConnectionToClient conn, ReplaceCharacterM
|
|||||||
GameObject playerObject = Instantiate(characterData.characterPrefabs[message.createCharacterMessage.characterNumber], oldPlayer.transform.position, oldPlayer.transform.rotation);
|
GameObject playerObject = Instantiate(characterData.characterPrefabs[message.createCharacterMessage.characterNumber], oldPlayer.transform.position, oldPlayer.transform.rotation);
|
||||||
|
|
||||||
// Instantiate the new player object and broadcast to clients
|
// Instantiate the new player object and broadcast to clients
|
||||||
// Include true for keepAuthority paramater to prevent ownership change
|
NetworkServer.ReplacePlayerForConnection(conn, playerObject, ReplacePlayerOptions.KeepActive);
|
||||||
NetworkServer.ReplacePlayerForConnection(conn, playerObject, true);
|
|
||||||
|
|
||||||
// Apply data from the message however appropriate for your game
|
// Apply data from the message however appropriate for your game
|
||||||
// Typically Player would be a component you write with syncvars or properties
|
// Typically Player would be a component you write with syncvars or properties
|
||||||
@ -133,4 +132,4 @@ public void ReplaceCharacter(ReplaceCharacterMessage message)
|
|||||||
NetworkClient.Send(message);
|
NetworkClient.Send(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,17 +92,7 @@ void CmdTakeControl(NetworkConnectionToClient conn = null)
|
|||||||
|
|
||||||
isControlled = true;
|
isControlled = true;
|
||||||
|
|
||||||
// set the player object to be the tank, keep ownership of
|
NetworkServer.ReplacePlayerForConnection(conn, gameObject, ReplacePlayerOptions.Unspawn);
|
||||||
// the original player object to avoid ChangeOwner message.
|
|
||||||
NetworkServer.ReplacePlayerForConnection(conn, gameObject);
|
|
||||||
|
|
||||||
StartCoroutine(UnspawnOldPlayer((GameObject)conn.authenticationData));
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerator UnspawnOldPlayer(GameObject player)
|
|
||||||
{
|
|
||||||
yield return new WaitForSeconds(0.1f);
|
|
||||||
NetworkServer.UnSpawn(player);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command]
|
[Command]
|
||||||
@ -123,7 +113,7 @@ void CmdReleaseControl()
|
|||||||
// clear the player object
|
// clear the player object
|
||||||
connectionToClient.authenticationData = null;
|
connectionToClient.authenticationData = null;
|
||||||
|
|
||||||
NetworkServer.ReplacePlayerForConnection(connectionToClient, player);
|
NetworkServer.ReplacePlayerForConnection(connectionToClient, player, ReplacePlayerOptions.KeepActive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1342,7 +1342,7 @@ public void ReplacePlayerForConnection_CallsOnStartLocalPlayer()
|
|||||||
clientNextIdentity.name = nameof(clientNextIdentity);
|
clientNextIdentity.name = nameof(clientNextIdentity);
|
||||||
|
|
||||||
// replace connection's player from 'previous' to 'next'
|
// replace connection's player from 'previous' to 'next'
|
||||||
NetworkServer.ReplacePlayerForConnection(connectionToClient, serverNextIdentity.gameObject);
|
NetworkServer.ReplacePlayerForConnection(connectionToClient, serverNextIdentity.gameObject, ReplacePlayerOptions.KeepActive);
|
||||||
ProcessMessages();
|
ProcessMessages();
|
||||||
|
|
||||||
// should call OnStartLocalPlayer on 'next' since it became the new local player.
|
// should call OnStartLocalPlayer on 'next' since it became the new local player.
|
||||||
@ -1372,7 +1372,7 @@ public void ReplacePlayerForConnection_CallsOnStopLocalPlayer()
|
|||||||
clientNextIdentity.name = nameof(clientNextIdentity);
|
clientNextIdentity.name = nameof(clientNextIdentity);
|
||||||
|
|
||||||
// replace connection's player from 'previous' to 'next'
|
// replace connection's player from 'previous' to 'next'
|
||||||
NetworkServer.ReplacePlayerForConnection(connectionToClient, serverNextIdentity.gameObject);
|
NetworkServer.ReplacePlayerForConnection(connectionToClient, serverNextIdentity.gameObject, ReplacePlayerOptions.KeepActive);
|
||||||
ProcessMessages();
|
ProcessMessages();
|
||||||
|
|
||||||
// should call OnStopLocalPlayer on 'previous' since it's not owned anymore now.
|
// should call OnStopLocalPlayer on 'previous' since it's not owned anymore now.
|
||||||
|
Loading…
Reference in New Issue
Block a user