Example #1
0
        /// <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);
        }
Example #2
0
 public DefaultGameObjectActorState([NotNull] IEntityDataFieldContainer entityData,
                                    [NotNull] NetworkEntityGuid entityGuid,
                                    [NotNull] GameObjectInstanceModel instanceModel,
                                    [NotNull] GameObjectTemplateModel templateModel,
                                    [NotNull] InterestCollection interest)
     : base(entityData, entityGuid, interest)
 {
     InstanceModel = instanceModel ?? throw new ArgumentNullException(nameof(instanceModel));
     TemplateModel = templateModel ?? throw new ArgumentNullException(nameof(templateModel));
 }
Example #3
0
        protected override void OnEventFired(object source, EntityCreationStartingEventArgs args)
        {
            InterestCollection playerInterestCollection = new InterestCollection();

            //directly add ourselves so we don't become interest in ourselves after spawning
            playerInterestCollection.Add(args.EntityGuid);

            //We just create our own manaul interest collection here.
            GuidToInterestCollectionMappable.AddObject(args.EntityGuid, playerInterestCollection);
        }
Example #4
0
        protected override void OnEventFired(object source, EntityDeconstructionFinishedEventArgs args)
        {
            //At this point, the entity deconstruction is FINISHED so we can actually tell all known entites to forget it.
            //Threadsafe internally to iterate
            foreach (NetworkEntityGuid entity in KnownEntities)
            {
                InterestCollection ic = InterestCollections.RetrieveEntity(entity);

                if (ic.Contains(args.EntityGuid))
                {
                    //We just spoof an exit to every interested collection who knows of the entity being cleaned up.
                    InterestEventSpoofer.SpoofExitInterest(new EntityInterestChangeEventArgs(entity, args.EntityGuid, EntityInterestChangeEventArgs.ChangeType.Exit));
                }
            }
        }
Example #5
0
        protected override Task HandleMessage(IPeerSessionMessageContext <GameServerPacketPayload> context, PlayerNetworkTrackerChangeUpdateRequest payload, NetworkEntityGuid guid)
        {
            //TODO: Do some validation here. Players could be sending empty ones, or invalid ones.
            InterestCollection interestCollection = InterestCollections.RetrieveEntity(guid);
            PlayerNetworkTrackerChangeUpdateEvent changeUpdateEvent = new PlayerNetworkTrackerChangeUpdateEvent(new EntityAssociatedData <PlayerNetworkTrackerChangeUpdateRequest>(guid, payload));

            //Only send to players and not yourself.
            foreach (NetworkEntityGuid entity in interestCollection.ContainedEntities)
            {
                if (entity.EntityType == EntityType.Player && entity.EntityId != guid.EntityId)
                {
                    EntityMessageSender.SendMessageAsync(entity, changeUpdateEvent);
                }
            }

            return(Task.CompletedTask);
        }
Example #6
0
        /// <inheritdoc />
        protected override void OnFinishedServicingEvents()
        {
            //After ALL the queued interest changes have been serviced
            //we can actually handle the changes and send them and such

            KnownEntities.LockObject.EnterReadLock();
            try
            {
                //We need to iterate the entire interest dictionary
                //That means we need to check the new incoming and outgoing entities
                //We do this because we need to build update packets for the players
                //so that they can become aware of them AND we can start pushing
                //events to them
                foreach (var entity in KnownEntities)
                {
                    InterestCollection interestCollection = ManagedInterestCollections.RetrieveEntity(entity);

                    //We want to skip any collection that doesn't have any pending changes.
                    //No reason to send a message about it nor dequeue anything
                    if (!interestCollection.HasPendingChanges())
                    {
                        continue;
                    }

                    //We should only build packets for players.
                    if (entity.EntityType == EntityType.Player)
                    {
                        VisibilityMessageSender.Send(new EntityVisibilityChangeContext(entity, interestCollection));
                    }

                    //No matter player or NPC we should dequeue the joining/leaving
                    //entites so that the state of the known entites reflects the diff packets sent
                    InterestDequeueSetCommand dequeueCommand = new InterestDequeueSetCommand(interestCollection);

                    //TODO: Should we execute right away? Or after all packets are sent?
                    dequeueCommand.Execute();
                }
            }
            finally
            {
                KnownEntities.LockObject.ExitReadLock();
            }
        }
Example #7
0
        /// <inheritdoc />
        public void Tick()
        {
            foreach (var entry in GuidToInterestCollectionMappable.EnumerateWithGuid(KnownEntities, EntityType.Player))
            {
                InterestCollection interest = entry.ComponentValue;

                //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.RetrieveEntity(interestingEntityGuid), ChangeTrackingCollections.RetrieveEntity(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(entry.EntityGuid, updates);
                }
            }

            foreach (var dataEntityCollection in ChangeTrackingCollections.Enumerate(KnownEntities))
            {
                dataEntityCollection.ClearTrackedChanges();
            }
        }
Example #8
0
 public NetworkedObjectActorState(IEntityDataFieldContainer entityData, NetworkEntityGuid entityGuid, [NotNull] InterestCollection interest)
     : base(entityData, entityGuid)
 {
     Interest = interest ?? throw new ArgumentNullException(nameof(interest));
 }
Example #9
0
 public BehaviourGameObjectState(IEntityDataFieldContainer entityData, NetworkEntityGuid entityGuid, GameObjectInstanceModel instanceModel, GameObjectTemplateModel templateModel,
                                 [NotNull] TBehaviourType behaviourData, [NotNull] InterestCollection interest)
     : base(entityData, entityGuid, instanceModel, templateModel, interest)
 {
     BehaviourData = behaviourData ?? throw new ArgumentNullException(nameof(behaviourData));
 }
Example #10
0
 public DefaultPlayerEntityActorState(IEntityDataFieldContainer entityData, NetworkEntityGuid entityGuid, InterestCollection interest, [NotNull] IPeerPayloadSendService <GameServerPacketPayload> sendService)
     : base(entityData, entityGuid, interest)
 {
     SendService = sendService ?? throw new ArgumentNullException(nameof(sendService));
 }