/// <summary> /// Determines if the interest collection has pending interest changes. /// (Joining or leaving the collection via queues). /// </summary> /// <param name="collection"></param> /// <returns></returns> public static bool HasPendingChanges([NotNull] this InterestCollection collection) { if (collection == null) { throw new ArgumentNullException(nameof(collection)); } return(!collection.EnteringDequeueable.isEmpty || !collection.LeavingDequeueable.isEmpty); }
/// <inheritdoc /> public GameObject Create(PlayerEntityCreationContext context) { GameObject gameObject = DecoratedFactory.Create(context); GuidToSessionMappable.Add(context.EntityGuid, context.SessionContext.ZoneSession); ConnectionIdToControllingEntityMap.Add(context.SessionContext.ConnectionId, context.EntityGuid); InterestCollection playerInterestCollection = new InterestCollection(); //directly add ourselves so we don't become interest in ourselves after spawning playerInterestCollection.Add(context.EntityGuid); //We just create our own manaul interest collection here. GuidToInterestCollectionMappable.Add(context.EntityGuid, playerInterestCollection); //We don't need to touch the gameobject, we can just return it. return(gameObject); }
/// <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(); } } }
public void Test_DequeueCommand_Handles_Entering_Entities() { //arrange //InterestDequeueSetCommand InterestCollection interestCollection = new InterestCollection(); interestCollection.Register(new NetworkEntityGuid(1), new NetworkEntityGuid(1)); interestCollection.Register(new NetworkEntityGuid(2), new NetworkEntityGuid(2)); //act Assert.AreEqual(0, interestCollection.ContainedEntities.Count); InterestDequeueSetCommand dequeue = new InterestDequeueSetCommand(interestCollection, interestCollection); dequeue.Execute(); //assert Assert.AreEqual(2, interestCollection.ContainedEntities.Count); Assert.True(interestCollection.EnteringDequeueable.isEmpty); }
public void Test_DequeueCommand_Handles_Leaving_Entities() { //arrange //InterestDequeueSetCommand InterestCollection interestCollection = new InterestCollection(); interestCollection.Add(new NetworkEntityGuid(1)); interestCollection.Add(new NetworkEntityGuid(2)); interestCollection.Unregister(new NetworkEntityGuid(1)); interestCollection.Unregister(new NetworkEntityGuid(2)); //act Assert.AreEqual(2, interestCollection.ContainedEntities.Count, "Has no contained entites."); InterestDequeueSetCommand dequeue = new InterestDequeueSetCommand(interestCollection, interestCollection); dequeue.Execute(); //assert Assert.AreEqual(0, interestCollection.ContainedEntities.Count, "Expected the contained entities to be removed, but some remained."); Assert.True(interestCollection.LeavingDequeueable.isEmpty); }