Initial Commit
This commit is contained in:
parent
53eb92e9af
commit
270ab7d11f
15341 changed files with 700234 additions and 0 deletions
|
@ -0,0 +1,598 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MLAPI.Serialization.Pooled;
|
||||
using MLAPI.Transports;
|
||||
|
||||
namespace MLAPI.NetworkVariable.Collections
|
||||
{
|
||||
/// <summary>
|
||||
/// Event based NetworkVariable container for syncing Dictionaries
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">The type for the dictionary keys</typeparam>
|
||||
/// <typeparam name="TValue">The type for the dictionary values</typeparam>
|
||||
public class NetworkDictionary<TKey, TValue> : IDictionary<TKey, TValue>, INetworkVariable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the last time the variable was synced
|
||||
/// </summary>
|
||||
public float LastSyncedTime { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// The settings for this container
|
||||
/// </summary>
|
||||
public readonly NetworkVariableSettings Settings = new NetworkVariableSettings();
|
||||
|
||||
private readonly IDictionary<TKey, TValue> m_Dictionary = new Dictionary<TKey, TValue>();
|
||||
private NetworkBehaviour m_NetworkBehaviour;
|
||||
private readonly List<NetworkDictionaryEvent<TKey, TValue>> m_DirtyEvents = new List<NetworkDictionaryEvent<TKey, TValue>>();
|
||||
|
||||
/// <summary>
|
||||
/// Delegate type for dictionary changed event
|
||||
/// </summary>
|
||||
/// <param name="changeEvent">Struct containing information about the change event</param>
|
||||
public delegate void OnDictionaryChangedDelegate(NetworkDictionaryEvent<TKey, TValue> changeEvent);
|
||||
|
||||
/// <summary>
|
||||
/// The callback to be invoked when the dictionary gets changed
|
||||
/// </summary>
|
||||
public event OnDictionaryChangedDelegate OnDictionaryChanged;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a NetworkDictionary with the default value and settings
|
||||
/// </summary>
|
||||
public NetworkDictionary() { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a NetworkDictionary with the default value and custom settings
|
||||
/// </summary>
|
||||
/// <param name="settings">The settings to use for the NetworkDictionary</param>
|
||||
public NetworkDictionary(NetworkVariableSettings settings)
|
||||
{
|
||||
Settings = settings;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a NetworkDictionary with a custom value and custom settings
|
||||
/// </summary>
|
||||
/// <param name="settings">The settings to use for the NetworkDictionary</param>
|
||||
/// <param name="value">The initial value to use for the NetworkDictionary</param>
|
||||
public NetworkDictionary(NetworkVariableSettings settings, IDictionary<TKey, TValue> value)
|
||||
{
|
||||
Settings = settings;
|
||||
m_Dictionary = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a NetworkDictionary with a custom value and the default settings
|
||||
/// </summary>
|
||||
/// <param name="value">The initial value to use for the NetworkDictionary</param>
|
||||
public NetworkDictionary(IDictionary<TKey, TValue> value)
|
||||
{
|
||||
m_Dictionary = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ResetDirty()
|
||||
{
|
||||
m_DirtyEvents.Clear();
|
||||
LastSyncedTime = NetworkManager.Singleton.NetworkTime;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public NetworkChannel GetChannel()
|
||||
{
|
||||
return Settings.SendNetworkChannel;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ReadDelta(Stream stream, bool keepDirtyDelta, ushort localTick, ushort remoteTick)
|
||||
{
|
||||
using (var reader = PooledNetworkReader.Get(stream))
|
||||
{
|
||||
ushort deltaCount = reader.ReadUInt16Packed();
|
||||
for (int i = 0; i < deltaCount; i++)
|
||||
{
|
||||
NetworkDictionaryEvent<TKey, TValue>.EventType eventType = (NetworkDictionaryEvent<TKey, TValue>.EventType)reader.ReadBits(3);
|
||||
switch (eventType)
|
||||
{
|
||||
case NetworkDictionaryEvent<TKey, TValue>.EventType.Add:
|
||||
{
|
||||
TKey key = (TKey)reader.ReadObjectPacked(typeof(TKey));
|
||||
TValue value = (TValue)reader.ReadObjectPacked(typeof(TValue));
|
||||
m_Dictionary.Add(key, value);
|
||||
|
||||
if (OnDictionaryChanged != null)
|
||||
{
|
||||
OnDictionaryChanged(new NetworkDictionaryEvent<TKey, TValue>
|
||||
{
|
||||
Type = eventType,
|
||||
Key = key,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
|
||||
if (keepDirtyDelta)
|
||||
{
|
||||
m_DirtyEvents.Add(new NetworkDictionaryEvent<TKey, TValue>()
|
||||
{
|
||||
Type = eventType,
|
||||
Key = key,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NetworkDictionaryEvent<TKey, TValue>.EventType.Remove:
|
||||
{
|
||||
TKey key = (TKey)reader.ReadObjectPacked(typeof(TKey));
|
||||
TValue value;
|
||||
m_Dictionary.TryGetValue(key, out value);
|
||||
m_Dictionary.Remove(key);
|
||||
|
||||
if (OnDictionaryChanged != null)
|
||||
{
|
||||
OnDictionaryChanged(new NetworkDictionaryEvent<TKey, TValue>
|
||||
{
|
||||
Type = eventType,
|
||||
Key = key,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
|
||||
if (keepDirtyDelta)
|
||||
{
|
||||
m_DirtyEvents.Add(new NetworkDictionaryEvent<TKey, TValue>()
|
||||
{
|
||||
Type = eventType,
|
||||
Key = key,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NetworkDictionaryEvent<TKey, TValue>.EventType.RemovePair:
|
||||
{
|
||||
TKey key = (TKey)reader.ReadObjectPacked(typeof(TKey));
|
||||
TValue value = (TValue)reader.ReadObjectPacked(typeof(TValue));
|
||||
m_Dictionary.Remove(new KeyValuePair<TKey, TValue>(key, value));
|
||||
|
||||
if (OnDictionaryChanged != null)
|
||||
{
|
||||
OnDictionaryChanged(new NetworkDictionaryEvent<TKey, TValue>
|
||||
{
|
||||
Type = eventType,
|
||||
Key = key,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
|
||||
if (keepDirtyDelta)
|
||||
{
|
||||
m_DirtyEvents.Add(new NetworkDictionaryEvent<TKey, TValue>()
|
||||
{
|
||||
Type = eventType,
|
||||
Key = key,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NetworkDictionaryEvent<TKey, TValue>.EventType.Clear:
|
||||
{
|
||||
//read nothing
|
||||
m_Dictionary.Clear();
|
||||
|
||||
if (OnDictionaryChanged != null)
|
||||
{
|
||||
OnDictionaryChanged(new NetworkDictionaryEvent<TKey, TValue>
|
||||
{
|
||||
Type = eventType
|
||||
});
|
||||
}
|
||||
|
||||
if (keepDirtyDelta)
|
||||
{
|
||||
m_DirtyEvents.Add(new NetworkDictionaryEvent<TKey, TValue>
|
||||
{
|
||||
Type = eventType
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NetworkDictionaryEvent<TKey, TValue>.EventType.Value:
|
||||
{
|
||||
TKey key = (TKey)reader.ReadObjectPacked(typeof(TKey));
|
||||
TValue value = (TValue)reader.ReadObjectPacked(typeof(TValue));
|
||||
|
||||
m_Dictionary[key] = value;
|
||||
|
||||
if (OnDictionaryChanged != null)
|
||||
{
|
||||
OnDictionaryChanged(new NetworkDictionaryEvent<TKey, TValue>
|
||||
{
|
||||
Type = eventType,
|
||||
Key = key,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
|
||||
if (keepDirtyDelta)
|
||||
{
|
||||
m_DirtyEvents.Add(new NetworkDictionaryEvent<TKey, TValue>()
|
||||
{
|
||||
Type = eventType,
|
||||
Key = key,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ReadField(Stream stream, ushort localTick, ushort remoteTick)
|
||||
{
|
||||
using (var reader = PooledNetworkReader.Get(stream))
|
||||
{
|
||||
m_Dictionary.Clear();
|
||||
ushort entryCount = reader.ReadUInt16Packed();
|
||||
for (int i = 0; i < entryCount; i++)
|
||||
{
|
||||
TKey key = (TKey)reader.ReadObjectPacked(typeof(TKey));
|
||||
TValue value = (TValue)reader.ReadObjectPacked(typeof(TValue));
|
||||
m_Dictionary.Add(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SetNetworkBehaviour(NetworkBehaviour behaviour)
|
||||
{
|
||||
m_NetworkBehaviour = behaviour;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool TryGetValue(TKey key, out TValue value)
|
||||
{
|
||||
return m_Dictionary.TryGetValue(key, out value);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void WriteDelta(Stream stream)
|
||||
{
|
||||
using (var writer = PooledNetworkWriter.Get(stream))
|
||||
{
|
||||
writer.WriteUInt16Packed((ushort)m_DirtyEvents.Count);
|
||||
for (int i = 0; i < m_DirtyEvents.Count; i++)
|
||||
{
|
||||
writer.WriteBits((byte)m_DirtyEvents[i].Type, 3);
|
||||
switch (m_DirtyEvents[i].Type)
|
||||
{
|
||||
case NetworkDictionaryEvent<TKey, TValue>.EventType.Add:
|
||||
{
|
||||
writer.WriteObjectPacked(m_DirtyEvents[i].Key);
|
||||
writer.WriteObjectPacked(m_DirtyEvents[i].Value);
|
||||
}
|
||||
break;
|
||||
case NetworkDictionaryEvent<TKey, TValue>.EventType.Remove:
|
||||
{
|
||||
writer.WriteObjectPacked(m_DirtyEvents[i].Key);
|
||||
}
|
||||
break;
|
||||
case NetworkDictionaryEvent<TKey, TValue>.EventType.RemovePair:
|
||||
{
|
||||
writer.WriteObjectPacked(m_DirtyEvents[i].Key);
|
||||
writer.WriteObjectPacked(m_DirtyEvents[i].Value);
|
||||
}
|
||||
break;
|
||||
case NetworkDictionaryEvent<TKey, TValue>.EventType.Clear:
|
||||
{
|
||||
//write nothing
|
||||
}
|
||||
break;
|
||||
case NetworkDictionaryEvent<TKey, TValue>.EventType.Value:
|
||||
{
|
||||
writer.WriteObjectPacked(m_DirtyEvents[i].Key);
|
||||
writer.WriteObjectPacked(m_DirtyEvents[i].Value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void WriteField(Stream stream)
|
||||
{
|
||||
using (var writer = PooledNetworkWriter.Get(stream))
|
||||
{
|
||||
writer.WriteUInt16Packed((ushort)m_Dictionary.Count);
|
||||
foreach (KeyValuePair<TKey, TValue> pair in m_Dictionary)
|
||||
{
|
||||
writer.WriteObjectPacked(pair.Key);
|
||||
writer.WriteObjectPacked(pair.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool CanClientWrite(ulong clientId)
|
||||
{
|
||||
switch (Settings.WritePermission)
|
||||
{
|
||||
case NetworkVariablePermission.Everyone:
|
||||
return true;
|
||||
case NetworkVariablePermission.ServerOnly:
|
||||
return false;
|
||||
case NetworkVariablePermission.OwnerOnly:
|
||||
return m_NetworkBehaviour.OwnerClientId == clientId;
|
||||
case NetworkVariablePermission.Custom:
|
||||
{
|
||||
if (Settings.WritePermissionCallback == null) return false;
|
||||
return Settings.WritePermissionCallback(clientId);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool CanClientRead(ulong clientId)
|
||||
{
|
||||
switch (Settings.ReadPermission)
|
||||
{
|
||||
case NetworkVariablePermission.Everyone:
|
||||
return true;
|
||||
case NetworkVariablePermission.ServerOnly:
|
||||
return false;
|
||||
case NetworkVariablePermission.OwnerOnly:
|
||||
return m_NetworkBehaviour.OwnerClientId == clientId;
|
||||
case NetworkVariablePermission.Custom:
|
||||
{
|
||||
if (Settings.ReadPermissionCallback == null) return false;
|
||||
return Settings.ReadPermissionCallback(clientId);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsDirty()
|
||||
{
|
||||
if (m_DirtyEvents.Count == 0) return false;
|
||||
if (Settings.SendTickrate == 0) return true;
|
||||
if (Settings.SendTickrate < 0) return false;
|
||||
if (NetworkManager.Singleton.NetworkTime - LastSyncedTime >= (1f / Settings.SendTickrate)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public TValue this[TKey key]
|
||||
{
|
||||
get => m_Dictionary[key];
|
||||
set
|
||||
{
|
||||
if (NetworkManager.Singleton.IsServer) m_Dictionary[key] = value;
|
||||
|
||||
NetworkDictionaryEvent<TKey, TValue> dictionaryEvent = new NetworkDictionaryEvent<TKey, TValue>()
|
||||
{
|
||||
Type = NetworkDictionaryEvent<TKey, TValue>.EventType.Value,
|
||||
Key = key,
|
||||
Value = value
|
||||
};
|
||||
|
||||
HandleAddDictionaryEvent(dictionaryEvent);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICollection<TKey> Keys => m_Dictionary.Keys;
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICollection<TValue> Values => m_Dictionary.Values;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Count => m_Dictionary.Count;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsReadOnly => m_Dictionary.IsReadOnly;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Add(TKey key, TValue value)
|
||||
{
|
||||
if (NetworkManager.Singleton.IsServer) m_Dictionary.Add(key, value);
|
||||
|
||||
NetworkDictionaryEvent<TKey, TValue> dictionaryEvent = new NetworkDictionaryEvent<TKey, TValue>()
|
||||
{
|
||||
Type = NetworkDictionaryEvent<TKey, TValue>.EventType.Add,
|
||||
Key = key,
|
||||
Value = value
|
||||
};
|
||||
|
||||
HandleAddDictionaryEvent(dictionaryEvent);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Add(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
if (NetworkManager.Singleton.IsServer) m_Dictionary.Add(item);
|
||||
|
||||
NetworkDictionaryEvent<TKey, TValue> dictionaryEvent = new NetworkDictionaryEvent<TKey, TValue>()
|
||||
{
|
||||
Type = NetworkDictionaryEvent<TKey, TValue>.EventType.Add,
|
||||
Key = item.Key,
|
||||
Value = item.Value
|
||||
};
|
||||
|
||||
HandleAddDictionaryEvent(dictionaryEvent);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Clear()
|
||||
{
|
||||
if (NetworkManager.Singleton.IsServer) m_Dictionary.Clear();
|
||||
|
||||
NetworkDictionaryEvent<TKey, TValue> dictionaryEvent = new NetworkDictionaryEvent<TKey, TValue>()
|
||||
{
|
||||
Type = NetworkDictionaryEvent<TKey, TValue>.EventType.Clear
|
||||
};
|
||||
|
||||
HandleAddDictionaryEvent(dictionaryEvent);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Contains(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
return m_Dictionary.Contains(item);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool ContainsKey(TKey key)
|
||||
{
|
||||
return m_Dictionary.ContainsKey(key);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
|
||||
{
|
||||
m_Dictionary.CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
||||
{
|
||||
return m_Dictionary.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Remove(TKey key)
|
||||
{
|
||||
if (NetworkManager.Singleton.IsServer)
|
||||
m_Dictionary.Remove(key);
|
||||
|
||||
TValue value;
|
||||
m_Dictionary.TryGetValue(key, out value);
|
||||
|
||||
NetworkDictionaryEvent<TKey, TValue> dictionaryEvent = new NetworkDictionaryEvent<TKey, TValue>()
|
||||
{
|
||||
Type = NetworkDictionaryEvent<TKey, TValue>.EventType.Remove,
|
||||
Key = key,
|
||||
Value = value
|
||||
};
|
||||
|
||||
HandleAddDictionaryEvent(dictionaryEvent);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Remove(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
if (NetworkManager.Singleton.IsServer) m_Dictionary.Remove(item);
|
||||
|
||||
NetworkDictionaryEvent<TKey, TValue> dictionaryEvent = new NetworkDictionaryEvent<TKey, TValue>()
|
||||
{
|
||||
Type = NetworkDictionaryEvent<TKey, TValue>.EventType.RemovePair,
|
||||
Key = item.Key,
|
||||
Value = item.Value
|
||||
};
|
||||
|
||||
HandleAddDictionaryEvent(dictionaryEvent);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return m_Dictionary.GetEnumerator();
|
||||
}
|
||||
|
||||
private void HandleAddDictionaryEvent(NetworkDictionaryEvent<TKey, TValue> dictionaryEvent)
|
||||
{
|
||||
if (NetworkManager.Singleton.IsServer)
|
||||
{
|
||||
if (NetworkManager.Singleton.ConnectedClients.Count > 0)
|
||||
{
|
||||
m_DirtyEvents.Add(dictionaryEvent);
|
||||
}
|
||||
|
||||
OnDictionaryChanged?.Invoke(dictionaryEvent);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_DirtyEvents.Add(dictionaryEvent);
|
||||
}
|
||||
}
|
||||
|
||||
public ushort RemoteTick
|
||||
{
|
||||
get
|
||||
{
|
||||
// todo: implement proper network tick for NetworkDictionary
|
||||
return NetworkTickSystem.NoTick;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Struct containing event information about changes to a NetworkDictionary.
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">The type for the dictionary key that the event is about</typeparam>
|
||||
/// <typeparam name="TValue">The type for the dictionary value that the event is about</typeparam>
|
||||
public struct NetworkDictionaryEvent<TKey, TValue>
|
||||
{
|
||||
/// <summary>
|
||||
/// Enum representing the different operations available for triggering an event.
|
||||
/// </summary>
|
||||
public enum EventType
|
||||
{
|
||||
/// <summary>
|
||||
/// Add
|
||||
/// </summary>
|
||||
Add,
|
||||
|
||||
/// <summary>
|
||||
/// Remove
|
||||
/// </summary>
|
||||
Remove,
|
||||
|
||||
/// <summary>
|
||||
/// Remove pair
|
||||
/// </summary>
|
||||
RemovePair,
|
||||
|
||||
/// <summary>
|
||||
/// Clear
|
||||
/// </summary>
|
||||
Clear,
|
||||
|
||||
/// <summary>
|
||||
/// Value changed
|
||||
/// </summary>
|
||||
Value
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enum representing the operation made to the dictionary.
|
||||
/// </summary>
|
||||
public EventType Type;
|
||||
|
||||
/// <summary>
|
||||
/// the key changed, added or removed if available.
|
||||
/// </summary>
|
||||
public TKey Key;
|
||||
|
||||
/// <summary>
|
||||
/// The value changed, added or removed if available.
|
||||
/// </summary>
|
||||
public TValue Value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 262db7b2db1128748a2e88dd7e20a764
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,602 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MLAPI.Serialization.Pooled;
|
||||
using MLAPI.Transports;
|
||||
|
||||
namespace MLAPI.NetworkVariable.Collections
|
||||
{
|
||||
/// <summary>
|
||||
/// Event based NetworkVariable container for syncing Lists
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type for the list</typeparam>
|
||||
public class NetworkList<T> : IList<T>, INetworkVariable
|
||||
{
|
||||
private readonly IList<T> m_List = new List<T>();
|
||||
private readonly List<NetworkListEvent<T>> m_DirtyEvents = new List<NetworkListEvent<T>>();
|
||||
private NetworkBehaviour m_NetworkBehaviour;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last time the variable was synced
|
||||
/// </summary>
|
||||
public float LastSyncedTime { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// The settings for this container
|
||||
/// </summary>
|
||||
public readonly NetworkVariableSettings Settings = new NetworkVariableSettings();
|
||||
|
||||
/// <summary>
|
||||
/// Delegate type for list changed event
|
||||
/// </summary>
|
||||
/// <param name="changeEvent">Struct containing information about the change event</param>
|
||||
public delegate void OnListChangedDelegate(NetworkListEvent<T> changeEvent);
|
||||
|
||||
/// <summary>
|
||||
/// The callback to be invoked when the list gets changed
|
||||
/// </summary>
|
||||
public event OnListChangedDelegate OnListChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a NetworkList with the default value and settings
|
||||
/// </summary>
|
||||
public NetworkList() { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a NetworkList with the default value and custom settings
|
||||
/// </summary>
|
||||
/// <param name="settings">The settings to use for the NetworkList</param>
|
||||
public NetworkList(NetworkVariableSettings settings)
|
||||
{
|
||||
Settings = settings;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a NetworkList with a custom value and custom settings
|
||||
/// </summary>
|
||||
/// <param name="settings">The settings to use for the NetworkList</param>
|
||||
/// <param name="value">The initial value to use for the NetworkList</param>
|
||||
public NetworkList(NetworkVariableSettings settings, IList<T> value)
|
||||
{
|
||||
Settings = settings;
|
||||
m_List = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a NetworkList with a custom value and the default settings
|
||||
/// </summary>
|
||||
/// <param name="value">The initial value to use for the NetworkList</param>
|
||||
public NetworkList(IList<T> value)
|
||||
{
|
||||
m_List = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ResetDirty()
|
||||
{
|
||||
m_DirtyEvents.Clear();
|
||||
LastSyncedTime = NetworkManager.Singleton.NetworkTime;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsDirty()
|
||||
{
|
||||
if (m_DirtyEvents.Count == 0) return false;
|
||||
if (Settings.SendTickrate == 0) return true;
|
||||
if (Settings.SendTickrate < 0) return false;
|
||||
if (NetworkManager.Singleton.NetworkTime - LastSyncedTime >= (1f / Settings.SendTickrate)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public NetworkChannel GetChannel()
|
||||
{
|
||||
return Settings.SendNetworkChannel;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool CanClientWrite(ulong clientId)
|
||||
{
|
||||
switch (Settings.WritePermission)
|
||||
{
|
||||
case NetworkVariablePermission.Everyone:
|
||||
return true;
|
||||
case NetworkVariablePermission.ServerOnly:
|
||||
return false;
|
||||
case NetworkVariablePermission.OwnerOnly:
|
||||
return m_NetworkBehaviour.OwnerClientId == clientId;
|
||||
case NetworkVariablePermission.Custom:
|
||||
{
|
||||
if (Settings.WritePermissionCallback == null) return false;
|
||||
return Settings.WritePermissionCallback(clientId);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool CanClientRead(ulong clientId)
|
||||
{
|
||||
switch (Settings.ReadPermission)
|
||||
{
|
||||
case NetworkVariablePermission.Everyone:
|
||||
return true;
|
||||
case NetworkVariablePermission.ServerOnly:
|
||||
return false;
|
||||
case NetworkVariablePermission.OwnerOnly:
|
||||
return m_NetworkBehaviour.OwnerClientId == clientId;
|
||||
case NetworkVariablePermission.Custom:
|
||||
{
|
||||
if (Settings.ReadPermissionCallback == null) return false;
|
||||
return Settings.ReadPermissionCallback(clientId);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void WriteDelta(Stream stream)
|
||||
{
|
||||
using (var writer = PooledNetworkWriter.Get(stream))
|
||||
{
|
||||
writer.WriteUInt16Packed((ushort)m_DirtyEvents.Count);
|
||||
for (int i = 0; i < m_DirtyEvents.Count; i++)
|
||||
{
|
||||
writer.WriteBits((byte)m_DirtyEvents[i].Type, 3);
|
||||
switch (m_DirtyEvents[i].Type)
|
||||
{
|
||||
case NetworkListEvent<T>.EventType.Add:
|
||||
{
|
||||
writer.WriteObjectPacked(m_DirtyEvents[i].Value); //BOX
|
||||
}
|
||||
break;
|
||||
case NetworkListEvent<T>.EventType.Insert:
|
||||
{
|
||||
writer.WriteInt32Packed(m_DirtyEvents[i].Index);
|
||||
writer.WriteObjectPacked(m_DirtyEvents[i].Value); //BOX
|
||||
}
|
||||
break;
|
||||
case NetworkListEvent<T>.EventType.Remove:
|
||||
{
|
||||
writer.WriteObjectPacked(m_DirtyEvents[i].Value); //BOX
|
||||
}
|
||||
break;
|
||||
case NetworkListEvent<T>.EventType.RemoveAt:
|
||||
{
|
||||
writer.WriteInt32Packed(m_DirtyEvents[i].Index);
|
||||
}
|
||||
break;
|
||||
case NetworkListEvent<T>.EventType.Value:
|
||||
{
|
||||
writer.WriteInt32Packed(m_DirtyEvents[i].Index);
|
||||
writer.WriteObjectPacked(m_DirtyEvents[i].Value); //BOX
|
||||
}
|
||||
break;
|
||||
case NetworkListEvent<T>.EventType.Clear:
|
||||
{
|
||||
//Nothing has to be written
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void WriteField(Stream stream)
|
||||
{
|
||||
using (var writer = PooledNetworkWriter.Get(stream))
|
||||
{
|
||||
writer.WriteUInt16Packed((ushort)m_List.Count);
|
||||
for (int i = 0; i < m_List.Count; i++)
|
||||
{
|
||||
writer.WriteObjectPacked(m_List[i]); //BOX
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ReadField(Stream stream, ushort localTick, ushort remoteTick)
|
||||
{
|
||||
using (var reader = PooledNetworkReader.Get(stream))
|
||||
{
|
||||
m_List.Clear();
|
||||
ushort count = reader.ReadUInt16Packed();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
m_List.Add((T)reader.ReadObjectPacked(typeof(T))); //BOX
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ReadDelta(Stream stream, bool keepDirtyDelta, ushort localTick, ushort remoteTick)
|
||||
{
|
||||
using (var reader = PooledNetworkReader.Get(stream))
|
||||
{
|
||||
ushort deltaCount = reader.ReadUInt16Packed();
|
||||
for (int i = 0; i < deltaCount; i++)
|
||||
{
|
||||
NetworkListEvent<T>.EventType eventType = (NetworkListEvent<T>.EventType)reader.ReadBits(3);
|
||||
switch (eventType)
|
||||
{
|
||||
case NetworkListEvent<T>.EventType.Add:
|
||||
{
|
||||
m_List.Add((T)reader.ReadObjectPacked(typeof(T))); //BOX
|
||||
|
||||
if (OnListChanged != null)
|
||||
{
|
||||
OnListChanged(new NetworkListEvent<T>
|
||||
{
|
||||
Type = eventType,
|
||||
Index = m_List.Count - 1,
|
||||
Value = m_List[m_List.Count - 1]
|
||||
});
|
||||
}
|
||||
|
||||
if (keepDirtyDelta)
|
||||
{
|
||||
m_DirtyEvents.Add(new NetworkListEvent<T>()
|
||||
{
|
||||
Type = eventType,
|
||||
Index = m_List.Count - 1,
|
||||
Value = m_List[m_List.Count - 1]
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NetworkListEvent<T>.EventType.Insert:
|
||||
{
|
||||
int index = reader.ReadInt32Packed();
|
||||
m_List.Insert(index, (T)reader.ReadObjectPacked(typeof(T))); //BOX
|
||||
|
||||
if (OnListChanged != null)
|
||||
{
|
||||
OnListChanged(new NetworkListEvent<T>
|
||||
{
|
||||
Type = eventType,
|
||||
Index = index,
|
||||
Value = m_List[index]
|
||||
});
|
||||
}
|
||||
|
||||
if (keepDirtyDelta)
|
||||
{
|
||||
m_DirtyEvents.Add(new NetworkListEvent<T>()
|
||||
{
|
||||
Type = eventType,
|
||||
Index = index,
|
||||
Value = m_List[index]
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NetworkListEvent<T>.EventType.Remove:
|
||||
{
|
||||
T value = (T)reader.ReadObjectPacked(typeof(T)); //BOX
|
||||
int index = m_List.IndexOf(value);
|
||||
m_List.RemoveAt(index);
|
||||
|
||||
if (OnListChanged != null)
|
||||
{
|
||||
OnListChanged(new NetworkListEvent<T>
|
||||
{
|
||||
Type = eventType,
|
||||
Index = index,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
|
||||
if (keepDirtyDelta)
|
||||
{
|
||||
m_DirtyEvents.Add(new NetworkListEvent<T>()
|
||||
{
|
||||
Type = eventType,
|
||||
Index = index,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NetworkListEvent<T>.EventType.RemoveAt:
|
||||
{
|
||||
int index = reader.ReadInt32Packed();
|
||||
T value = m_List[index];
|
||||
m_List.RemoveAt(index);
|
||||
|
||||
if (OnListChanged != null)
|
||||
{
|
||||
OnListChanged(new NetworkListEvent<T>
|
||||
{
|
||||
Type = eventType,
|
||||
Index = index,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
|
||||
if (keepDirtyDelta)
|
||||
{
|
||||
m_DirtyEvents.Add(new NetworkListEvent<T>()
|
||||
{
|
||||
Type = eventType,
|
||||
Index = index,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NetworkListEvent<T>.EventType.Value:
|
||||
{
|
||||
int index = reader.ReadInt32Packed();
|
||||
T value = (T)reader.ReadObjectPacked(typeof(T)); //BOX
|
||||
if (index < m_List.Count) m_List[index] = value;
|
||||
|
||||
if (OnListChanged != null)
|
||||
{
|
||||
OnListChanged(new NetworkListEvent<T>
|
||||
{
|
||||
Type = eventType,
|
||||
Index = index,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
|
||||
if (keepDirtyDelta)
|
||||
{
|
||||
m_DirtyEvents.Add(new NetworkListEvent<T>()
|
||||
{
|
||||
Type = eventType,
|
||||
Index = index,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NetworkListEvent<T>.EventType.Clear:
|
||||
{
|
||||
//Read nothing
|
||||
m_List.Clear();
|
||||
|
||||
if (OnListChanged != null)
|
||||
{
|
||||
OnListChanged(new NetworkListEvent<T>
|
||||
{
|
||||
Type = eventType,
|
||||
});
|
||||
}
|
||||
|
||||
if (keepDirtyDelta)
|
||||
{
|
||||
m_DirtyEvents.Add(new NetworkListEvent<T>()
|
||||
{
|
||||
Type = eventType
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SetNetworkBehaviour(NetworkBehaviour behaviour)
|
||||
{
|
||||
m_NetworkBehaviour = behaviour;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return m_List.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable)m_List).GetEnumerator();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Add(T item)
|
||||
{
|
||||
if (NetworkManager.Singleton.IsServer) m_List.Add(item);
|
||||
|
||||
NetworkListEvent<T> listEvent = new NetworkListEvent<T>()
|
||||
{
|
||||
Type = NetworkListEvent<T>.EventType.Add,
|
||||
Value = item,
|
||||
Index = m_List.Count - 1
|
||||
};
|
||||
|
||||
HandleAddListEvent(listEvent);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Clear()
|
||||
{
|
||||
if (NetworkManager.Singleton.IsServer) m_List.Clear();
|
||||
|
||||
NetworkListEvent<T> listEvent = new NetworkListEvent<T>()
|
||||
{
|
||||
Type = NetworkListEvent<T>.EventType.Clear
|
||||
};
|
||||
|
||||
HandleAddListEvent(listEvent);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Contains(T item)
|
||||
{
|
||||
return m_List.Contains(item);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
m_List.CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Remove(T item)
|
||||
{
|
||||
if (NetworkManager.Singleton.IsServer) m_List.Remove(item);
|
||||
|
||||
NetworkListEvent<T> listEvent = new NetworkListEvent<T>()
|
||||
{
|
||||
Type = NetworkListEvent<T>.EventType.Remove,
|
||||
Value = item
|
||||
};
|
||||
|
||||
HandleAddListEvent(listEvent);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Count => m_List.Count;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsReadOnly => m_List.IsReadOnly;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int IndexOf(T item)
|
||||
{
|
||||
return m_List.IndexOf(item);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Insert(int index, T item)
|
||||
{
|
||||
if (NetworkManager.Singleton.IsServer) m_List.Insert(index, item);
|
||||
|
||||
NetworkListEvent<T> listEvent = new NetworkListEvent<T>()
|
||||
{
|
||||
Type = NetworkListEvent<T>.EventType.Insert,
|
||||
Index = index,
|
||||
Value = item
|
||||
};
|
||||
|
||||
HandleAddListEvent(listEvent);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
if (NetworkManager.Singleton.IsServer) m_List.RemoveAt(index);
|
||||
|
||||
NetworkListEvent<T> listEvent = new NetworkListEvent<T>()
|
||||
{
|
||||
Type = NetworkListEvent<T>.EventType.RemoveAt,
|
||||
Index = index
|
||||
};
|
||||
|
||||
HandleAddListEvent(listEvent);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public T this[int index]
|
||||
{
|
||||
get => m_List[index];
|
||||
set
|
||||
{
|
||||
if (NetworkManager.Singleton.IsServer)
|
||||
m_List[index] = value;
|
||||
|
||||
NetworkListEvent<T> listEvent = new NetworkListEvent<T>()
|
||||
{
|
||||
Type = NetworkListEvent<T>.EventType.Value,
|
||||
Index = index,
|
||||
Value = value
|
||||
};
|
||||
|
||||
HandleAddListEvent(listEvent);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleAddListEvent(NetworkListEvent<T> listEvent)
|
||||
{
|
||||
if (NetworkManager.Singleton.IsServer)
|
||||
{
|
||||
if (NetworkManager.Singleton.ConnectedClients.Count > 0)
|
||||
{
|
||||
m_DirtyEvents.Add(listEvent);
|
||||
}
|
||||
|
||||
OnListChanged?.Invoke(listEvent);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_DirtyEvents.Add(listEvent);
|
||||
}
|
||||
}
|
||||
|
||||
public ushort RemoteTick
|
||||
{
|
||||
get
|
||||
{
|
||||
// todo: implement proper network tick for NetworkList
|
||||
return NetworkTickSystem.NoTick;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Struct containing event information about changes to a NetworkList.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type for the list that the event is about</typeparam>
|
||||
public struct NetworkListEvent<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Enum representing the different operations available for triggering an event.
|
||||
/// </summary>
|
||||
public enum EventType
|
||||
{
|
||||
/// <summary>
|
||||
/// Add
|
||||
/// </summary>
|
||||
Add,
|
||||
|
||||
/// <summary>
|
||||
/// Insert
|
||||
/// </summary>
|
||||
Insert,
|
||||
|
||||
/// <summary>
|
||||
/// Remove
|
||||
/// </summary>
|
||||
Remove,
|
||||
|
||||
/// <summary>
|
||||
/// Remove at
|
||||
/// </summary>
|
||||
RemoveAt,
|
||||
|
||||
/// <summary>
|
||||
/// Value changed
|
||||
/// </summary>
|
||||
Value,
|
||||
|
||||
/// <summary>
|
||||
/// Clear
|
||||
/// </summary>
|
||||
Clear
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enum representing the operation made to the list.
|
||||
/// </summary>
|
||||
public EventType Type;
|
||||
|
||||
/// <summary>
|
||||
/// The value changed, added or removed if available.
|
||||
/// </summary>
|
||||
public T Value;
|
||||
|
||||
/// <summary>
|
||||
/// the index changed, added or removed if available
|
||||
/// </summary>
|
||||
public int Index;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 42fb86f9389141347856337e3c62ad80
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,548 @@
|
|||
#if !NET35
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MLAPI.Serialization.Pooled;
|
||||
using MLAPI.Transports;
|
||||
|
||||
namespace MLAPI.NetworkVariable.Collections
|
||||
{
|
||||
/// <summary>
|
||||
/// Event based NetworkVariable container for syncing Sets
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type for the set</typeparam>
|
||||
public class NetworkSet<T> : ISet<T>, INetworkVariable
|
||||
{
|
||||
private readonly ISet<T> m_Set = new HashSet<T>();
|
||||
private readonly List<NetworkSetEvent<T>> m_DirtyEvents = new List<NetworkSetEvent<T>>();
|
||||
private NetworkBehaviour m_NetworkBehaviour;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last time the variable was synced
|
||||
/// </summary>
|
||||
public float LastSyncedTime { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// The settings for this container
|
||||
/// </summary>
|
||||
public readonly NetworkVariableSettings Settings = new NetworkVariableSettings();
|
||||
|
||||
/// <summary>
|
||||
/// Delegate type for set changed event
|
||||
/// </summary>
|
||||
/// <param name="changeEvent">Struct containing information about the change event</param>
|
||||
public delegate void OnSetChangedDelegate(NetworkSetEvent<T> changeEvent);
|
||||
|
||||
/// <summary>
|
||||
/// The callback to be invoked when the set gets changed
|
||||
/// </summary>
|
||||
public event OnSetChangedDelegate OnSetChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a NetworkSet with the default value and settings
|
||||
/// </summary>
|
||||
public NetworkSet() { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a NetworkSet with the default value and custom settings
|
||||
/// </summary>
|
||||
/// <param name="settings">The settings to use for the NetworkList</param>
|
||||
public NetworkSet(NetworkVariableSettings settings)
|
||||
{
|
||||
Settings = settings;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a NetworkSet with a custom value and custom settings
|
||||
/// </summary>
|
||||
/// <param name="settings">The settings to use for the NetworkSet</param>
|
||||
/// <param name="value">The initial value to use for the NetworkSet</param>
|
||||
public NetworkSet(NetworkVariableSettings settings, ISet<T> value)
|
||||
{
|
||||
Settings = settings;
|
||||
m_Set = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a NetworkSet with a custom value and the default settings
|
||||
/// </summary>
|
||||
/// <param name="value">The initial value to use for the NetworkList</param>
|
||||
public NetworkSet(ISet<T> value)
|
||||
{
|
||||
m_Set = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ResetDirty()
|
||||
{
|
||||
m_DirtyEvents.Clear();
|
||||
LastSyncedTime = NetworkManager.Singleton.NetworkTime;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsDirty()
|
||||
{
|
||||
if (m_DirtyEvents.Count == 0) return false;
|
||||
if (Settings.SendTickrate == 0) return true;
|
||||
if (Settings.SendTickrate < 0) return false;
|
||||
if (NetworkManager.Singleton.NetworkTime - LastSyncedTime >= (1f / Settings.SendTickrate)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public NetworkChannel GetChannel()
|
||||
{
|
||||
return Settings.SendNetworkChannel;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool CanClientWrite(ulong clientId)
|
||||
{
|
||||
switch (Settings.WritePermission)
|
||||
{
|
||||
case NetworkVariablePermission.Everyone:
|
||||
return true;
|
||||
case NetworkVariablePermission.ServerOnly:
|
||||
return false;
|
||||
case NetworkVariablePermission.OwnerOnly:
|
||||
return m_NetworkBehaviour.OwnerClientId == clientId;
|
||||
case NetworkVariablePermission.Custom:
|
||||
{
|
||||
if (Settings.WritePermissionCallback == null) return false;
|
||||
return Settings.WritePermissionCallback(clientId);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool CanClientRead(ulong clientId)
|
||||
{
|
||||
switch (Settings.ReadPermission)
|
||||
{
|
||||
case NetworkVariablePermission.Everyone:
|
||||
return true;
|
||||
case NetworkVariablePermission.ServerOnly:
|
||||
return false;
|
||||
case NetworkVariablePermission.OwnerOnly:
|
||||
return m_NetworkBehaviour.OwnerClientId == clientId;
|
||||
case NetworkVariablePermission.Custom:
|
||||
{
|
||||
if (Settings.ReadPermissionCallback == null) return false;
|
||||
return Settings.ReadPermissionCallback(clientId);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void WriteDelta(Stream stream)
|
||||
{
|
||||
using (var writer = PooledNetworkWriter.Get(stream))
|
||||
{
|
||||
writer.WriteUInt16Packed((ushort)m_DirtyEvents.Count);
|
||||
for (int i = 0; i < m_DirtyEvents.Count; i++)
|
||||
{
|
||||
writer.WriteBits((byte)m_DirtyEvents[i].Type, 2);
|
||||
|
||||
switch (m_DirtyEvents[i].Type)
|
||||
{
|
||||
case NetworkSetEvent<T>.EventType.Add:
|
||||
{
|
||||
writer.WriteObjectPacked(m_DirtyEvents[i].Value); //BOX
|
||||
}
|
||||
break;
|
||||
case NetworkSetEvent<T>.EventType.Remove:
|
||||
{
|
||||
writer.WriteObjectPacked(m_DirtyEvents[i].Value); //BOX
|
||||
}
|
||||
break;
|
||||
case NetworkSetEvent<T>.EventType.Clear:
|
||||
{
|
||||
//Nothing has to be written
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void WriteField(Stream stream)
|
||||
{
|
||||
using (var writer = PooledNetworkWriter.Get(stream))
|
||||
{
|
||||
writer.WriteUInt16Packed((ushort)m_Set.Count);
|
||||
|
||||
foreach (T value in m_Set)
|
||||
{
|
||||
writer.WriteObjectPacked(value); //BOX
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ReadField(Stream stream, ushort localTick, ushort remoteTick)
|
||||
{
|
||||
using (var reader = PooledNetworkReader.Get(stream))
|
||||
{
|
||||
m_Set.Clear();
|
||||
ushort count = reader.ReadUInt16Packed();
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
m_Set.Add((T)reader.ReadObjectPacked(typeof(T))); //BOX
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ReadDelta(Stream stream, bool keepDirtyDelta, ushort localTick, ushort remoteTick)
|
||||
{
|
||||
using (var reader = PooledNetworkReader.Get(stream))
|
||||
{
|
||||
ushort deltaCount = reader.ReadUInt16Packed();
|
||||
for (int i = 0; i < deltaCount; i++)
|
||||
{
|
||||
NetworkSetEvent<T>.EventType eventType = (NetworkSetEvent<T>.EventType)reader.ReadBits(2);
|
||||
switch (eventType)
|
||||
{
|
||||
case NetworkSetEvent<T>.EventType.Add:
|
||||
{
|
||||
T value = (T)reader.ReadObjectPacked(typeof(T)); //BOX
|
||||
m_Set.Add(value);
|
||||
|
||||
if (OnSetChanged != null)
|
||||
{
|
||||
OnSetChanged(new NetworkSetEvent<T>
|
||||
{
|
||||
Type = eventType,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
|
||||
if (keepDirtyDelta)
|
||||
{
|
||||
m_DirtyEvents.Add(new NetworkSetEvent<T>()
|
||||
{
|
||||
Type = eventType,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NetworkSetEvent<T>.EventType.Remove:
|
||||
{
|
||||
T value = (T)reader.ReadObjectPacked(typeof(T)); //BOX
|
||||
m_Set.Remove(value);
|
||||
|
||||
if (OnSetChanged != null)
|
||||
{
|
||||
OnSetChanged(new NetworkSetEvent<T>
|
||||
{
|
||||
Type = eventType,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
|
||||
if (keepDirtyDelta)
|
||||
{
|
||||
m_DirtyEvents.Add(new NetworkSetEvent<T>()
|
||||
{
|
||||
Type = eventType,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NetworkSetEvent<T>.EventType.Clear:
|
||||
{
|
||||
//Read nothing
|
||||
m_Set.Clear();
|
||||
|
||||
if (OnSetChanged != null)
|
||||
{
|
||||
OnSetChanged(new NetworkSetEvent<T>
|
||||
{
|
||||
Type = eventType,
|
||||
});
|
||||
}
|
||||
|
||||
if (keepDirtyDelta)
|
||||
{
|
||||
m_DirtyEvents.Add(new NetworkSetEvent<T>()
|
||||
{
|
||||
Type = eventType
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SetNetworkBehaviour(NetworkBehaviour behaviour)
|
||||
{
|
||||
m_NetworkBehaviour = behaviour;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return m_Set.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return m_Set.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
void ICollection<T>.Add(T item)
|
||||
{
|
||||
if (NetworkManager.Singleton.IsServer) m_Set.Add(item);
|
||||
|
||||
NetworkSetEvent<T> setEvent = new NetworkSetEvent<T>()
|
||||
{
|
||||
Type = NetworkSetEvent<T>.EventType.Add,
|
||||
Value = item
|
||||
};
|
||||
m_DirtyEvents.Add(setEvent);
|
||||
|
||||
if (NetworkManager.Singleton.IsServer && OnSetChanged != null)
|
||||
OnSetChanged(setEvent);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ExceptWith(IEnumerable<T> other)
|
||||
{
|
||||
foreach (T value in other)
|
||||
{
|
||||
if (m_Set.Contains(value))
|
||||
{
|
||||
Remove(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void IntersectWith(IEnumerable<T> other)
|
||||
{
|
||||
HashSet<T> otherSet = new HashSet<T>(other);
|
||||
|
||||
foreach (T value in m_Set)
|
||||
{
|
||||
if (!otherSet.Contains(value))
|
||||
{
|
||||
Remove(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsProperSubsetOf(IEnumerable<T> other)
|
||||
{
|
||||
return m_Set.IsProperSubsetOf(other);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsProperSupersetOf(IEnumerable<T> other)
|
||||
{
|
||||
return m_Set.IsProperSupersetOf(other);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsSubsetOf(IEnumerable<T> other)
|
||||
{
|
||||
return m_Set.IsSubsetOf(other);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsSupersetOf(IEnumerable<T> other)
|
||||
{
|
||||
return m_Set.IsSupersetOf(other);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Overlaps(IEnumerable<T> other)
|
||||
{
|
||||
return m_Set.Overlaps(other);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool SetEquals(IEnumerable<T> other)
|
||||
{
|
||||
return m_Set.SetEquals(other);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SymmetricExceptWith(IEnumerable<T> other)
|
||||
{
|
||||
foreach (T value in other)
|
||||
{
|
||||
if (m_Set.Contains(value))
|
||||
{
|
||||
Remove(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NetworkManager.Singleton.IsServer) m_Set.Add(value);
|
||||
|
||||
NetworkSetEvent<T> setEvent = new NetworkSetEvent<T>()
|
||||
{
|
||||
Type = NetworkSetEvent<T>.EventType.Add,
|
||||
Value = value
|
||||
};
|
||||
m_DirtyEvents.Add(setEvent);
|
||||
|
||||
if (NetworkManager.Singleton.IsServer && OnSetChanged != null)
|
||||
OnSetChanged(setEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void UnionWith(IEnumerable<T> other)
|
||||
{
|
||||
foreach (T value in other)
|
||||
{
|
||||
if (!m_Set.Contains(value))
|
||||
{
|
||||
if (NetworkManager.Singleton.IsServer) m_Set.Add(value);
|
||||
|
||||
NetworkSetEvent<T> setEvent = new NetworkSetEvent<T>()
|
||||
{
|
||||
Type = NetworkSetEvent<T>.EventType.Add,
|
||||
Value = value
|
||||
};
|
||||
m_DirtyEvents.Add(setEvent);
|
||||
|
||||
if (NetworkManager.Singleton.IsServer && OnSetChanged != null)
|
||||
OnSetChanged(setEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
bool ISet<T>.Add(T item)
|
||||
{
|
||||
if (NetworkManager.Singleton.IsServer) m_Set.Add(item);
|
||||
|
||||
NetworkSetEvent<T> setEvent = new NetworkSetEvent<T>()
|
||||
{
|
||||
Type = NetworkSetEvent<T>.EventType.Add,
|
||||
Value = item
|
||||
};
|
||||
m_DirtyEvents.Add(setEvent);
|
||||
|
||||
if (NetworkManager.Singleton.IsServer && OnSetChanged != null)
|
||||
OnSetChanged(setEvent);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Clear()
|
||||
{
|
||||
if (NetworkManager.Singleton.IsServer) m_Set.Clear();
|
||||
|
||||
NetworkSetEvent<T> setEvent = new NetworkSetEvent<T>()
|
||||
{
|
||||
Type = NetworkSetEvent<T>.EventType.Clear
|
||||
};
|
||||
m_DirtyEvents.Add(setEvent);
|
||||
|
||||
if (NetworkManager.Singleton.IsServer && OnSetChanged != null)
|
||||
OnSetChanged(setEvent);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Contains(T item)
|
||||
{
|
||||
return m_Set.Contains(item);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
m_Set.CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Remove(T item)
|
||||
{
|
||||
if (NetworkManager.Singleton.IsServer) m_Set.Remove(item);
|
||||
|
||||
NetworkSetEvent<T> setEvent = new NetworkSetEvent<T>()
|
||||
{
|
||||
Type = NetworkSetEvent<T>.EventType.Remove,
|
||||
Value = item
|
||||
};
|
||||
m_DirtyEvents.Add(setEvent);
|
||||
|
||||
if (NetworkManager.Singleton.IsServer && OnSetChanged != null)
|
||||
OnSetChanged(setEvent);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Count => m_Set.Count;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsReadOnly => m_Set.IsReadOnly;
|
||||
|
||||
public ushort RemoteTick
|
||||
{
|
||||
get
|
||||
{
|
||||
// todo: implement proper network tick for NetworkSet
|
||||
return NetworkTickSystem.NoTick;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Struct containing event information about changes to a NetworkSet.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type for the set that the event is about</typeparam>
|
||||
public struct NetworkSetEvent<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Enum representing the different operations available for triggering an event.
|
||||
/// </summary>
|
||||
public enum EventType
|
||||
{
|
||||
/// <summary>
|
||||
/// Add
|
||||
/// </summary>
|
||||
Add,
|
||||
|
||||
/// <summary>
|
||||
/// Remove
|
||||
/// </summary>
|
||||
Remove,
|
||||
|
||||
/// <summary>
|
||||
/// Clear
|
||||
/// </summary>
|
||||
Clear
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enum representing the operation made to the set.
|
||||
/// </summary>
|
||||
public EventType Type;
|
||||
|
||||
/// <summary>
|
||||
/// The value changed, added or removed if available.
|
||||
/// </summary>
|
||||
public T Value;
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 245b489a4e4f2174fbdeb27b9cdee07b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Add table
Add a link
Reference in a new issue