public void Test_FieldValueFactory_With_Single_Value_Produces_Correct_FieldValueUpdate([EntityDataCollectionTestRange] int index, [Values(1, 2, 3, 4, 5, 6, 7, 8)] int value) { //arrange ChangeTrackingEntityFieldDataCollectionDecorator <TestFieldType> collection = new ChangeTrackingEntityFieldDataCollectionDecorator <TestFieldType>(new EntityFieldDataCollection <TestFieldType>()); FieldValueUpdateFactory updateFactory = new FieldValueUpdateFactory(); //act collection.SetFieldValue <int>(index, value); FieldValueUpdate fieldValueUpdate = updateFactory.Create(new EntityFieldUpdateCreationContext(collection, collection.ChangeTrackingArray)); //assert Assert.AreEqual(1, fieldValueUpdate.FieldValueUpdateMask.EnumerateSetBitsByIndex().Count(), $"Found more than 1 set bit."); Assert.AreEqual(value, fieldValueUpdate.FieldValueUpdates.First(), $"Serialized value was not expected value."); Assert.AreEqual(index, fieldValueUpdate.FieldValueUpdateMask.EnumerateSetBitsByIndex().First(), $"Index: {index} was expected to be in the update but was not."); }
public void Test_FieldValueFactory_With_Multiple_Value_Produces_Correct_FieldValueUpdate() { //arrange ChangeTrackingEntityFieldDataCollectionDecorator <TestFieldType> collection = new ChangeTrackingEntityFieldDataCollectionDecorator <TestFieldType>(new EntityFieldDataCollection <TestFieldType>()); FieldValueUpdateFactory updateFactory = new FieldValueUpdateFactory(); //act collection.SetFieldValue <int>(1, 5); collection.SetFieldValue <int>(2, 4); collection.SetFieldValue <int>(3, 7); FieldValueUpdate fieldValueUpdate = updateFactory.Create(new EntityFieldUpdateCreationContext(collection, collection.ChangeTrackingArray)); //assert Assert.AreEqual(3, fieldValueUpdate.FieldValueUpdateMask.EnumerateSetBitsByIndex().Count(), $"Found more than 1 set bit."); Assert.AreEqual(5, fieldValueUpdate.FieldValueUpdates.First(), $"Serialized value was not expected value."); Assert.AreEqual(1, fieldValueUpdate.FieldValueUpdateMask.EnumerateSetBitsByIndex().First(), $"Index: {1} was expected to be first index."); }
/// <inheritdoc /> public void Tick() { using (LockingPolicy.ReaderLock(null, CancellationToken.None)) { //For every player we need to do some processing so that we can entity data update values foreach (var guid in PlayerGuids) { InterestCollection interest = GetEntityInterestCollection(guid); //Even if we only know ourselves we should do this anyway //so that the client can receieve entity data changes about itself //TODO: We probably won't send an update about ALL entites, so this is some wasted allocations and time List <EntityAssociatedData <FieldValueUpdate> > updates = new List <EntityAssociatedData <FieldValueUpdate> >(interest.ContainedEntities.Count); foreach (var interestingEntityGuid in interest.ContainedEntities) { //Don't build an update for entities that don't have any changes if (!ChangeTrackerHasChangesForEntity(interestingEntityGuid)) { continue; } //TODO: We should cache this update value so we don't need to recompute it for ALL players who are interested //This is the update collection for the particular Entity with guid interestingEntityGuid //We want to use the CHANGE TRACKING bitarray for updates. If this was initial discovery we'd use the SIT bitarray to send all set values. FieldValueUpdate update = UpdateFactory.Create(new EntityFieldUpdateCreationContext(ChangeTrackingCollections[interestingEntityGuid], ChangeTrackingCollections[interestingEntityGuid].ChangeTrackingArray)); updates.Add(new EntityAssociatedData <FieldValueUpdate>(interestingEntityGuid, update)); } //It's possible no entity had updates, so we should not send a packet update if (updates.Count != 0) { SendUpdate(guid, updates); } } foreach (var dataEntityCollection in ChangeTrackingCollections.Values) { dataEntityCollection.ClearTrackedChanges(); } } }
/// <inheritdoc /> public EntityCreationData([NotNull] NetworkEntityGuid entityGuid, [NotNull] IMovementData initialMovementData, [NotNull] FieldValueUpdate initialFieldValues) { EntityGuid = entityGuid ?? throw new ArgumentNullException(nameof(entityGuid)); InitialMovementData = initialMovementData ?? throw new ArgumentNullException(nameof(initialMovementData)); InitialFieldValues = initialFieldValues ?? throw new ArgumentNullException(nameof(initialFieldValues)); }
private static EntityFieldDataCollection <EntityDataFieldType> CreateEntityDataCollectionFromPayload(FieldValueUpdate fieldUpdateValues) { //TODO: We need better initial handling for entity data EntityFieldDataCollection <EntityDataFieldType> entityData = new EntityFieldDataCollection <EntityDataFieldType>(); int currentSentIndex = 0; foreach (var setIndex in fieldUpdateValues.FieldValueUpdateMask.EnumerateSetBitsByIndex()) { entityData.SetFieldValue(setIndex, fieldUpdateValues.FieldValueUpdates.ElementAt(currentSentIndex)); currentSentIndex++; } return(entityData); }