public void Spawn(int id, Type type, Action <IEntity> callback = null)
        {
            lock (m_SpawnedEntities)
            {
                if (m_SpawnedEntities.ContainsKey(id))
                {
                    throw new Exception($"Entity #{id} exists already!");
                }
            }

            if (!typeof(IEntity).IsAssignableFrom(type) || type.IsAbstract || type.IsInterface || !type.IsClass)
            {
                throw new Exception("Failed to spawn invalid entity: " + type.FullName);
            }

            m_Logger.LogDebug($"Spawning entity {type.Name}@{id}");

            m_TaskScheduler.RunOnMainThread(this, () =>
            {
                var entityInstance = (IEntity)m_Container.Activate(type);
                entityInstance.Id  = id;
                entityInstance.Init();

                lock (m_SpawnedEntities)
                {
                    m_SpawnedEntities.Add(entityInstance.Id, entityInstance);
                }

                callback?.Invoke(entityInstance);
            }, $"SpawnEntity-[{type.Name}]@{id}");
        }
        public void RegisterPacketHandler <T>() where T : class, IPacketHandler
        {
            var instance = m_Container.Activate <T>();

            if (!m_PacketHandlers.ContainsKey(instance.PacketId))
            {
                m_PacketHandlers.Add(instance.PacketId, new List <IPacketHandler>());
            }

            m_PacketHandlers[instance.PacketId].Add(instance);
        }