/// <inheritdoc /> public void SetFieldValue <TValueType>(int index, TValueType value) where TValueType : struct { int potentialNewValue = Unsafe.As <TValueType, int>(ref value); //We lock here because it's possible that we're in the middle of setting //and someone clears HasPendingCHanges since they went through the collection //This could cause a race condition between networking coming in and changing entity data //and the change tracking/dispatcher not dispatching changes due to being missed or canceled out //in this race condition. lock (SyncObj) { //If the values aren't equal we need to set the tracking/dirty stuff //Then we also should set the data if (!potentialNewValue.Equals(EntityDataCollection.GetFieldValue <int>(index))) { ChangeTrackingArray.Set(index, true); EntityDataCollection.SetFieldValue(index, value); //We only have pending changes if the value is not equal HasPendingChanges = true; } else { //TODO: This kinda exposing an implementation detail because if we started with 0 and setting 0 the above if will fail. //The reasoning is if we explictly set 0 then we set the bit because it might not be set DataSetIndicationArray.Set(index, true); } } }
/// <inheritdoc /> public void ClearTrackedChanges() { lock (SyncObj) { //TODO: This is slow and inefficient. We should maintain and memcpy an array of false bits. We may have to do this hundreds/thousands of a minute. ChangeTrackingArray.SetAll(false); HasPendingChanges = false; } }