private void HandleItemCreated(INetworkEntity item)
 {
     if (item is ILayerable layerable)
     {
         _layerables.TryAdd(layerable);
     }
 }
Example #2
0
        /// <summary>
        /// Called when an Update message has arrived, applies the new state to the entity.
        /// </summary>
        /// <param name="entityId">The unique identifier for the entity.</param>
        /// <param name="payload">The object that will be used to apply the entity's starting state.</param>
        /// <param name="isReckoning">True if this is a reckoning update.</param>
        /// <param name="time">The time the message was sent, used for projecting the state to current time.</param>
        private void UpdateEntity(long entityId, long ownerId, object payload, bool isReckoning, double time)
        {
            INetworkEntity targetEntity = mEntities.Where(e => e.EntityId == entityId && e.OwnerId == ownerId).SingleOrDefault();

            // TODO: automatically create entity?
            // ignore if null, entity creation message may not have arrived

            mLog?.Info($"Receiving update from {ownerId} to update entity {payload?.GetType()}");

            if (targetEntity != null)
            {
                if (targetEntity.OwnerId != this.NetworkId || isReckoning)
                {
                    targetEntity.UpdateFromState(payload, time);
                }

                BroadcastIfServer(entityId, targetEntity.OwnerId, payload,
                                  isReckoning ?
                                  NetworkMessageType.Reckoning :
                                  NetworkMessageType.Update
                                  );
            }
            else
            {
                mLog.Debug("Couldn't find entity to update: " + entityId);
            }
        }
Example #3
0
    public Session(INetworkEntity entity, int accountID)
    {
        if (entity.GetEntityType() != EntityType.PC)
        {
            throw new ArgumentException("Cannot start session with non player entity");
        }

        AccountID   = accountID;
        this.Entity = entity;
    }
        /// <summary>
        /// Returns the owning player.
        /// </summary>
        /// <param name="entity">The entity to receive the owning player from</param>
        /// <returns>The player that owns the entity.</returns>
        public static IPlayer GetOwner([NotNull] this INetworkEntity entity)
        {
            int ownerId = entity.OwnerId;

            if (entity.OwnerId == -1)
            {
                return(entity.Manager.GetServerPlayer());
            }

            return(entity.Manager?.GetPlayer(ownerId));
        }
Example #5
0
 /// <summary>
 /// Broadcasts a message to all clients to update the provided entity.
 /// Note that this is broadcast only. No updating should happen until
 /// a message is received.
 /// </summary>
 /// <param name="entity">The entity to update.</param>
 public void RequestUpdateEntity(INetworkEntity entity)
 {
     if (Role == NetworkRole.Server)
     {
         UpdateEntity(entity.EntityId, entity.OwnerId, entity.GetState(), true, ServerTime);
     }
     else
     {
         SendDataMessage(entity, NetworkMessageType.Update);
     }
 }
Example #6
0
        public void AddToEntities(INetworkEntity entityToAdd)
        {
#if DEBUG
            if (mEntities.Contains(entityToAdd))
            {
                throw new InvalidOperationException("This entity is already part of the list, it can't be added again.");
            }
#endif
            entityToAdd.EntityId = GetUniqueEntityId();
            mEntities.Add(entityToAdd);
        }
Example #7
0
 /// <summary>
 /// Broadcasts a message to all clients to destroy the provided entity.
 /// Note that this is broadcast only. No destruction should happen until
 /// a message is received.
 /// </summary>
 /// <param name="entity">The entity to destroy.</param>
 public void RequestDestroyEntity(INetworkEntity entity)
 {
     if (Role == NetworkRole.Server)
     {
         DestroyEntity(entity.EntityId, entity.OwnerId);
     }
     else
     {
         SendDataMessage(entity, NetworkMessageType.Destroy);
     }
 }
Example #8
0
        /// <summary>
        /// Uses the provided entity to compose a data message.
        /// ReliableSequenced method is suggested to balance performance with deliverability.
        /// </summary>
        /// <param name="entity">The entity to build a message from.</param>
        /// <param name="action">The type of message to send.</param>
        /// <param name="method">Delivery method.</param>
        /// <param name="recipient">The recipient connection. Will send to all if null.</param>
        private void SendDataMessage(INetworkEntity entity, NetworkMessageType action, NetConnection recipient = null)
        {
            // clients can't force a message for an entity they don't own
            if (Role != NetworkRole.Server && entity.OwnerId != NetworkId)
            {
                throw new RedGrinException("Cannot send an update for an entity that is not owned by this client!");
            }

            object payload = entity.GetState();

            SendDataMessage(entity.EntityId, entity.OwnerId, payload, action, recipient);
        }
Example #9
0
        /// <summary>
        /// Called when a Destroy message has arrived, destroys an entity.
        /// </summary>
        /// <param name="entityId">The unique ID of the entity to be destroyed</param>
        private void DestroyEntity(long entityId)
        {
            INetworkEntity target = mEntities.Where(e => e.EntityId == entityId).SingleOrDefault();

            if (target != null)
            {
                BroadcastIfServer(target.EntityId, target.OwnerId, null, NetworkMessageType.Destroy);
                mEntities.Remove(target);
                GameArena?.RequestDestroyEntity(target);
            }
            else
            {
                mLog.Debug("Couldn't find entity marked for destruction: " + entityId);
            }
        }
Example #10
0
        /// <summary>
        /// Called when an Update message has arrived, applies the new state to the entity.
        /// </summary>
        /// <param name="entityId">The unique identifier for the entity.</param>
        /// <param name="payload">The object that will be used to apply the entity's starting state.</param>
        /// <param name="isReckoning">True if this is a reckoning update.</param>
        /// <param name="time">The time the message was sent, used for projecting the state to current time.</param>
        private void UpdateEntity(ulong id, object payload, bool isReckoning, double time)
        {
            INetworkEntity targetEntity = entities.Where(e => e.Id == id).SingleOrDefault();

            if (targetEntity != null)
            {
                targetEntity.UpdateFromState(payload, time, isReckoning);
                BroadcastIfServer(id, payload, isReckoning ? NetworkMessageType.Reckoning : NetworkMessageType.Update);
            }
            else
            {
                // ignore if null, entity creation message may not have arrived yet
                log.Debug("Couldn't find entity to update: " + id);
            }
        }
Example #11
0
        /// <summary>
        /// Called when a Destroy message has arrived, destroys an entity.
        /// </summary>
        /// <param name="entityId">The unique ID of the entity to be destroyed</param>
        private void DestroyEntity(ulong id)
        {
            INetworkEntity target = entities.Where(e => e.Id == id).SingleOrDefault();

            if (target != null)
            {
                log.Debug($"Destroying entity {id}");
                BroadcastIfServer(target.Id, null, NetworkMessageType.Destroy);
                entities.Remove(target);
                GameArena?.HandleDestroyEntity(target);
            }
            else
            {
                log.Debug($"Couldn't find entity marked for destruction: {id}");
            }
        }
Example #12
0
        /// <summary>
        /// Sends a Destroy message for all entities owned by a specific NetworkId.
        /// Usually called in Server mode when a client disconnects to update other clients
        /// </summary>
        /// <param name="ownerId">The OwnerId of entities to destroy.</param>
        private void DestroyAllOwnedById(long ownerId)
        {
            for (int i = mEntities.Count - 1; i > -1; i--)
            {
                INetworkEntity entity = mEntities[i];

                if (entity.OwnerId == ownerId)
                {
                    SendDataMessage(entity, NetworkMessageType.Destroy);
                    if (Role == NetworkRole.Server)
                    {
                        DestroyEntity(entity.EntityId, ownerId);
                    }
                }
            }
        }
Example #13
0
        /// <summary>
        /// Called when a Create message has arrived, gets an entity from the game screen.
        /// </summary>
        /// <param name="ownerId">The NetworkId of the peer that controls the new entity.</param>
        /// <param name="entityId">The unique identifier for the entity.</param>
        /// <param name="payload">The object that will be used to apply the entity's starting state.</param>
        /// <param name="time">The time the message was sent, used for projecting the state to current time.</param>
        private void CreateEntity(ulong id, object payload, double time)
        {
            // check entity with ID already exists
            INetworkEntity targetEntity = entities.Where(e => e.Id == id).SingleOrDefault();

            if (targetEntity == null)
            {
                targetEntity = GameArena?.HandleCreateEntity(id, payload);

                // force correct unique ID
                targetEntity.Id = id;
            }
            targetEntity.UpdateFromState(payload, time, false);
            entities.Add(targetEntity);

            BroadcastIfServer(id, payload, NetworkMessageType.Create);
        }
Example #14
0
        /// <summary>
        /// Called when an Update message has arrived, applies the new state to the entity.
        /// </summary>
        /// <param name="entityId">The unique identifier for the entity.</param>
        /// <param name="payload">The object that will be used to apply the entity's starting state.</param>
        /// <param name="isReckoning">True if this is a reckoning update.</param>
        /// <param name="time">The time the message was sent, used for projecting the state to current time.</param>
        private void UpdateEntity(long entityId, long ownerId, object payload, bool isReckoning, double time)
        {
            INetworkEntity targetEntity = mEntities.Where(e => e.EntityId == entityId && e.OwnerId == ownerId).SingleOrDefault();

            // TODO: automatically create entity?
            // ignore if null, entity creation message may not have arrived
            if (targetEntity != null)
            {
                targetEntity.UpdateState(payload, time, isReckoning);

                BroadcastIfServer(entityId, targetEntity.OwnerId, payload,
                                  isReckoning ?
                                  NetworkMessageType.Update :
                                  NetworkMessageType.Reckoning);
            }
            else
            {
                mLog.Debug("Couldn't find entity to update: " + entityId);
            }
        }
Example #15
0
        /// <summary>
        /// Called when a Create message has arrived, gets an entity from the game screen.
        /// </summary>
        /// <param name="ownerId">The NetworkId of the peer that controls the new entity.</param>
        /// <param name="entityId">The unique identifier for the entity.</param>
        /// <param name="payload">The object that will be used to apply the entity's starting state.</param>
        /// <param name="time">The time the message was sent, used for projecting the state to current time.</param>
        private void CreateEntity(long ownerId, long entityId, object payload, double time)
        {
            // check if already exists.
            INetworkEntity targetEntity = mEntities.Where(e => e.EntityId == entityId && e.OwnerId == ownerId).SingleOrDefault();

            if (targetEntity == null)
            {
                targetEntity = GameArena.RequestCreateEntity(ownerId, entityId, payload);
            }
            else
            {
                mLog.Warning("Attempted to create entity for ID that already exists: " + entityId);
            }

            targetEntity.OwnerId  = ownerId;
            targetEntity.EntityId = entityId;
            targetEntity.UpdateState(payload, time);
            mEntities.Add(targetEntity);

            BroadcastIfServer(entityId, ownerId, payload, NetworkMessageType.Create);
        }
Example #16
0
        /// <summary>
        /// Sends a Destroy message for all entities that no longer have an owner
        /// </summary>
        private void DestroyUnownedEntities()
        {
            // ensure our connections list is accurate
            RefreshConnectionCollection();

            for (int i = entities.Count - 1; i > -1; i--)
            {
                INetworkEntity entity = entities[i];
                var            id     = entity.GetClientId();

                // if we don't own the entity and its ClientId isn't in the map
                // the client must have disconnected and the entity should be destroyed
                if (id != ClientId && !clientIdConnectionMap.ContainsKey(entity.GetClientId()))
                {
                    SendDataMessage(entity, NetworkMessageType.Destroy);
                    if (Role == NetworkRole.Server)
                    {
                        DestroyEntity(entity.Id);
                    }
                }
            }
        }
        /// <summary>
        /// Returns true if the entity belongs to the local client or false if it belongs to a remote client.
        /// </summary>
        /// <param name="entity">The entity to test for</param>
        /// <returns>true if the entity belongs to the local client or false if it belongs to a remote client</returns>
        /// <exception cref="InvalidOperationException">If the Entity is not initialized</exception>
        public static bool IsLocal(this INetworkEntity entity)
        {
            if (entity.Manager == null)
            {
                return(false);
            }

            var connection    = entity.Manager?.Connection;
            int localClientId = connection.LocalClient.ClientId;

            if (localClientId == -1)
            {
                return(false);
            }

            if (connection.IsServer() && entity.IsOwnedByScene())
            {
                return(true);
            }

            return(localClientId != -1 && entity.OwnerId == localClientId);
        }
Example #18
0
        /// <summary>
        /// Called when a Create message has arrived, gets an entity from the game screen.
        /// </summary>
        /// <param name="ownerId">The NetworkId of the peer that controls the new entity.</param>
        /// <param name="entityId">The unique identifier for the entity.</param>
        /// <param name="payload">The object that will be used to apply the entity's starting state.</param>
        /// <param name="time">The time the message was sent, used for projecting the state to current time.</param>
        private void CreateEntity(long ownerId, long entityId, object payload, double time)
        {
            // this is a brand new entity, get a new ID
            if (entityId == -1)
            {
                if (Role == NetworkRole.Server)
                {
                    entityId = GetUniqueEntityId();
                }
                else
                {
                    var msg = "Something went wrong, client received bad entity ID.";
                    mLog.Error(msg);
                    throw new RedGrinException(msg);
                }
            }

            // check entity with ID already exists
            INetworkEntity targetEntity = mEntities.Where(e => e.EntityId == entityId).SingleOrDefault();

            if (targetEntity == null)
            {
                targetEntity = GameArena?.RequestCreateEntity(ownerId, payload);
            }
            else
            {
                var msg = "Attempted to create entity for ID that already exists: " + entityId;
                mLog?.Error(msg);
                throw new RedGrinException(msg);
            }

            targetEntity.UpdateFromState(payload, time);
            targetEntity.OwnerId  = ownerId;
            targetEntity.EntityId = entityId;
            mEntities.Add(targetEntity);

            BroadcastIfServer(entityId, ownerId, payload, NetworkMessageType.Create);
        }
 /// <summary>
 /// Destroys given entity on all clients.
 /// </summary>
 /// Unregisters the given entity and sends its destroy event to all other clients.
 /// <param name="entity">The entity to destroy</param>
 public static void Destroy(this INetworkEntity entity)
 {
     entity.Manager?.DestroyEntity(entity);
 }
 /// <summary>
 /// Returns the owning player.
 /// </summary>
 /// <param name="entity">The entity to receive the owning player from</param>
 /// <returns>The player that owns the entity.</returns>
 public static TPlayerEntity GetOwner <TPlayerEntity>([NotNull] this INetworkEntity entity) where TPlayerEntity : class, IPlayer
 {
     return(entity.Manager?.GetPlayer(entity.OwnerId) as TPlayerEntity);
 }
