/// <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();
                }
            }
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }