Example #1
0
        /// <inheritdoc />
        public void Send(EntityMovementMessageContext context)
        {
            //When they call this, they intend to send a movement update to the connection associated
            //with the NetworkEntityGuid provided so we lookup the session associated with it
            //as well as the interest list and movement data for each individual entry int he internest
            //collection to build the movement packet.
            if (!SessionMappable.ContainsKey(context.EntityGuid))
            {
                throw new InvalidOperationException($"Tried to send movement update to Session with Guid: {context.EntityGuid} but none existed.");
            }

            //it's possible they aren't interested or have an empty interest so they may have no collection.
            if (!GuidToInterestCollectionMappable.ContainsKey(context.EntityGuid))
            {
                return;
            }

            EntityAssociatedData <IMovementData>[] movementBlocks = BuildMovementBlocks(context.EntityGuid);

            //it is possible that no movement data needs to be sent, because none is ddirty so we need to check
            if (movementBlocks.Length == 0)
            {
                return;
            }

            MovementDataUpdateEventPayload movementUpdateEvent = new MovementDataUpdateEventPayload(movementBlocks);

            SessionMappable[context.EntityGuid].SendMessage(movementUpdateEvent);
        }
        /// <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);
        }
Example #3
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();
            }
        }
 private InterestCollection GetEntityInterestCollection(NetworkEntityGuid guid)
 {
     try
     {
         return(GuidToInterestCollectionMappable[guid]);
     }
     catch (Exception e)
     {
         throw new InvalidOperationException($"Attempted to load Entity: {guid}'s interst collection From: {GuidToInterestCollectionMappable.GetType().Name} but failed. No interest collection matched the key. Exception: {e.Message}", e);
     }
 }