Example #21
0
        /// <summary>
        /// Uses the provided entity to compose a data message.
        /// ReliableSequenced method is suggested to balance performance with deliverability.
        /// </summary>
        /// <param name="entity">The entity to build a message from.</param>
        /// <param name="action">The type of message to send.</param>
        /// <param name="method">Delivery method.</param>
        /// <param name="recipient">The recipient connection. Will send to all if null.</param>
        private void SendDataMessage(INetworkEntity entity, NetworkMessageType action, NetConnection recipient = null)
        {
            object payload = entity.GetState();

            SendDataMessage(entity.Id, payload, action, recipient);
        }
 public static T[] GetNetworkComponents <T>(this INetworkEntity entity) where T : INetworkComponent
 {
     return(entity.Components.OfType <T>().ToArray());
 }
 public static T GetNetworkComponent <T>(this INetworkEntity entity) where T : INetworkComponent
 {
     return(entity.Components.OfType <T>().FirstOrDefault());
 }
        /// <summary>
        /// Checks whether an entity is owned by this client on the
        /// network by unpacking the client ID from the entity and
        /// comparing it to the network's client ID
        /// </summary>
        /// <param name="entity">The entity to check</param>
        /// <returns>True if entity's owner ID matches this Client ID</returns>
        public static bool IsOwned(this INetworkEntity entity)
        {
            var id = UnpackClientId(entity.Id);

            return(id == NetworkManager.Self.ClientId);
        }
 /// <summary>
 /// Returns if the entity is owned by the scene.
 /// </summary>
 /// Scene-owned entities are controlled by the server.
 ///
 /// <param name="entity">The entity to test for</param>
 /// <returns>Whether the entity is owned by the scene</returns>
 public static bool IsOwnedByScene([NotNull] this INetworkEntity entity)
 {
     return(entity.OwnerId == -1);
 }
 /// <summary>
 /// Gets the owning client's identifier from an entity's UniqueId
 /// </summary>
 /// <param name="entity">The INetworkEntity to use</param>
 /// <returns>The client ID that created the entity</returns>
 public static byte GetClientId(this INetworkEntity entity)
 {
     return(UnpackClientId(entity.Id));
 }
 /// <summary>
 /// Sets the Unique Id on the provided entity by packing the
 /// client ID and entity Id values.
 /// </summary>
 /// <param name="entity">The INetworkEntity to affect</param>
 /// <param name="clientId">The client identifier creating the entity</param>
 /// <param name="entityId">The entity's local identifier on the client</param>
 public static void SetEntityId(this INetworkEntity entity, byte clientId, uint entityId)
 {
     entity.Id = PackUniqueId(clientId, entityId);
 }
Example #28
0
 private void HandleNetworkEntityRemovedFromPipe(IServiceList <INetworkEntity> sender, INetworkEntity networkEntity)
 {
     // Broadcast the delete message to all users who are not also in the new NE's pipe.
     networkEntity.Messages[Guppy.Network.Constants.Messages.NetworkEntity.Delete].Create(
         this.Entity.Users.Connections.Except(networkEntity.Pipe?.Users.Connections ?? Enumerable.Empty <NetConnection>()));
 }
Example #29
0
 private void HandleNetworkEntityAddedToPipe(IServiceList <INetworkEntity> sender, INetworkEntity networkEntity)
 {
     // Broadcast create message through the pipe...
     networkEntity.Messages[Guppy.Network.Constants.Messages.NetworkEntity.Create].Create(this.Entity);
 }
 public static ISerializer GetSerializer([NotNull] this INetworkEntity entity)
 {
     return(entity.Manager?.GetSerializer());
 }