mirror of
https://github.com/Dadechin/Unity-WebSocket.git
synced 2025-07-04 04:14:34 +00:00
167 lines
5.9 KiB
C#
167 lines
5.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.CompilerServices;
|
|
using FishNet.CodeGenerating;
|
|
using FishNet.Connection;
|
|
using FishNet.Managing;
|
|
using FishNet.Managing.Logging;
|
|
using FishNet.Managing.Server;
|
|
using FishNet.Object;
|
|
using FishNet.Object.Synchronizing;
|
|
using GameKit.Dependencies.Utilities;
|
|
using UnityEngine;
|
|
|
|
namespace FishNet.Component.Ownership
|
|
{
|
|
/// <summary>
|
|
/// Adding this component allows any client to take ownership of the object and begin modifying it immediately.
|
|
/// </summary>
|
|
public class PredictedOwner : NetworkBehaviour
|
|
{
|
|
#region Public.
|
|
|
|
/// <summary>
|
|
/// True if the local client used TakeOwnership and is awaiting an ownership change.
|
|
/// </summary>
|
|
public bool TakingOwnership { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Owner on client prior to taking ownership. This can be used to reverse a failed ownership attempt.
|
|
/// </summary>
|
|
public NetworkConnection PreviousOwner { get; private set; } = NetworkManager.EmptyConnection;
|
|
|
|
#endregion
|
|
|
|
#region Serialized.
|
|
|
|
/// <summary>
|
|
/// True if to enable this component.
|
|
/// </summary>
|
|
[Tooltip("True if to enable this component.")] [SerializeField]
|
|
private bool _allowTakeOwnership = true;
|
|
private readonly SyncVar<bool> _allowTakeOwnershipSyncVar = new();
|
|
|
|
/// <summary>
|
|
/// Sets the next value for AllowTakeOwnership and synchronizes it.
|
|
/// Only the server may use this method.
|
|
/// </summary>
|
|
/// <param name="value">Next value to use.</param>
|
|
[Server]
|
|
public void SetAllowTakeOwnership(bool value) => _allowTakeOwnershipSyncVar.Value = value;
|
|
|
|
#endregion
|
|
|
|
protected virtual void Awake()
|
|
{
|
|
_allowTakeOwnershipSyncVar.Value = _allowTakeOwnership;
|
|
_allowTakeOwnershipSyncVar.UpdateSendRate(0f);
|
|
_allowTakeOwnershipSyncVar.OnChange += _allowTakeOwnershipSyncVar_OnChange;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when SyncVar value changes for AllowTakeOwnership.
|
|
/// </summary>
|
|
private void _allowTakeOwnershipSyncVar_OnChange(bool prev, bool next, bool asServer)
|
|
{
|
|
if (asServer || !base.IsHostStarted)
|
|
_allowTakeOwnership = next;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called on the client after gaining or losing ownership.
|
|
/// </summary>
|
|
/// <param name="prevOwner">Previous owner of this object.</param>
|
|
public override void OnOwnershipClient(NetworkConnection prevOwner)
|
|
{
|
|
/* Unset taken ownership either way.
|
|
* If the new owner it won't be used,
|
|
* if no longer owner then another client
|
|
* took it. */
|
|
TakingOwnership = false;
|
|
PreviousOwner = base.Owner;
|
|
}
|
|
|
|
[Client]
|
|
|
|
[Obsolete("Use TakeOwnership(bool).")]
|
|
public virtual void TakeOwnership() => TakeOwnership(includeNested: true);
|
|
|
|
/// <summary>
|
|
/// Gives ownership of this to the local client and allows immediate control.
|
|
/// </summary>
|
|
/// <param name="includeNested">True to also take ownership of nested objects.</param>
|
|
public virtual void TakeOwnership(bool includeNested)
|
|
{
|
|
if (!_allowTakeOwnershipSyncVar.Value)
|
|
return;
|
|
//Already owner.
|
|
if (base.IsOwner)
|
|
return;
|
|
|
|
NetworkConnection c = base.ClientManager.Connection;
|
|
TakingOwnership = true;
|
|
//If not server go through the server.
|
|
if (!base.IsServerStarted)
|
|
{
|
|
base.NetworkObject.SetLocalOwnership(c, includeNested);
|
|
ServerTakeOwnership(includeNested);
|
|
}
|
|
//Otherwise take directly without rpcs.
|
|
else
|
|
{
|
|
OnTakeOwnership(c, includeNested);
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Takes ownership of this object.
|
|
/// </summary>
|
|
[ServerRpc(RequireOwnership = false)]
|
|
private void ServerTakeOwnership(bool includeNested, NetworkConnection caller = null)
|
|
{
|
|
OnTakeOwnership(caller, includeNested);
|
|
}
|
|
|
|
[Server]
|
|
|
|
[Obsolete("Use OnTakeOwnership(bool).")]
|
|
protected virtual void OnTakeOwnership(NetworkConnection caller) => OnTakeOwnership(caller, recursive: false);
|
|
|
|
/// <summary>
|
|
/// Called on the server when a client tries to take ownership of this object.
|
|
/// </summary>
|
|
/// <param name="caller">Connection trying to take ownership.</param>
|
|
[Server]
|
|
protected virtual void OnTakeOwnership(NetworkConnection caller, bool recursive)
|
|
{
|
|
//Client somehow disconnected between here and there.
|
|
if (!caller.IsActive)
|
|
return;
|
|
//Feature is not enabled.
|
|
if (!_allowTakeOwnershipSyncVar.Value)
|
|
return;
|
|
//Already owner.
|
|
if (caller == base.Owner)
|
|
return;
|
|
|
|
base.GiveOwnership(caller);
|
|
if (recursive)
|
|
{
|
|
List<NetworkObject> allNested = base.NetworkObject.GetNetworkObjects(GetNetworkObjectOption.AllNestedRecursive);
|
|
|
|
foreach (NetworkObject nob in allNested)
|
|
{
|
|
PredictedOwner po = nob.PredictedOwner;
|
|
if (po != null)
|
|
po.OnTakeOwnership(caller, recursive: true);
|
|
}
|
|
|
|
CollectionCaches<NetworkObject>.Store(allNested);
|
|
}
|
|
/* No need to send a response back because an ownershipchange will handle changes.
|
|
* Although if you were to override with this your own behavior
|
|
* you could send responses for approved/denied. */
|
|
}
|
|
}
|
|
} |