1using System.Collections;
2using System.Collections.Generic;
8 public delegate
void SyncDictionaryChanged(Operation op, TKey key, TValue item);
10 protected readonly IDictionary<TKey, TValue> objects;
12 public int Count => objects.Count;
13 public bool IsReadOnly {
get;
private set; }
14 public event SyncDictionaryChanged Callback;
16 public enum Operation :
byte
26 internal Operation operation;
36 readonly List<Change> changes =
new List<Change>();
52 public ICollection<TKey> Keys => objects.Keys;
54 public ICollection<TValue> Values => objects.Values;
56 IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys => objects.Keys;
58 IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values => objects.Values;
66 this.objects = objects;
69 void AddOperation(Operation op, TKey key, TValue item)
73 throw new System.InvalidOperationException(
"SyncDictionaries can only be modified by the server");
76 Change change =
new Change
89 Callback?.Invoke(op, key, item);
95 writer.WriteUInt((uint)objects.Count);
97 foreach (KeyValuePair<TKey, TValue> syncItem
in objects)
99 writer.Write(syncItem.Key);
100 writer.Write(syncItem.Value);
107 writer.WriteUInt((uint)changes.Count);
113 writer.WriteUInt((uint)changes.Count);
115 for (
int i = 0; i < changes.Count; i++)
117 Change change = changes[i];
118 writer.WriteByte((
byte)change.operation);
120 switch (change.operation)
122 case Operation.OP_ADD:
123 case Operation.OP_REMOVE:
124 case Operation.OP_SET:
125 writer.Write(change.key);
126 writer.Write(change.item);
128 case Operation.OP_CLEAR:
140 int count = (int)reader.ReadUInt();
145 for (
int i = 0; i < count; i++)
147 TKey key = reader.Read<TKey>();
148 TValue obj = reader.Read<TValue>();
149 objects.Add(key, obj);
155 changesAhead = (int)reader.ReadUInt();
163 int changesCount = (int)reader.ReadUInt();
165 for (
int i = 0; i < changesCount; i++)
167 Operation operation = (Operation)reader.ReadByte();
171 bool apply = changesAhead == 0;
173 TValue item =
default;
177 case Operation.OP_ADD:
178 case Operation.OP_SET:
179 key = reader.Read<TKey>();
180 item = reader.Read<TValue>();
187 case Operation.OP_CLEAR:
194 case Operation.OP_REMOVE:
195 key = reader.Read<TKey>();
196 item = reader.Read<TValue>();
206 Callback?.Invoke(operation, key, item);
219 AddOperation(Operation.OP_CLEAR,
default,
default);
222 public bool ContainsKey(TKey key) => objects.ContainsKey(key);
224 public bool Remove(TKey key)
226 if (objects.TryGetValue(key, out TValue item) && objects.Remove(key))
228 AddOperation(Operation.OP_REMOVE, key, item);
234 public TValue
this[TKey i]
242 AddOperation(Operation.OP_SET, i, value);
247 AddOperation(Operation.OP_ADD, i, value);
252 public bool TryGetValue(TKey key, out TValue value) => objects.TryGetValue(key, out value);
254 public void Add(TKey key, TValue value)
256 objects.Add(key, value);
257 AddOperation(Operation.OP_ADD, key, value);
260 public void Add(KeyValuePair<TKey, TValue> item) => Add(item.Key, item.Value);
262 public bool Contains(KeyValuePair<TKey, TValue> item)
264 return TryGetValue(item.Key, out TValue val) && EqualityComparer<TValue>.Default.Equals(val, item.Value);
267 public void CopyTo(KeyValuePair<TKey, TValue>[] array,
int arrayIndex)
269 if (arrayIndex < 0 || arrayIndex > array.Length)
271 throw new System.ArgumentOutOfRangeException(nameof(arrayIndex),
"Array Index Out of Range");
273 if (array.Length - arrayIndex < Count)
275 throw new System.ArgumentException(
"The number of items in the SyncDictionary is greater than the available space from arrayIndex to the end of the destination array");
279 foreach (KeyValuePair<TKey, TValue> item
in objects)
286 public bool Remove(KeyValuePair<TKey, TValue> item)
288 bool result = objects.Remove(item.Key);
291 AddOperation(Operation.OP_REMOVE, item.Key, item.Value);
296 public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => objects.GetEnumerator();
298 IEnumerator IEnumerable.GetEnumerator() => objects.GetEnumerator();
304 public SyncDictionary(IEqualityComparer<TKey> eq) : base(
new Dictionary<TKey, TValue>(eq)) {}
305 public SyncDictionary(IDictionary<TKey, TValue> d) : base(
new Dictionary<TKey, TValue>(d)) {}
306 public new Dictionary<TKey, TValue>.ValueCollection Values => ((Dictionary<TKey, TValue>)objects).Values;
307 public new Dictionary<TKey, TValue>.KeyCollection Keys => ((Dictionary<TKey, TValue>)objects).Keys;
308 public new Dictionary<TKey, TValue>.Enumerator GetEnumerator() => ((Dictionary<TKey, TValue>)objects).GetEnumerator();
Network Reader for most simple types like floats, ints, buffers, structs, etc. Use NetworkReaderPool....
Network Writer for most simple types like floats, ints, buffers, structs, etc. Use NetworkWriterPool....
override void Reset()
Resets the SyncObject so that it can be re-used
override void OnSerializeDelta(NetworkWriter writer)
Write the changes made to the object since last sync
override void OnSerializeAll(NetworkWriter writer)
Write a full copy of the object
override void ClearChanges()
Discard all the queued changes
override void OnDeserializeDelta(NetworkReader reader)
Reads the changes made to the object since last sync
override void OnDeserializeAll(NetworkReader reader)
Reads a full copy of the object
SyncObjects sync state between server and client. E.g. SyncLists.
Action OnDirty
Used internally to set owner NetworkBehaviour's dirty mask bit when changed.
Func< bool > IsRecording
Used internally to check if we are currently tracking changes.