Add StickGame Assets
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
using FishNet.Connection;
|
||||
using FishNet.Object;
|
||||
using FishNet.Observing;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Component.Observing
|
||||
{
|
||||
/// <summary>
|
||||
/// When this observer condition is placed on an object, a client must be within the specified distance to view the object.
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "FishNet/Observers/Distance Condition", fileName = "New Distance Condition")]
|
||||
public class DistanceCondition : ObserverCondition
|
||||
{
|
||||
#region Serialized.
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Tooltip("Maximum distance a client must be within this object to see it.")]
|
||||
[SerializeField]
|
||||
private float _maximumDistance = 100f;
|
||||
/// <summary>
|
||||
/// Maximum distance a client must be within this object to see it.
|
||||
/// </summary>
|
||||
public float MaximumDistance { get => _maximumDistance; set => _maximumDistance = value; }
|
||||
/// <summary>
|
||||
/// Additional percent of distance client must be until this object is hidden. For example, if distance was 100f and percent was 0.5f the client must be 150f units away before this object is hidden again. This can be useful for keeping objects from regularly appearing and disappearing.
|
||||
/// </summary>
|
||||
[Tooltip("Additional percent of distance client must be until this object is hidden. For example, if distance was 100f and percent was 0.5f the client must be 150f units away before this object is hidden again. This can be useful for keeping objects from regularly appearing and disappearing.")]
|
||||
[Range(0f, 1f)]
|
||||
[SerializeField]
|
||||
private float _hideDistancePercent = 0.1f;
|
||||
/// <summary>
|
||||
/// How often this condition may change for a connection. This prevents objects from appearing and disappearing rapidly. A value of 0f will cause the object the update quickly as possible while any other value will be used as a delay.
|
||||
/// </summary>
|
||||
[Obsolete("UpdateFrequency is no longer used.")] //Remove on 2023/06/01
|
||||
[HideInInspector]
|
||||
public float UpdateFrequency;
|
||||
#endregion
|
||||
|
||||
#region Private.
|
||||
/// <summary>
|
||||
/// Tracks when connections may be updated for this object.
|
||||
/// </summary>
|
||||
private Dictionary<NetworkConnection, float> _timedUpdates = new Dictionary<NetworkConnection, float>();
|
||||
#endregion
|
||||
|
||||
public void ConditionConstructor(float maximumDistance)
|
||||
{
|
||||
MaximumDistance = maximumDistance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if the object which this condition resides should be visible to connection.
|
||||
/// </summary>
|
||||
/// <param name="connection">Connection which the condition is being checked for.</param>
|
||||
/// <param name="currentlyAdded">True if the connection currently has visibility of this object.</param>
|
||||
/// <param name="notProcessed">True if the condition was not processed. This can be used to skip processing for performance. While output as true this condition result assumes the previous ConditionMet value.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override bool ConditionMet(NetworkConnection connection, bool currentlyAdded, out bool notProcessed)
|
||||
{
|
||||
//If here then checks are being processed.
|
||||
notProcessed = false;
|
||||
|
||||
float sqrMaximumDistance;
|
||||
/* If already visible then use additional
|
||||
* distance to determine when to hide. */
|
||||
if (currentlyAdded)
|
||||
{
|
||||
float maxModified = (MaximumDistance * (1f + _hideDistancePercent));
|
||||
sqrMaximumDistance = (maxModified * maxModified);
|
||||
}
|
||||
//Not visible, use normal distance.
|
||||
else
|
||||
{
|
||||
sqrMaximumDistance = (MaximumDistance * MaximumDistance);
|
||||
}
|
||||
|
||||
Vector3 thisPosition = NetworkObject.transform.position;
|
||||
foreach (NetworkObject nob in connection.Objects)
|
||||
{
|
||||
//If within distance.
|
||||
if (Vector3.SqrMagnitude(nob.transform.position - thisPosition) <= sqrMaximumDistance)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If here no client objects are within distance. */
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// How a condition is handled.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override ObserverConditionType GetConditionType() => ObserverConditionType.Timed;
|
||||
|
||||
/// <summary>
|
||||
/// Clones referenced ObserverCondition. This must be populated with your conditions settings.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override ObserverCondition Clone()
|
||||
{
|
||||
DistanceCondition copy = ScriptableObject.CreateInstance<DistanceCondition>();
|
||||
copy.ConditionConstructor(MaximumDistance);
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7c3e28fa2e37d1d41b4f63c8a0cc2553
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8e63bfe98ed333f4d9b0e8c81c98c513
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 731898d70776e2341a64ea1f9494299a, type: 3}
|
||||
m_Name: GridCondition
|
||||
m_EditorClassIdentifier:
|
||||
NetworkObject: {fileID: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cc503f7541ebd424c94541e6a767efee
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,48 @@
|
||||
using FishNet.Connection;
|
||||
using FishNet.Object;
|
||||
using FishNet.Observing;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Component.Observing
|
||||
{
|
||||
/// <summary>
|
||||
/// When this observer condition is placed on an object, a client must be within the specified grid accuracy to view the object.
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "FishNet/Observers/Grid Condition", fileName = "New Grid Condition")]
|
||||
public class GridCondition : ObserverCondition
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns if the object which this condition resides should be visible to connection.
|
||||
/// </summary>
|
||||
/// <param name="connection">Connection which the condition is being checked for.</param>
|
||||
/// <param name="currentlyAdded">True if the connection currently has visibility of this object.</param>
|
||||
/// <param name="notProcessed">True if the condition was not processed. This can be used to skip processing for performance. While output as true this condition result assumes the previous ConditionMet value.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override bool ConditionMet(NetworkConnection connection, bool currentlyAdded, out bool notProcessed)
|
||||
{
|
||||
//If here then checks are being processed.
|
||||
notProcessed = false;
|
||||
|
||||
return connection.HashGridEntry.NearbyEntries.Contains(base.NetworkObject.HashGridEntry);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// How a condition is handled.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override ObserverConditionType GetConditionType() => ObserverConditionType.Timed;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Clones referenced ObserverCondition. This must be populated with your conditions settings.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override ObserverCondition Clone()
|
||||
{
|
||||
GridCondition copy = ScriptableObject.CreateInstance<GridCondition>();
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 731898d70776e2341a64ea1f9494299a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,260 @@
|
||||
using FishNet.Managing;
|
||||
using FishNet.Object;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Component.Observing
|
||||
{
|
||||
public class GridEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Position on the grid.
|
||||
/// </summary>
|
||||
public Vector2Int Position;
|
||||
/// <summary>
|
||||
/// This grid entry as well those neighboring it.
|
||||
/// </summary>
|
||||
public HashSet<GridEntry> NearbyEntries;
|
||||
|
||||
public GridEntry() { }
|
||||
public GridEntry(HashSet<GridEntry> nearby)
|
||||
{
|
||||
NearbyEntries = nearby;
|
||||
}
|
||||
|
||||
public void SetValues(Vector2Int position, HashSet<GridEntry> nearby)
|
||||
{
|
||||
Position = position;
|
||||
NearbyEntries = nearby;
|
||||
}
|
||||
public void SetValues(HashSet<GridEntry> nearby)
|
||||
{
|
||||
NearbyEntries = nearby;
|
||||
}
|
||||
public void SetValues(Vector2Int position)
|
||||
{
|
||||
Position = position;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Position = Vector2Int.zero;
|
||||
NearbyEntries.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public class HashGrid : MonoBehaviour
|
||||
{
|
||||
#region Types.
|
||||
public enum GridAxes : byte
|
||||
{
|
||||
XY = 0,
|
||||
YZ = 1,
|
||||
XZ = 2,
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal.
|
||||
/// <summary>
|
||||
/// Value for when grid position is not set.
|
||||
/// </summary>
|
||||
internal static Vector2Int UnsetGridPosition = (Vector2Int.one * int.MaxValue);
|
||||
/// <summary>
|
||||
/// An empty grid entry.
|
||||
/// </summary>
|
||||
internal static GridEntry EmptyGridEntry = new GridEntry(new HashSet<GridEntry>());
|
||||
#endregion
|
||||
|
||||
#region Serialized.
|
||||
/// <summary>
|
||||
/// Axes of world space to base the grid on.
|
||||
/// </summary>
|
||||
[Tooltip("Axes of world space to base the grid on.")]
|
||||
[SerializeField]
|
||||
private GridAxes _gridAxes = GridAxes.XY;
|
||||
/// <summary>
|
||||
/// Accuracy of the grid. Objects will be considered nearby if they are within this number of units. Lower values may be more expensive.
|
||||
/// </summary>
|
||||
[Tooltip("Accuracy of the grid. Objects will be considered nearby if they are within this number of units. Lower values may be more expensive.")]
|
||||
[Range(1, ushort.MaxValue)]
|
||||
[SerializeField]
|
||||
private ushort _accuracy = 10;
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Half of accuracy.
|
||||
/// </summary>
|
||||
private int _halfAccuracy;
|
||||
/// <summary>
|
||||
/// Cache of List<GridEntry>.
|
||||
/// </summary>
|
||||
private Stack<HashSet<GridEntry>> _gridEntryHashSetCache = new Stack<HashSet<GridEntry>>();
|
||||
/// <summary>
|
||||
/// Cache of GridEntrys.
|
||||
/// </summary>
|
||||
private Stack<GridEntry> _gridEntryCache = new Stack<GridEntry>();
|
||||
/// <summary>
|
||||
/// All grid entries.
|
||||
/// </summary>
|
||||
private Dictionary<Vector2Int, GridEntry> _gridEntries = new Dictionary<Vector2Int, GridEntry>();
|
||||
/// <summary>
|
||||
/// NetworkManager this is used with.
|
||||
/// </summary>
|
||||
private NetworkManager _networkManager;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_networkManager = GetComponentInParent<NetworkManager>();
|
||||
|
||||
if (_networkManager == null)
|
||||
{
|
||||
NetworkManager.StaticLogError($"NetworkManager not found on object or within parent of {gameObject.name}. The {GetType().Name} must be placed on or beneath a NetworkManager.");
|
||||
return;
|
||||
}
|
||||
|
||||
//Make sure there is only one per networkmanager.
|
||||
if (!_networkManager.HasInstance<HashGrid>())
|
||||
{
|
||||
_halfAccuracy = Mathf.CeilToInt((float)_accuracy / 2f);
|
||||
_networkManager.RegisterInstance(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets out values to be used when creating a new GridEntry.
|
||||
/// </summary>
|
||||
private void OutputNewGridCollections(out GridEntry gridEntry, out HashSet<GridEntry> gridEntries)
|
||||
{
|
||||
const int cacheCount = 100;
|
||||
//Build caches if needed.
|
||||
if (_gridEntryHashSetCache.Count == 0)
|
||||
{
|
||||
for (int i = 0; i < cacheCount; i++)
|
||||
_gridEntryHashSetCache.Push(new HashSet<GridEntry>());
|
||||
}
|
||||
if (_gridEntryCache.Count == 0)
|
||||
{
|
||||
for (int i = 0; i < cacheCount; i++)
|
||||
_gridEntryCache.Push(new GridEntry());
|
||||
}
|
||||
|
||||
gridEntry = _gridEntryCache.Pop();
|
||||
gridEntries = _gridEntryHashSetCache.Pop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a GridEntry for position and inserts it into GridEntries.
|
||||
/// </summary>
|
||||
private GridEntry CreateGridEntry(Vector2Int position)
|
||||
{
|
||||
//Make this into a stack that populates a number of entries when empty. also populate with some in awake.
|
||||
GridEntry newEntry;
|
||||
HashSet<GridEntry> nearby;
|
||||
OutputNewGridCollections(out newEntry, out nearby);
|
||||
newEntry.SetValues(position, nearby);
|
||||
//Add to grid.
|
||||
_gridEntries[position] = newEntry;
|
||||
|
||||
//Get neighbors.
|
||||
int endX = (position.x + 1);
|
||||
int endY = (position.y + 1);
|
||||
int iterations = 0;
|
||||
for (int x = (position.x - 1); x <= endX; x++)
|
||||
{
|
||||
for (int y = (position.y - 1); y <= endY; y++)
|
||||
{
|
||||
iterations++;
|
||||
if (_gridEntries.TryGetValue(new Vector2Int(x, y), out GridEntry foundEntry))
|
||||
{
|
||||
nearby.Add(foundEntry);
|
||||
foundEntry.NearbyEntries.Add(newEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newEntry;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets grid positions and neighbors for a NetworkObject.
|
||||
/// </summary>
|
||||
internal void GetNearbyHashGridPositions(NetworkObject nob, ref HashSet<Vector2Int> collection)
|
||||
{
|
||||
Vector2Int position = GetHashGridPosition(nob);
|
||||
//Get neighbors.
|
||||
int endX = (position.x + 1);
|
||||
int endY = (position.y + 1);
|
||||
for (int x = (position.x - 1); x < endX; x++)
|
||||
{
|
||||
for (int y = (position.y - 1); y < endY; y++)
|
||||
collection.Add(new Vector2Int(x, y));
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the grid position to use for a NetworkObjects current position.
|
||||
/// </summary>
|
||||
internal Vector2Int GetHashGridPosition(NetworkObject nob)
|
||||
{
|
||||
Vector3 position = nob.transform.position;
|
||||
float fX;
|
||||
float fY;
|
||||
if (_gridAxes == GridAxes.XY)
|
||||
{
|
||||
fX = position.x;
|
||||
fY = position.y;
|
||||
}
|
||||
else if (_gridAxes == GridAxes.XZ)
|
||||
{
|
||||
fX = position.x;
|
||||
fY = position.z;
|
||||
}
|
||||
else if (_gridAxes == GridAxes.YZ)
|
||||
{
|
||||
fX = position.y;
|
||||
fY = position.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
_networkManager?.LogError($"GridAxes of {_gridAxes.ToString()} is not handled.");
|
||||
return default;
|
||||
}
|
||||
|
||||
return new Vector2Int(
|
||||
(int)fX / _halfAccuracy
|
||||
, (int)fY / _halfAccuracy
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets a GridEntry for a NetworkObject, creating the entry if needed.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal GridEntry GetGridEntry(NetworkObject nob)
|
||||
{
|
||||
Vector2Int pos = GetHashGridPosition(nob);
|
||||
return GetGridEntry(pos);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a GridEntry for position, creating the entry if needed.
|
||||
/// </summary>
|
||||
internal GridEntry GetGridEntry(Vector2Int position)
|
||||
{
|
||||
GridEntry result;
|
||||
if (!_gridEntries.TryGetValue(position, out result))
|
||||
result = CreateGridEntry(position);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a9fc3aafb02eb74fb571c300f846bf2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,31 @@
|
||||
using FishNet.Connection;
|
||||
using FishNet.Observing;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Component.Observing
|
||||
{
|
||||
[CreateAssetMenu(menuName = "FishNet/Observers/Host Only Condition", fileName = "New Host Only Condition")]
|
||||
public class HostOnlyCondition : ObserverCondition
|
||||
{
|
||||
public override bool ConditionMet(NetworkConnection connection, bool currentlyAdded, out bool notProcessed)
|
||||
{
|
||||
notProcessed = false;
|
||||
/* Only return true if connection is the local client.
|
||||
* This check only runs on the server, so if local client
|
||||
* is true then they must also be the server (clientHost). */
|
||||
return (base.NetworkObject.ClientManager.Connection == connection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// How a condition is handled.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override ObserverConditionType GetConditionType() => ObserverConditionType.Normal;
|
||||
|
||||
public override ObserverCondition Clone()
|
||||
{
|
||||
HostOnlyCondition copy = ScriptableObject.CreateInstance<HostOnlyCondition>();
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa62c0af0c0a4da46b03309dcd3858c3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,802 @@
|
||||
using FishNet.Connection;
|
||||
using FishNet.Managing;
|
||||
using FishNet.Managing.Logging;
|
||||
using FishNet.Managing.Server;
|
||||
using FishNet.Object;
|
||||
using FishNet.Observing;
|
||||
using FishNet.Utility.Extension;
|
||||
using FishNet.Utility.Performance;
|
||||
using GameKit.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Component.Observing
|
||||
{
|
||||
/// <summary>
|
||||
/// When this observer condition is placed on an object, a client must be within the same match to view the object.
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "FishNet/Observers/Match Condition", fileName = "New Match Condition")]
|
||||
public class MatchCondition : ObserverCondition
|
||||
{
|
||||
#region Types.
|
||||
/// <summary>
|
||||
/// MatchCondition collections used.
|
||||
/// </summary>
|
||||
public class ConditionCollections
|
||||
{
|
||||
public Dictionary<int, HashSet<NetworkConnection>> MatchConnections = new Dictionary<int, HashSet<NetworkConnection>>();
|
||||
public Dictionary<NetworkConnection, HashSet<int>> ConnectionMatches = new Dictionary<NetworkConnection, HashSet<int>>();
|
||||
public Dictionary<int, HashSet<NetworkObject>> MatchObjects = new Dictionary<int, HashSet<NetworkObject>>();
|
||||
public Dictionary<NetworkObject, HashSet<int>> ObjectMatches = new Dictionary<NetworkObject, HashSet<int>>();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private.
|
||||
[Obsolete("Use GetMatchConnections(NetworkManager).")] //Remove on 2023/06/01
|
||||
public static Dictionary<int, HashSet<NetworkConnection>> MatchConnections => GetMatchConnections();
|
||||
[Obsolete("Use GetConnectionMatches(NetworkManager).")] //Remove on 2024/01/01.
|
||||
public static Dictionary<NetworkConnection, HashSet<int>> ConnectionMatch => GetConnectionMatches();
|
||||
[Obsolete("Use GetMatchObjects(NetworkManager).")] //Remove on 2024/01/01.
|
||||
public static Dictionary<int, HashSet<NetworkObject>> MatchObject => GetMatchObjects();
|
||||
[Obsolete("Use GetObjectMatches(NetworkManager).")] //Remove on 2024/01/01.
|
||||
public static Dictionary<NetworkObject, HashSet<int>> ObjectMatch => GetObjectMatches();
|
||||
/// <summary>
|
||||
/// Collections for each NetworkManager instance.
|
||||
/// </summary>
|
||||
private static Dictionary<NetworkManager, ConditionCollections> _collections = new Dictionary<NetworkManager, ConditionCollections>();
|
||||
#endregion
|
||||
|
||||
#region Collections.
|
||||
/// <summary>
|
||||
/// Stores collections for a manager.
|
||||
/// </summary>
|
||||
/// <param name="manager"></param>
|
||||
internal static void StoreCollections(NetworkManager manager)
|
||||
{
|
||||
ConditionCollections cc;
|
||||
if (!_collections.TryGetValue(manager, out cc))
|
||||
return;
|
||||
|
||||
foreach (HashSet<int> item in cc.ObjectMatches.Values)
|
||||
CollectionCaches<int>.Store(item);
|
||||
foreach (HashSet<NetworkConnection> item in cc.MatchConnections.Values)
|
||||
CollectionCaches<NetworkConnection>.Store(item);
|
||||
foreach (HashSet<NetworkObject> item in cc.MatchObjects.Values)
|
||||
CollectionCaches<NetworkObject>.Store(item);
|
||||
foreach (HashSet<int> item in cc.ConnectionMatches.Values)
|
||||
CollectionCaches<int>.Store(item);
|
||||
|
||||
_collections.Remove(manager);
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets condition collections for a NetowrkManager.
|
||||
/// </summary>
|
||||
private static ConditionCollections GetCollections(NetworkManager manager = null)
|
||||
{
|
||||
if (manager == null)
|
||||
manager = InstanceFinder.NetworkManager;
|
||||
|
||||
ConditionCollections cc;
|
||||
if (!_collections.TryGetValue(manager, out cc))
|
||||
{
|
||||
cc = new ConditionCollections();
|
||||
_collections[manager] = cc;
|
||||
}
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns matches and connections in each match.
|
||||
/// </summary>
|
||||
/// <param name="manager">NetworkManager to use.</param>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<int, HashSet<NetworkConnection>> GetMatchConnections(NetworkManager manager = null)
|
||||
{
|
||||
ConditionCollections cc = GetCollections(manager);
|
||||
return cc.MatchConnections;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns connections and the matches they are in.
|
||||
/// </summary>
|
||||
/// <param name="manager">NetworkManager to use.</param>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<NetworkConnection, HashSet<int>> GetConnectionMatches(NetworkManager manager = null)
|
||||
{
|
||||
ConditionCollections cc = GetCollections(manager);
|
||||
return cc.ConnectionMatches;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns matches and objects within each match.
|
||||
/// </summary>
|
||||
/// <param name="manager">NetworkManager to use.</param>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<int, HashSet<NetworkObject>> GetMatchObjects(NetworkManager manager = null)
|
||||
{
|
||||
ConditionCollections cc = GetCollections(manager);
|
||||
return cc.MatchObjects;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns objects and the matches they are in.
|
||||
/// </summary>
|
||||
/// <param name="manager">NetworkManager to use.</param>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<NetworkObject, HashSet<int>> GetObjectMatches(NetworkManager manager = null)
|
||||
{
|
||||
ConditionCollections cc = GetCollections(manager);
|
||||
return cc.ObjectMatches;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public void ConditionConstructor() { }
|
||||
|
||||
#region Add to match NetworkConnection.
|
||||
/// <summary>
|
||||
/// Adds a connection to a match.
|
||||
/// </summary>
|
||||
private static bool AddToMatch(int match, NetworkConnection conn, NetworkManager manager, bool replaceMatch, bool rebuild)
|
||||
{
|
||||
Dictionary<int, HashSet<NetworkConnection>> matchConnections = GetMatchConnections(manager);
|
||||
|
||||
if (replaceMatch)
|
||||
RemoveFromMatchesWithoutRebuild(conn, manager);
|
||||
|
||||
/* Get current connections in match. This is where the conn
|
||||
* will be added to. If does not exist then make new
|
||||
* collection. */
|
||||
HashSet<NetworkConnection> matchConnValues;
|
||||
if (!matchConnections.TryGetValueIL2CPP(match, out matchConnValues))
|
||||
{
|
||||
matchConnValues = CollectionCaches<NetworkConnection>.RetrieveHashSet();
|
||||
matchConnections.Add(match, matchConnValues);
|
||||
}
|
||||
|
||||
bool r = matchConnValues.Add(conn);
|
||||
AddToConnectionMatches(conn, match, manager);
|
||||
if (r && rebuild)
|
||||
GetServerObjects(manager).RebuildObservers();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a connection to a match.
|
||||
/// </summary>
|
||||
/// <param name="match">Match to add conn to.</param>
|
||||
/// <param name="conn">Connection to add to match.</param>
|
||||
/// <param name="manager">NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used.</param>
|
||||
/// <param name="replaceMatch">True to replace other matches with the new match.</param>
|
||||
public static void AddToMatch(int match, NetworkConnection conn, NetworkManager manager = null, bool replaceMatch = false)
|
||||
{
|
||||
AddToMatch(match, conn, manager, replaceMatch, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates a connection within ConnectionMatches to contain match.
|
||||
/// </summary>
|
||||
private static void AddToConnectionMatches(NetworkConnection conn, int match, NetworkManager manager)
|
||||
{
|
||||
Dictionary<NetworkConnection, HashSet<int>> connectionMatches = GetConnectionMatches(manager);
|
||||
|
||||
HashSet<int> matches;
|
||||
if (!connectionMatches.TryGetValueIL2CPP(conn, out matches))
|
||||
{
|
||||
matches = CollectionCaches<int>.RetrieveHashSet();
|
||||
connectionMatches[conn] = matches;
|
||||
}
|
||||
|
||||
matches.Add(match);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds connections to a match.
|
||||
/// </summary>
|
||||
/// <param name="match">Match to add conns to.</param>
|
||||
/// <param name="conns">Connections to add to match.</param>
|
||||
/// <param name="manager">NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used.</param>
|
||||
/// <param name="replaceMatch">True to replace other matches with the new match.</param>
|
||||
public static void AddToMatch(int match, NetworkConnection[] conns, NetworkManager manager = null, bool replaceMatch = false)
|
||||
{
|
||||
AddToMatch(match, conns.ToList(), manager, replaceMatch);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds connections to a match.
|
||||
/// </summary>
|
||||
/// <param name="match">Match to add conns to.</param>
|
||||
/// <param name="conns">Connections to add to match.</param>
|
||||
/// <param name="manager">NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used.</param>
|
||||
/// <param name="replaceMatch">True to replace other matches with the new match.</param>
|
||||
public static void AddToMatch(int match, List<NetworkConnection> conns, NetworkManager manager = null, bool replaceMatch = false)
|
||||
{
|
||||
bool added = false;
|
||||
foreach (NetworkConnection c in conns)
|
||||
added |= AddToMatch(match, c, manager, replaceMatch, false);
|
||||
|
||||
if (added)
|
||||
GetServerObjects(manager).RebuildObservers();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Add to match NetworkObject.
|
||||
/// <summary>
|
||||
/// Adds an object to a match.
|
||||
/// </summary>
|
||||
private static bool AddToMatch(int match, NetworkObject nob, NetworkManager manager, bool replaceMatch, bool rebuild)
|
||||
{
|
||||
Dictionary<int, HashSet<NetworkObject>> matchObjects = GetMatchObjects(manager);
|
||||
Dictionary<NetworkObject, HashSet<int>> objectMatches = GetObjectMatches(manager);
|
||||
|
||||
if (replaceMatch)
|
||||
RemoveFromMatchWithoutRebuild(nob, manager);
|
||||
|
||||
HashSet<NetworkObject> matchObjectsValues;
|
||||
if (!matchObjects.TryGetValueIL2CPP(match, out matchObjectsValues))
|
||||
{
|
||||
matchObjectsValues = CollectionCaches<NetworkObject>.RetrieveHashSet();
|
||||
matchObjects.Add(match, matchObjectsValues);
|
||||
}
|
||||
bool added = matchObjectsValues.Add(nob);
|
||||
|
||||
/* Also add to reverse dictionary. */
|
||||
HashSet<int> objectMatchesValues;
|
||||
if (!objectMatches.TryGetValueIL2CPP(nob, out objectMatchesValues))
|
||||
{
|
||||
objectMatchesValues = CollectionCaches<int>.RetrieveHashSet();
|
||||
objectMatches.Add(nob, objectMatchesValues);
|
||||
}
|
||||
objectMatchesValues.Add(match);
|
||||
|
||||
if (added && rebuild)
|
||||
GetServerObjects(manager).RebuildObservers();
|
||||
|
||||
return added;
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds an object to a match.
|
||||
/// </summary>
|
||||
/// <param name="match">Match to add conn to.</param>
|
||||
/// <param name="nob">Connection to add to match.</param>
|
||||
/// <param name="manager">NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used.</param>
|
||||
/// <param name="replaceMatch">True to replace other matches with the new match.</param>
|
||||
public static void AddToMatch(int match, NetworkObject nob, NetworkManager manager = null, bool replaceMatch = false)
|
||||
{
|
||||
AddToMatch(match, nob, manager, replaceMatch, true);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds objects to a match.
|
||||
/// </summary>
|
||||
/// <param name="match">Match to add conns to.</param>
|
||||
/// <param name="nobs">Connections to add to match.</param>
|
||||
/// <param name="manager">NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used.</param>
|
||||
/// <param name="replaceMatch">True to replace other matches with the new match.</param>
|
||||
public static void AddToMatch(int match, NetworkObject[] nobs, NetworkManager manager = null, bool replaceMatch = false)
|
||||
{
|
||||
AddToMatch(match, nobs.ToList(), manager, replaceMatch);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds objects to a match.
|
||||
/// </summary>
|
||||
/// <param name="match">Match to add conns to.</param>
|
||||
/// <param name="nobs">Connections to add to match.</param>
|
||||
/// <param name="manager">NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used.</param>
|
||||
/// <param name="replaceMatch">True to replace other matches with the new match.</param>
|
||||
public static void AddToMatch(int match, List<NetworkObject> nobs, NetworkManager manager = null, bool replaceMatch = false)
|
||||
{
|
||||
//Remove from current matches.
|
||||
if (replaceMatch)
|
||||
{
|
||||
foreach (NetworkObject n in nobs)
|
||||
RemoveFromMatchWithoutRebuild(n, manager);
|
||||
}
|
||||
|
||||
bool added = false;
|
||||
//Add to matches.
|
||||
foreach (NetworkObject n in nobs)
|
||||
added |= AddToMatch(match, n, manager, replaceMatch, false);
|
||||
|
||||
if (added)
|
||||
GetServerObjects(manager).RebuildObservers();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TryRemoveKey.
|
||||
/// <summary>
|
||||
/// Removes a key if values are empty, and caches values.
|
||||
/// </summary>
|
||||
private static void TryRemoveKey(Dictionary<int, HashSet<NetworkObject>> dict, int key, HashSet<NetworkObject> value)
|
||||
{
|
||||
bool isEmpty = true;
|
||||
if (value != null)
|
||||
{
|
||||
isEmpty = (value.Count == 0);
|
||||
if (isEmpty)
|
||||
CollectionCaches<NetworkObject>.Store(value);
|
||||
}
|
||||
|
||||
if (isEmpty)
|
||||
dict.Remove(key);
|
||||
}
|
||||
/// <summary>
|
||||
/// Removes a key if values are empty, and caches values.
|
||||
/// </summary>
|
||||
private static void TryRemoveKey(Dictionary<int, HashSet<NetworkObject>> dict, int key)
|
||||
{
|
||||
HashSet<NetworkObject> value;
|
||||
dict.TryGetValue(key, out value);
|
||||
TryRemoveKey(dict, key, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a key if values are empty, and caches values.
|
||||
/// </summary>
|
||||
private static void TryRemoveKey(Dictionary<NetworkObject, HashSet<int>> dict, NetworkObject key, HashSet<int> value)
|
||||
{
|
||||
bool isEmpty = true;
|
||||
if (value != null)
|
||||
{
|
||||
isEmpty = (value.Count == 0);
|
||||
if (isEmpty)
|
||||
CollectionCaches<int>.Store(value);
|
||||
}
|
||||
|
||||
if (isEmpty)
|
||||
dict.Remove(key);
|
||||
}
|
||||
/// <summary>
|
||||
/// Removes a key if values are empty, and caches values.
|
||||
/// </summary>
|
||||
private static void TryRemoveKey(Dictionary<NetworkObject, HashSet<int>> dict, NetworkObject key)
|
||||
{
|
||||
HashSet<int> value;
|
||||
dict.TryGetValueIL2CPP(key, out value);
|
||||
TryRemoveKey(dict, key, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a key if values are empty, and caches values.
|
||||
/// </summary>
|
||||
private static void TryRemoveKey(Dictionary<int, HashSet<NetworkConnection>> dict, int key, HashSet<NetworkConnection> value)
|
||||
{
|
||||
bool isEmpty = true;
|
||||
if (value != null)
|
||||
{
|
||||
isEmpty = (value.Count == 0);
|
||||
if (isEmpty)
|
||||
CollectionCaches<NetworkConnection>.Store(value);
|
||||
}
|
||||
|
||||
if (isEmpty)
|
||||
dict.Remove(key);
|
||||
}
|
||||
/// <summary>
|
||||
/// Removes a key if values are empty, and caches values.
|
||||
/// </summary>
|
||||
private static void TryRemoveKey(Dictionary<int, HashSet<NetworkConnection>> dict, int key)
|
||||
{
|
||||
HashSet<NetworkConnection> value;
|
||||
dict.TryGetValueIL2CPP(key, out value);
|
||||
TryRemoveKey(dict, key, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a key if values are empty, and caches values.
|
||||
/// </summary>
|
||||
private static void TryRemoveKey(Dictionary<NetworkConnection, HashSet<int>> dict, NetworkConnection key, HashSet<int> value)
|
||||
{
|
||||
bool isEmpty = true;
|
||||
if (value != null)
|
||||
{
|
||||
isEmpty = (value.Count == 0);
|
||||
if (isEmpty)
|
||||
CollectionCaches<int>.Store(value);
|
||||
}
|
||||
|
||||
if (isEmpty)
|
||||
dict.Remove(key);
|
||||
}
|
||||
/// <summary>
|
||||
/// Removes a key and caches collections where needed.
|
||||
/// </summary>
|
||||
private static void TryRemoveKey(Dictionary<NetworkConnection, HashSet<int>> dict, NetworkConnection key)
|
||||
{
|
||||
HashSet<int> value;
|
||||
dict.TryGetValueIL2CPP(key, out value);
|
||||
TryRemoveKey(dict, key, value);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Remove from match NetworkConnection.
|
||||
/// <summary>
|
||||
/// Removes a connection from all matches without rebuilding observers.
|
||||
/// </summary>
|
||||
/// <param name="conn">Connection to remove from matches.</param>
|
||||
/// <param name="manager">NetworkManager connection belongs to. This is not currently used.</param>
|
||||
internal static bool RemoveFromMatchesWithoutRebuild(NetworkConnection conn, NetworkManager manager)
|
||||
{
|
||||
Dictionary<NetworkConnection, HashSet<int>> connectionMatches = GetConnectionMatches(manager);
|
||||
Dictionary<int, HashSet<NetworkConnection>> matchConnections = GetMatchConnections(manager);
|
||||
|
||||
bool removed = false;
|
||||
//If found to be in a match.
|
||||
if (connectionMatches.TryGetValueIL2CPP(conn, out HashSet<int> connectionMatchesValues))
|
||||
{
|
||||
removed = (connectionMatchesValues.Count > 0);
|
||||
foreach (int m in connectionMatchesValues)
|
||||
{
|
||||
HashSet<NetworkConnection> matchConnsValues;
|
||||
//If match is found.
|
||||
if (matchConnections.TryGetValue(m, out matchConnsValues))
|
||||
{
|
||||
matchConnsValues.Remove(conn);
|
||||
TryRemoveKey(matchConnections, m, matchConnsValues);
|
||||
}
|
||||
}
|
||||
|
||||
//Clear matches connection is in.
|
||||
connectionMatchesValues.Clear();
|
||||
//Remove from connectionMatches.
|
||||
TryRemoveKey(connectionMatches, conn, connectionMatchesValues);
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a connection from all matches.
|
||||
/// </summary>
|
||||
/// <param name="conn">NetworkConnection to remove.</param>
|
||||
/// <param name="manager">NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used.</param>
|
||||
public static void RemoveFromMatch(NetworkConnection conn, NetworkManager manager)
|
||||
{
|
||||
bool removed = RemoveFromMatchesWithoutRebuild(conn, manager);
|
||||
if (removed)
|
||||
GetServerObjects(manager).RebuildObservers();
|
||||
}
|
||||
/// <summary>
|
||||
/// Removes a connection from a match.
|
||||
/// </summary>
|
||||
private static bool RemoveFromMatch(int match, NetworkConnection conn, NetworkManager manager, bool rebuild)
|
||||
{
|
||||
Dictionary<NetworkConnection, HashSet<int>> connectionMatches = GetConnectionMatches(manager);
|
||||
Dictionary<int, HashSet<NetworkConnection>> matchConnections = GetMatchConnections(manager);
|
||||
|
||||
bool removed = false;
|
||||
HashSet<NetworkConnection> matchConnsValues;
|
||||
if (matchConnections.TryGetValueIL2CPP(match, out matchConnsValues))
|
||||
{
|
||||
removed |= matchConnsValues.Remove(conn);
|
||||
HashSet<int> connectionMatchesValues;
|
||||
if (connectionMatches.TryGetValueIL2CPP(conn, out connectionMatchesValues))
|
||||
{
|
||||
connectionMatchesValues.Remove(match);
|
||||
TryRemoveKey(connectionMatches, conn, connectionMatchesValues);
|
||||
}
|
||||
if (removed && rebuild)
|
||||
{
|
||||
TryRemoveKey(matchConnections, match, matchConnsValues);
|
||||
GetServerObjects(manager).RebuildObservers();
|
||||
}
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
/// <summary>
|
||||
/// Removes a connection from a match.
|
||||
/// </summary>
|
||||
/// <param name="match">Match to remove conn from.</param>
|
||||
/// <param name="conn">Connection to remove from match.</param>
|
||||
/// <param name="manager">NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool RemoveFromMatch(int match, NetworkConnection conn, NetworkManager manager = null)
|
||||
{
|
||||
return RemoveFromMatch(match, conn, manager, true);
|
||||
}
|
||||
/// <summary>
|
||||
/// Removes connections from a match.
|
||||
/// </summary>
|
||||
/// <param name="match">Match to remove conns from.</param>
|
||||
/// <param name="conns">Connections to remove from match.</param>
|
||||
/// <param name="manager">NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void RemoveFromMatch(int match, NetworkConnection[] conns, NetworkManager manager)
|
||||
{
|
||||
RemoveFromMatch(match, conns.ToList(), manager);
|
||||
}
|
||||
/// <summary>
|
||||
/// Removes connections from a match.
|
||||
/// </summary>
|
||||
/// <param name="match">Match to remove conns from.</param>
|
||||
/// <param name="conns">Connections to remove from match.</param>
|
||||
/// <param name="manager">NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void RemoveFromMatch(int match, List<NetworkConnection> conns, NetworkManager manager)
|
||||
{
|
||||
bool removed = false;
|
||||
foreach (NetworkConnection c in conns)
|
||||
removed |= RemoveFromMatch(match, c, manager, false);
|
||||
|
||||
if (removed)
|
||||
GetServerObjects(manager).RebuildObservers();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Remove from match NetworkObject.
|
||||
/// <summary>
|
||||
/// Removes a network object from any match without rebuilding observers.
|
||||
/// </summary>
|
||||
/// <param name="nob">NetworkObject to remove.</param>
|
||||
/// <param name="manager">Manager which the network object belongs to. This value is not yet used.</param>
|
||||
internal static bool RemoveFromMatchWithoutRebuild(NetworkObject nob, NetworkManager manager)
|
||||
{
|
||||
Dictionary<NetworkObject, HashSet<int>> objectMatches = GetObjectMatches(manager);
|
||||
Dictionary<int, HashSet<NetworkObject>> matchObjects = GetMatchObjects(manager);
|
||||
|
||||
HashSet<int> objectMatchesValues;
|
||||
bool removed = false;
|
||||
//If found to be in a match.
|
||||
if (objectMatches.TryGetValueIL2CPP(nob, out objectMatchesValues))
|
||||
{
|
||||
removed = (objectMatchesValues.Count > 0);
|
||||
foreach (int m in objectMatchesValues)
|
||||
{
|
||||
//If match is found.
|
||||
if (matchObjects.TryGetValue(m, out HashSet<NetworkObject> matchObjectsValues))
|
||||
{
|
||||
matchObjectsValues.Remove(nob);
|
||||
TryRemoveKey(matchObjects, m, matchObjectsValues);
|
||||
}
|
||||
}
|
||||
|
||||
//Since object is being removed from all matches this can be cleared.
|
||||
objectMatchesValues.Clear();
|
||||
TryRemoveKey(objectMatches, nob, objectMatchesValues);
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
/// <summary>
|
||||
/// Removes nob from all matches.
|
||||
/// </summary>
|
||||
/// <param name="nob">NetworkObject to remove.</param>
|
||||
/// <param name="manager">NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used.</param>
|
||||
public static bool RemoveFromMatch(NetworkObject nob, NetworkManager manager = null)
|
||||
{
|
||||
bool removed = RemoveFromMatchWithoutRebuild(nob, manager);
|
||||
if (removed)
|
||||
GetServerObjects(manager).RebuildObservers(nob);
|
||||
|
||||
return removed;
|
||||
}
|
||||
/// <summary>
|
||||
/// Removes a network object from all matches.
|
||||
/// </summary>
|
||||
/// <param name="nobs">NetworkObjects to remove.</param>
|
||||
/// <param name="manager">NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used.</param>
|
||||
public static void RemoveFromMatch(NetworkObject[] nobs, NetworkManager manager = null)
|
||||
{
|
||||
RemoveFromMatch(nobs.ToList(), manager);
|
||||
}
|
||||
/// <summary>
|
||||
/// Removes network objects from all matches.
|
||||
/// </summary>
|
||||
/// <param name="nobs">NetworkObjects to remove.</param>
|
||||
/// <param name="manager">NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used.</param>
|
||||
public static void RemoveFromMatch(List<NetworkObject> nobs, NetworkManager manager = null)
|
||||
{
|
||||
bool removed = false;
|
||||
foreach (NetworkObject n in nobs)
|
||||
removed |= RemoveFromMatchWithoutRebuild(n, manager);
|
||||
|
||||
if (removed)
|
||||
GetServerObjects(manager).RebuildObservers(nobs);
|
||||
}
|
||||
/// <summary>
|
||||
/// Removes a network object from a match.
|
||||
/// </summary>
|
||||
/// <param name="match">Match to remove conn from.</param>
|
||||
/// <param name="nob">NetworkObject to remove from match.</param>
|
||||
/// <param name="manager">NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void RemoveFromMatch(int match, NetworkObject nob, NetworkManager manager = null)
|
||||
{
|
||||
Dictionary<int, HashSet<NetworkObject>> matchObjects = GetMatchObjects(manager);
|
||||
Dictionary<NetworkObject, HashSet<int>> objectMatches = GetObjectMatches(manager);
|
||||
|
||||
HashSet<NetworkObject> matchObjectsValues;
|
||||
if (matchObjects.TryGetValueIL2CPP(match, out matchObjectsValues))
|
||||
{
|
||||
bool removed = matchObjectsValues.Remove(nob);
|
||||
|
||||
if (removed)
|
||||
{
|
||||
/* Check if nob is still in matches. If not then remove
|
||||
* nob from ObjectMatches. */
|
||||
HashSet<int> objectMatchesValues;
|
||||
if (objectMatches.TryGetValueIL2CPP(nob, out objectMatchesValues))
|
||||
{
|
||||
objectMatchesValues.Remove(match);
|
||||
TryRemoveKey(objectMatches, nob, objectMatchesValues);
|
||||
}
|
||||
|
||||
TryRemoveKey(matchObjects, match, matchObjectsValues);
|
||||
GetServerObjects(manager).RebuildObservers(nob);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Removes network objects from a match.
|
||||
/// </summary>
|
||||
/// <param name="match">Match to remove conns from.</param>
|
||||
/// <param name="nobs">NetworkObjects to remove from match.</param>
|
||||
/// <param name="manager">NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void RemoveFromMatch(int match, NetworkObject[] nobs, NetworkManager manager = null)
|
||||
{
|
||||
Dictionary<int, HashSet<NetworkObject>> matchObjects = GetMatchObjects(manager);
|
||||
Dictionary<NetworkObject, HashSet<int>> objectMatches = GetObjectMatches(manager);
|
||||
|
||||
if (matchObjects.TryGetValueIL2CPP(match, out HashSet<NetworkObject> matchObjectsValues))
|
||||
{
|
||||
bool removed = false;
|
||||
for (int i = 0; i < nobs.Length; i++)
|
||||
{
|
||||
NetworkObject n = nobs[i];
|
||||
removed |= matchObjectsValues.Remove(n);
|
||||
objectMatches.Remove(n);
|
||||
}
|
||||
|
||||
if (removed)
|
||||
{
|
||||
TryRemoveKey(matchObjects, match, matchObjectsValues);
|
||||
GetServerObjects(manager).RebuildObservers(nobs);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Removes network objects from a match.
|
||||
/// </summary>
|
||||
/// <param name="match">Match to remove conns from.</param>
|
||||
/// <param name="nobs">NetworkObjects to remove from match.</param>
|
||||
/// <param name="manager">NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void RemoveFromMatch(int match, List<NetworkObject> nobs, NetworkManager manager = null)
|
||||
{
|
||||
Dictionary<int, HashSet<NetworkObject>> matchObjects = GetMatchObjects(manager);
|
||||
Dictionary<NetworkObject, HashSet<int>> objectMatches = GetObjectMatches(manager);
|
||||
|
||||
if (matchObjects.TryGetValueIL2CPP(match, out HashSet<NetworkObject> matchObjectsValues))
|
||||
{
|
||||
bool removed = false;
|
||||
for (int i = 0; i < nobs.Count; i++)
|
||||
{
|
||||
NetworkObject n = nobs[i];
|
||||
removed |= matchObjectsValues.Remove(n);
|
||||
objectMatches.Remove(n);
|
||||
}
|
||||
|
||||
if (removed)
|
||||
{
|
||||
TryRemoveKey(matchObjects, match, matchObjectsValues);
|
||||
GetServerObjects(manager).RebuildObservers(nobs);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Returns if the object which this condition resides should be visible to connection.
|
||||
/// </summary>
|
||||
/// <param name="connection">Connection which the condition is being checked for.</param>
|
||||
/// <param name="currentlyAdded">True if the connection currently has visibility of this object.</param>
|
||||
/// <param name="notProcessed">True if the condition was not processed. This can be used to skip processing for performance. While output as true this condition result assumes the previous ConditionMet value.</param>
|
||||
public override bool ConditionMet(NetworkConnection connection, bool currentlyAdded, out bool notProcessed)
|
||||
{
|
||||
//If here then checks are being processed.
|
||||
notProcessed = false;
|
||||
NetworkConnection owner = base.NetworkObject.Owner;
|
||||
/* If object is owned then check if owner
|
||||
* and connection share a match. */
|
||||
if (owner.IsValid)
|
||||
{
|
||||
Dictionary<NetworkConnection, HashSet<int>> connectionMatches = GetConnectionMatches(base.NetworkObject.NetworkManager);
|
||||
//Output owner matches.
|
||||
HashSet<int> ownerMatches;
|
||||
//bool ownerMatchesFound = connectionMatches.TryGetValueIL2CPP(owner, out ownerMatches);
|
||||
////Connection isn't in a match.
|
||||
//if (!connectionMatches.TryGetValueIL2CPP(connection, out HashSet<int> connMatches))
|
||||
//{
|
||||
// //If owner is also not in a match then they can see each other.
|
||||
// return !ownerMatchesFound;
|
||||
//}
|
||||
/* This objects owner is not in a match so treat it like
|
||||
* a networkobject without an owner. Objects not in matches
|
||||
* are visible to everyone. */
|
||||
if (!connectionMatches.TryGetValueIL2CPP(owner, out ownerMatches))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
/* Owner is in a match. See if connection is in any of
|
||||
* the same matches. */
|
||||
else
|
||||
{
|
||||
//If conn is not in any matches then they cannot see this object, as it is.
|
||||
if (!connectionMatches.TryGetValue(connection, out HashSet<int> connMatches))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//See if conn is in any of the same matches.
|
||||
else
|
||||
{
|
||||
foreach (int m in connMatches)
|
||||
{
|
||||
if (ownerMatches.Contains(m))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//Fall through, not found.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/* If no owner see if the object is in a match and if so
|
||||
* then compare that. */
|
||||
else
|
||||
{
|
||||
Dictionary<NetworkObject, HashSet<int>> objectMatches = GetObjectMatches(base.NetworkObject.NetworkManager);
|
||||
Dictionary<NetworkConnection, HashSet<int>> connectionMatches = GetConnectionMatches(base.NetworkObject.NetworkManager);
|
||||
|
||||
//Object isn't in a match. Is visible with no owner.
|
||||
HashSet<int> objectMatchesValues;
|
||||
if (!objectMatches.TryGetValueIL2CPP(base.NetworkObject, out objectMatchesValues))
|
||||
return true;
|
||||
/* See if connection is in any of same matches as the object.
|
||||
* If connection isn't in a match then it fails as at this point
|
||||
* object would be, but not conn. */
|
||||
if (!connectionMatches.TryGetValueIL2CPP(connection, out HashSet<int> connectionMatchesValues))
|
||||
return false;
|
||||
|
||||
//Compare for same matches.
|
||||
foreach (int cM in connectionMatchesValues)
|
||||
{
|
||||
if (objectMatchesValues.Contains(cM))
|
||||
return true;
|
||||
}
|
||||
|
||||
//Fall through, not in any of the matches.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns which ServerObjects to rebuild observers on.
|
||||
/// </summary>
|
||||
/// <param name="nm"></param>
|
||||
/// <returns></returns>
|
||||
private static ServerObjects GetServerObjects(NetworkManager manager)
|
||||
{
|
||||
return (manager == null) ? InstanceFinder.ServerManager.Objects : manager.ServerManager.Objects;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// How a condition is handled.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override ObserverConditionType GetConditionType() => ObserverConditionType.Normal;
|
||||
|
||||
/// <summary>
|
||||
/// Clones referenced ObserverCondition. This must be populated with your conditions settings.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override ObserverCondition Clone()
|
||||
{
|
||||
MatchCondition copy = ScriptableObject.CreateInstance<MatchCondition>();
|
||||
copy.ConditionConstructor();
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5afdd6c2de1c76f4faa6840cc29fda8a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,45 @@
|
||||
using FishNet.Connection;
|
||||
using FishNet.Observing;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Component.Observing
|
||||
{
|
||||
/// <summary>
|
||||
/// This condition makes an object only visible to the owner.
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "FishNet/Observers/Owner Only Condition", fileName = "New Owner Only Condition")]
|
||||
public class OwnerOnlyCondition : ObserverCondition
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Returns if the object which this condition resides should be visible to connection.
|
||||
/// </summary>
|
||||
/// <param name="connection">Connection which the condition is being checked for.</param>
|
||||
/// <param name="currentlyAdded">True if the connection currently has visibility of this object.</param>
|
||||
/// <param name="notProcessed">True if the condition was not processed. This can be used to skip processing for performance. While output as true this condition result assumes the previous ConditionMet value.</param>
|
||||
public override bool ConditionMet(NetworkConnection connection, bool currentlyAdded, out bool notProcessed)
|
||||
{
|
||||
notProcessed = false;
|
||||
/* Returning false immediately indicates no connection will
|
||||
* meet this condition. */
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// How a condition is handled.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override ObserverConditionType GetConditionType() => ObserverConditionType.Normal;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Clones referenced ObserverCondition. This must be populated with your conditions settings.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override ObserverCondition Clone()
|
||||
{
|
||||
OwnerOnlyCondition copy = ScriptableObject.CreateInstance<OwnerOnlyCondition>();
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1ca3d8a36a10fd344806a2df999f3eda
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,63 @@
|
||||
using FishNet.Connection;
|
||||
using FishNet.Observing;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace FishNet.Component.Observing
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// When this observer condition is placed on an object, a client must be within the same scene to view the object.
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "FishNet/Observers/Scene Condition", fileName = "New Scene Condition")]
|
||||
public class SceneCondition : ObserverCondition
|
||||
{
|
||||
#region Serialized.
|
||||
///// <summary>
|
||||
///// True to synchronize which scene the object was spawned in to clients. When true this object will be moved to the clients equivelant of the scene it was spawned in on the server. This setting does not continously move this object to the same scene.
|
||||
///// </summary>
|
||||
//[Tooltip("True to synchronize which scene the object was spawned in to clients. When true this object will be moved to the clients equivelant of the scene it was spawned in on the server. This setting does not continously move this object to the same scene.")]
|
||||
//[SerializeField]
|
||||
//private bool _synchronizeScene;
|
||||
#endregion
|
||||
|
||||
public void ConditionConstructor()
|
||||
{
|
||||
//_synchronizeScene = synchronizeScene;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if the object which this condition resides should be visible to connection.
|
||||
/// </summary>
|
||||
/// <param name="connection">Connection which the condition is being checked for.</param>
|
||||
/// <param name="currentlyAdded">True if the connection currently has visibility of this object.</param>
|
||||
/// <param name="notProcessed">True if the condition was not processed. This can be used to skip processing for performance. While output as true this condition result assumes the previous ConditionMet value.</param>
|
||||
public override bool ConditionMet(NetworkConnection connection, bool currentlyAdded, out bool notProcessed)
|
||||
{
|
||||
notProcessed = false;
|
||||
/* When there is no owner only then is the gameobject
|
||||
* scene checked. That's the only way to know at this point. */
|
||||
return connection.Scenes.Contains(base.NetworkObject.gameObject.scene);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// How a condition is handled.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override ObserverConditionType GetConditionType() => ObserverConditionType.Normal;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Clones referenced ObserverCondition. This must be populated with your conditions settings.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override ObserverCondition Clone()
|
||||
{
|
||||
SceneCondition copy = ScriptableObject.CreateInstance<SceneCondition>();
|
||||
//copy.ConditionConstructor(_synchronizeScene);
|
||||
copy.ConditionConstructor();
|
||||
return copy;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fab85d1c51ee2c344b7dd914dc262ec4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1f8371074a46da248ba15efa18140ff3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 7c3e28fa2e37d1d41b4f63c8a0cc2553, type: 3}
|
||||
m_Name: DistanceCondition
|
||||
m_EditorClassIdentifier:
|
||||
NetworkObject: {fileID: 0}
|
||||
_maximumDistance: 10
|
||||
_hideDistancePercent: 0.1
|
||||
UpdateFrequency: 0
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5f33eb0e5b83b5546822cfe42a305657
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: aa62c0af0c0a4da46b03309dcd3858c3, type: 3}
|
||||
m_Name: HostOnlyCondition
|
||||
m_EditorClassIdentifier:
|
||||
NetworkObject: {fileID: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9ff842b44ec59314d9efcecbcdbaac04
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5afdd6c2de1c76f4faa6840cc29fda8a, type: 3}
|
||||
m_Name: MatchCondition
|
||||
m_EditorClassIdentifier:
|
||||
NetworkObject: {fileID: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: efcd7f0dfd341ed4e8671079e91e0544
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 1ca3d8a36a10fd344806a2df999f3eda, type: 3}
|
||||
m_Name: OwnerOnlyCondition
|
||||
m_EditorClassIdentifier:
|
||||
NetworkObject: {fileID: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bcf92670d91dbb74dad77c56b9b8712e
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fab85d1c51ee2c344b7dd914dc262ec4, type: 3}
|
||||
m_Name: SceneCondition
|
||||
m_EditorClassIdentifier:
|
||||
NetworkObject: {fileID: 0}
|
||||
_synchronizeScene: 1
|
||||
_timed: 0
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2033f54fd2794464bae08fa5a55c8996
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user