Initial Commit

This commit is contained in:
Sebastian Cabrera 2021-08-02 05:44:37 -04:00
parent 53eb92e9af
commit 270ab7d11f
15341 changed files with 700234 additions and 0 deletions

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 614a7000210157648b54dd16914b97b5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -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;
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 262db7b2db1128748a2e88dd7e20a764
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -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;
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 42fb86f9389141347856337e3c62ad80
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -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

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 245b489a4e4f2174fbdeb27b9cdee07b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,82 @@
using System.IO;
using MLAPI.Transports;
namespace MLAPI.NetworkVariable
{
/// <summary>
/// Interface for network value containers
/// </summary>
public interface INetworkVariable
{
/// <summary>
/// Returns the name of the channel to be used for syncing
/// </summary>
/// <returns>The name of the channel to be used for syncing</returns>
NetworkChannel GetChannel();
/// <summary>
/// Resets the dirty state and marks the variable as synced / clean
/// </summary>
void ResetDirty();
/// <summary>
/// Gets Whether or not the container is dirty
/// </summary>
/// <returns>Whether or not the container is dirty</returns>
bool IsDirty();
/// <summary>
/// Gets Whether or not a specific client can write to the varaible
/// </summary>
/// <param name="clientId">The clientId of the remote client</param>
/// <returns>Whether or not the client can write to the variable</returns>
bool CanClientWrite(ulong clientId);
/// <summary>
/// Gets Whether or not a specific client can read to the varaible
/// </summary>
/// <param name="clientId">The clientId of the remote client</param>
/// <returns>Whether or not the client can read to the variable</returns>
bool CanClientRead(ulong clientId);
/// <summary>
/// Writes the dirty changes, that is, the changes since the variable was last dirty, to the writer
/// </summary>
/// <param name="stream">The stream to write the dirty changes to</param>
void WriteDelta(Stream stream);
/// <summary>
/// Writes the complete state of the variable to the writer
/// </summary>
/// <param name="stream">The stream to write the state to</param>
void WriteField(Stream stream);
/// <summary>
/// Reads the complete state from the reader and applies it
/// </summary>
/// <param name="stream">The stream to read the state from</param>
/// <param name="localTick">The local network tick at which this var was written, on the machine it was written </param>
/// <param name="remoteTick">The remote network tick at which this var was sent by the host </param>
void ReadField(Stream stream, ushort localTick, ushort remoteTick);
/// <summary>
/// Reads delta from the reader and applies them to the internal value
/// </summary>
/// <param name="stream">The stream to read the delta from</param>
/// <param name="keepDirtyDelta">Whether or not the delta should be kept as dirty or consumed</param>
/// <param name="localTick">The local network tick at which this var was written, on the machine it was written </param>
/// <param name="remoteTick">The remote network tick at which this var was sent by the host </param>
void ReadDelta(Stream stream, bool keepDirtyDelta, ushort localTick, ushort remoteTick);
/// <summary>
/// Sets NetworkBehaviour the container belongs to.
/// </summary>
/// <param name="behaviour">The behaviour the container behaves to</param>
void SetNetworkBehaviour(NetworkBehaviour behaviour);
/// <summary>
/// Accessor for the RemoteTick stored in the networkVariable, list, set or dictionary
/// </summary>
ushort RemoteTick { get; }
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 87f1fd4778c2dab4b8bc02c738cade25
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,585 @@
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System;
using MLAPI.Serialization.Pooled;
using MLAPI.Transports;
namespace MLAPI.NetworkVariable
{
/// <summary>
/// A variable that can be synchronized over the network.
/// </summary>
[Serializable]
public class NetworkVariable<T> : INetworkVariable
{
/// <summary>
/// The settings for this var
/// </summary>
public readonly NetworkVariableSettings Settings = new NetworkVariableSettings();
/// <summary>
/// The last time the variable was written to locally
/// </summary>
public ushort LocalTick { get; internal set; }
/// <summary>
/// The last time the variable was written to remotely. Uses the remote timescale
/// </summary>
public ushort RemoteTick { get; internal set; }
/// <summary>
/// Delegate type for value changed event
/// </summary>
/// <param name="previousValue">The value before the change</param>
/// <param name="newValue">The new value</param>
public delegate void OnValueChangedDelegate(T previousValue, T newValue);
/// <summary>
/// The callback to be invoked when the value gets changed
/// </summary>
public OnValueChangedDelegate OnValueChanged;
private NetworkBehaviour m_NetworkBehaviour;
/// <summary>
/// Creates a NetworkVariable with the default value and settings
/// </summary>
public NetworkVariable() { }
/// <summary>
/// Creates a NetworkVariable with the default value and custom settings
/// </summary>
/// <param name="settings">The settings to use for the NetworkVariable</param>
public NetworkVariable(NetworkVariableSettings settings)
{
Settings = settings;
}
/// <summary>
/// Creates a NetworkVariable with a custom value and custom settings
/// </summary>
/// <param name="settings">The settings to use for the NetworkVariable</param>
/// <param name="value">The initial value to use for the NetworkVariable</param>
public NetworkVariable(NetworkVariableSettings settings, T value)
{
Settings = settings;
m_InternalValue = value;
}
/// <summary>
/// Creates a NetworkVariable with a custom value and the default settings
/// </summary>
/// <param name="value">The initial value to use for the NetworkVariable</param>
public NetworkVariable(T value)
{
m_InternalValue = value;
}
[SerializeField]
private T m_InternalValue;
/// <summary>
/// The value of the NetworkVariable container
/// </summary>
public T Value
{
get => m_InternalValue;
set
{
if (EqualityComparer<T>.Default.Equals(m_InternalValue, value)) return;
// Setter is assumed to be called locally, by game code.
// When used by the host, it is its responsibility to set the RemoteTick
RemoteTick = NetworkTickSystem.NoTick;
m_IsDirty = true;
T previousValue = m_InternalValue;
m_InternalValue = value;
OnValueChanged?.Invoke(previousValue, m_InternalValue);
}
}
private bool m_IsDirty = false;
/// <summary>
/// Sets whether or not the variable needs to be delta synced
/// </summary>
public void SetDirty(bool isDirty)
{
m_IsDirty = isDirty;
}
/// <inheritdoc />
public bool IsDirty()
{
return m_IsDirty;
}
/// <inheritdoc />
public void ResetDirty()
{
m_IsDirty = false;
}
/// <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;
}
/// <summary>
/// Writes the variable to the writer
/// </summary>
/// <param name="stream">The stream to write the value to</param>
public void WriteDelta(Stream stream)
{
WriteField(stream);
}
/// <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;
}
/// <summary>
/// Reads value from the reader and applies it
/// </summary>
/// <param name="stream">The stream to read the value from</param>
/// <param name="keepDirtyDelta">Whether or not the container should keep the dirty delta, or mark the delta as consumed</param>
public void ReadDelta(Stream stream, bool keepDirtyDelta, ushort localTick, ushort remoteTick)
{
// todo: This allows the host-returned value to be set back to an old value
// this will need to be adjusted to check if we're have a most recent value
LocalTick = localTick;
RemoteTick = remoteTick;
using (var reader = PooledNetworkReader.Get(stream))
{
T previousValue = m_InternalValue;
m_InternalValue = (T)reader.ReadObjectPacked(typeof(T));
if (keepDirtyDelta) m_IsDirty = true;
OnValueChanged?.Invoke(previousValue, m_InternalValue);
}
}
/// <inheritdoc />
public void SetNetworkBehaviour(NetworkBehaviour behaviour)
{
m_NetworkBehaviour = behaviour;
}
/// <inheritdoc />
public void ReadField(Stream stream, ushort localTick, ushort remoteTick)
{
ReadDelta(stream, false, localTick, remoteTick);
}
/// <inheritdoc />
public void WriteField(Stream stream)
{
// Store the local tick at which this NetworkVariable was modified
LocalTick = NetworkBehaviour.CurrentTick;
using (var writer = PooledNetworkWriter.Get(stream))
{
writer.WriteObjectPacked(m_InternalValue); //BOX
}
}
/// <inheritdoc />
public NetworkChannel GetChannel()
{
return Settings.SendNetworkChannel;
}
}
/// <summary>
/// A NetworkVariable that holds strings and support serialization
/// </summary>
[Serializable]
public class NetworkVariableString : NetworkVariable<string>
{
/// <inheritdoc />
public NetworkVariableString() : base(string.Empty) { }
/// <inheritdoc />
public NetworkVariableString(NetworkVariableSettings settings) : base(settings, string.Empty) { }
/// <inheritdoc />
public NetworkVariableString(string value) : base(value) { }
/// <inheritdoc />
public NetworkVariableString(NetworkVariableSettings settings, string value) : base(settings, value) { }
}
/// <summary>
/// A NetworkVariable that holds bools and support serialization
/// </summary>
[Serializable]
public class NetworkVariableBool : NetworkVariable<bool>
{
/// <inheritdoc />
public NetworkVariableBool() { }
/// <inheritdoc />
public NetworkVariableBool(NetworkVariableSettings settings) : base(settings) { }
/// <inheritdoc />
public NetworkVariableBool(bool value) : base(value) { }
/// <inheritdoc />
public NetworkVariableBool(NetworkVariableSettings settings, bool value) : base(settings, value) { }
}
/// <summary>
/// A NetworkVariable that holds bytes and support serialization
/// </summary>
[Serializable]
public class NetworkVariableByte : NetworkVariable<byte>
{
/// <inheritdoc />
public NetworkVariableByte() { }
/// <inheritdoc />
public NetworkVariableByte(NetworkVariableSettings settings) : base(settings) { }
/// <inheritdoc />
public NetworkVariableByte(byte value) : base(value) { }
/// <inheritdoc />
public NetworkVariableByte(NetworkVariableSettings settings, byte value) : base(settings, value) { }
}
/// <summary>
/// A NetworkVariable that holds sbytes and support serialization
/// </summary>
[Serializable]
public class NetworkVariableSByte : NetworkVariable<sbyte>
{
/// <inheritdoc />
public NetworkVariableSByte() { }
/// <inheritdoc />
public NetworkVariableSByte(NetworkVariableSettings settings) : base(settings) { }
/// <inheritdoc />
public NetworkVariableSByte(sbyte value) : base(value) { }
/// <inheritdoc />
public NetworkVariableSByte(NetworkVariableSettings settings, sbyte value) : base(settings, value) { }
}
/// <summary>
/// A NetworkVariable that holds ushorts and support serialization
/// </summary>
[Serializable]
public class NetworkVariableUShort : NetworkVariable<ushort>
{
/// <inheritdoc />
public NetworkVariableUShort() { }
/// <inheritdoc />
public NetworkVariableUShort(NetworkVariableSettings settings) : base(settings) { }
/// <inheritdoc />
public NetworkVariableUShort(ushort value) : base(value) { }
/// <inheritdoc />
public NetworkVariableUShort(NetworkVariableSettings settings, ushort value) : base(settings, value) { }
}
/// <summary>
/// A NetworkVariable that holds shorts and support serialization
/// </summary>
[Serializable]
public class NetworkVariableShort : NetworkVariable<short>
{
/// <inheritdoc />
public NetworkVariableShort() { }
/// <inheritdoc />
public NetworkVariableShort(NetworkVariableSettings settings) : base(settings) { }
/// <inheritdoc />
public NetworkVariableShort(short value) : base(value) { }
/// <inheritdoc />
public NetworkVariableShort(NetworkVariableSettings settings, short value) : base(settings, value) { }
}
/// <summary>
/// A NetworkVariable that holds uints and support serialization
/// </summary>
[Serializable]
public class NetworkVariableUInt : NetworkVariable<uint>
{
/// <inheritdoc />
public NetworkVariableUInt() { }
/// <inheritdoc />
public NetworkVariableUInt(NetworkVariableSettings settings) : base(settings) { }
/// <inheritdoc />
public NetworkVariableUInt(uint value) : base(value) { }
/// <inheritdoc />
public NetworkVariableUInt(NetworkVariableSettings settings, uint value) : base(settings, value) { }
}
/// <summary>
/// A NetworkVariable that holds ints and support serialization
/// </summary>
[Serializable]
public class NetworkVariableInt : NetworkVariable<int>
{
/// <inheritdoc />
public NetworkVariableInt() { }
/// <inheritdoc />
public NetworkVariableInt(NetworkVariableSettings settings) : base(settings) { }
/// <inheritdoc />
public NetworkVariableInt(int value) : base(value) { }
/// <inheritdoc />
public NetworkVariableInt(NetworkVariableSettings settings, int value) : base(settings, value) { }
}
/// <summary>
/// A NetworkVariable that holds ulongs and support serialization
/// </summary>
[Serializable]
public class NetworkVariableULong : NetworkVariable<ulong>
{
/// <inheritdoc />
public NetworkVariableULong() { }
/// <inheritdoc />
public NetworkVariableULong(NetworkVariableSettings settings) : base(settings) { }
/// <inheritdoc />
public NetworkVariableULong(ulong value) : base(value) { }
/// <inheritdoc />
public NetworkVariableULong(NetworkVariableSettings settings, ulong value) : base(settings, value) { }
}
/// <summary>
/// A NetworkVariable that holds longs and support serialization
/// </summary>
[Serializable]
public class NetworkVariableLong : NetworkVariable<long>
{
/// <inheritdoc />
public NetworkVariableLong() { }
/// <inheritdoc />
public NetworkVariableLong(NetworkVariableSettings settings) : base(settings) { }
/// <inheritdoc />
public NetworkVariableLong(long value) : base(value) { }
/// <inheritdoc />
public NetworkVariableLong(NetworkVariableSettings settings, long value) : base(settings, value) { }
}
/// <summary>
/// A NetworkVariable that holds floats and support serialization
/// </summary>
[Serializable]
public class NetworkVariableFloat : NetworkVariable<float>
{
/// <inheritdoc />
public NetworkVariableFloat() { }
/// <inheritdoc />
public NetworkVariableFloat(NetworkVariableSettings settings) : base(settings) { }
/// <inheritdoc />
public NetworkVariableFloat(float value) : base(value) { }
/// <inheritdoc />
public NetworkVariableFloat(NetworkVariableSettings settings, float value) : base(settings, value) { }
}
/// <summary>
/// A NetworkVariable that holds doubles and support serialization
/// </summary>
[Serializable]
public class NetworkVariableDouble : NetworkVariable<double>
{
/// <inheritdoc />
public NetworkVariableDouble() { }
/// <inheritdoc />
public NetworkVariableDouble(NetworkVariableSettings settings) : base(settings) { }
/// <inheritdoc />
public NetworkVariableDouble(double value) : base(value) { }
/// <inheritdoc />
public NetworkVariableDouble(NetworkVariableSettings settings, double value) : base(settings, value) { }
}
/// <summary>
/// A NetworkVariable that holds vector2s and support serialization
/// </summary>
[Serializable]
public class NetworkVariableVector2 : NetworkVariable<Vector2>
{
/// <inheritdoc />
public NetworkVariableVector2() { }
/// <inheritdoc />
public NetworkVariableVector2(NetworkVariableSettings settings) : base(settings) { }
/// <inheritdoc />
public NetworkVariableVector2(Vector2 value) : base(value) { }
/// <inheritdoc />
public NetworkVariableVector2(NetworkVariableSettings settings, Vector2 value) : base(settings, value) { }
}
/// <summary>
/// A NetworkVariable that holds vector3s and support serialization
/// </summary>
[Serializable]
public class NetworkVariableVector3 : NetworkVariable<Vector3>
{
/// <inheritdoc />
public NetworkVariableVector3() { }
/// <inheritdoc />
public NetworkVariableVector3(NetworkVariableSettings settings) : base(settings) { }
/// <inheritdoc />
public NetworkVariableVector3(Vector3 value) : base(value) { }
/// <inheritdoc />
public NetworkVariableVector3(NetworkVariableSettings settings, Vector3 value) : base(settings, value) { }
}
/// <summary>
/// A NetworkVariable that holds vector4s and support serialization
/// </summary>
[Serializable]
public class NetworkVariableVector4 : NetworkVariable<Vector4>
{
/// <inheritdoc />
public NetworkVariableVector4() { }
/// <inheritdoc />
public NetworkVariableVector4(NetworkVariableSettings settings) : base(settings) { }
/// <inheritdoc />
public NetworkVariableVector4(Vector4 value) : base(value) { }
/// <inheritdoc />
public NetworkVariableVector4(NetworkVariableSettings settings, Vector4 value) : base(settings, value) { }
}
/// <summary>
/// A NetworkVariable that holds colors and support serialization
/// </summary>
[Serializable]
public class NetworkVariableColor : NetworkVariable<Color>
{
/// <inheritdoc />
public NetworkVariableColor() { }
/// <inheritdoc />
public NetworkVariableColor(NetworkVariableSettings settings) : base(settings) { }
/// <inheritdoc />
public NetworkVariableColor(Color value) : base(value) { }
/// <inheritdoc />
public NetworkVariableColor(NetworkVariableSettings settings, Color value) : base(settings, value) { }
}
/// <summary>
/// A NetworkVariable that holds color32s and support serialization
/// </summary>
[Serializable]
public class NetworkVariableColor32 : NetworkVariable<Color32>
{
/// <inheritdoc />
public NetworkVariableColor32() { }
/// <inheritdoc />
public NetworkVariableColor32(NetworkVariableSettings settings) : base(settings) { }
/// <inheritdoc />
public NetworkVariableColor32(Color32 value) : base(value) { }
/// <inheritdoc />
public NetworkVariableColor32(NetworkVariableSettings settings, Color32 value) : base(settings, value) { }
}
/// <summary>
/// A NetworkVariable that holds rays and support serialization
/// </summary>
[Serializable]
public class NetworkVariableRay : NetworkVariable<Ray>
{
/// <inheritdoc />
public NetworkVariableRay() { }
/// <inheritdoc />
public NetworkVariableRay(NetworkVariableSettings settings) : base(settings) { }
/// <inheritdoc />
public NetworkVariableRay(Ray value) : base(value) { }
/// <inheritdoc />
public NetworkVariableRay(NetworkVariableSettings settings, Ray value) : base(settings, value) { }
}
/// <summary>
/// A NetworkVariable that holds quaternions and support serialization
/// </summary>
[Serializable]
public class NetworkVariableQuaternion : NetworkVariable<Quaternion>
{
/// <inheritdoc />
public NetworkVariableQuaternion() { }
/// <inheritdoc />
public NetworkVariableQuaternion(NetworkVariableSettings settings) : base(settings) { }
/// <inheritdoc />
public NetworkVariableQuaternion(Quaternion value) : base(value) { }
/// <inheritdoc />
public NetworkVariableQuaternion(NetworkVariableSettings settings, Quaternion value) : base(settings, value) { }
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0f6bd4b05b09e604986db16876d2cd4f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,28 @@
namespace MLAPI.NetworkVariable
{
/// <summary>
/// Permission type
/// </summary>
public enum NetworkVariablePermission
{
/// <summary>
/// Everyone
/// </summary>
Everyone,
/// <summary>
/// Server-only operation
/// </summary>
ServerOnly,
/// <summary>
/// Owner-ownly
/// </summary>
OwnerOnly,
/// <summary>
/// Custom delegate
/// </summary>
Custom
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bc753a77be3d7e846b7bb2612a67ac62
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,50 @@
using MLAPI.Transports;
namespace MLAPI.NetworkVariable
{
/// <summary>
/// Delegate type for permission checking
/// </summary>
/// <param name="clientId">The clientId whose permissions to check</param>
public delegate bool NetworkVariablePermissionsDelegate(ulong clientId);
/// <summary>
/// The settings class used by the build in NetworkVar implementations
/// </summary>
public class NetworkVariableSettings
{
/// <summary>
/// Defines the write permissions for this var
/// </summary>
public NetworkVariablePermission WritePermission = NetworkVariablePermission.ServerOnly;
/// <summary>
/// Defines the read permissions for this var
/// </summary>
public NetworkVariablePermission ReadPermission = NetworkVariablePermission.Everyone;
/// <summary>
/// The delegate used to evaluate write permission when the "Custom" mode is used
/// </summary>
public NetworkVariablePermissionsDelegate WritePermissionCallback = null;
/// <summary>
/// The delegate used to evaluate read permission when the "Custom" mode is used
/// </summary>
public NetworkVariablePermissionsDelegate ReadPermissionCallback = null;
/// <summary>
/// The maximum times per second this var will be synced.
/// A value of 0 will cause the variable to sync as soon as possible after being changed.
/// A value of less than 0 will cause the variable to sync only at once at spawn and not update again.
/// </summary>
public float SendTickrate = 0;
/// <summary>
/// The name of the channel to use for this variable.
/// Variables with different channels will be split into different packets
/// </summary>
public NetworkChannel SendNetworkChannel = NetworkChannel.DefaultMessage;
/// <summary>
/// Constructs a new NetworkVariableSettings instance
/// </summary>
public NetworkVariableSettings() { }
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 06315503f26247d4aaa786326d12ecdc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: