public void Update( )
        {
            if ( !Loaded )
                return;
            if ( !Initialized )
                return;
            if ( !MySandboxGameWrapper.IsGameStarted )
                return;

            _lastUpdateTime = DateTime.Now - _lastUpdate;
            _averageUpdateInterval = ( _averageUpdateTime + _lastUpdateTime.TotalMilliseconds ) / 2;
            _lastUpdate = DateTime.Now;

            EntityEventManager.Instance.ResourceLocked = true;

            List<EntityEventManager.EntityEvent> events = EntityEventManager.Instance.EntityEvents;
            List<ChatManager.ChatEvent> chatEvents = ChatManager.Instance.ChatEvents;

            //Generate the player join/leave events here
            List<ulong> connectedPlayers = PlayerManager.Instance.ConnectedPlayers;
            try
            {
                foreach ( ulong steamId in connectedPlayers )
                {
                    if ( !_lastConnectedPlayerList.Contains( steamId ) )
                    {
                        EntityEventManager.EntityEvent playerEvent = new EntityEventManager.EntityEvent
                                                                     {
                                                                         priority = 1,
                                                                         timestamp = DateTime.Now,
                                                                         type = EntityEventManager.EntityEventType.OnPlayerJoined,
                                                                         entity = steamId
                                                                     };
                        //TODO - Find a way to stall the event long enough for a linked character entity to exist - this is impossible because of cockpits and respawnships
                        //For now, create a dummy entity just for passing the player's steam id along
                        events.Add( playerEvent );
                    }
                }
                foreach ( ulong steamId in _lastConnectedPlayerList )
                {
                    if ( !connectedPlayers.Contains( steamId ) )
                    {
                        EntityEventManager.EntityEvent playerEvent = new EntityEventManager.EntityEvent
                                                                     {
                                                                         priority = 1,
                                                                         timestamp = DateTime.Now,
                                                                         type = EntityEventManager.EntityEventType.OnPlayerLeft,
                                                                         entity = steamId
                                                                     };
                        //TODO - Find a way to stall the event long enough for a linked character entity to exist - this is impossible because of cockpits and respawnships
                        //For now, create a dummy entity just for passing the player's steam id along
                        events.Add( playerEvent );
                    }
                }
            }
            catch ( Exception ex )
            {
                ApplicationLog.BaseLog.Error( ex );
            }
            _lastConnectedPlayerList = new List<ulong>( connectedPlayers );

            //Run the update threads on the plugins
            foreach ( Guid key in Plugins.Keys )
            {
                object plugin = Plugins[ key ];

                if ( !PluginStates.ContainsKey( key ) )
                    continue;

                PluginManagerThreadParams parameters = new PluginManagerThreadParams
                                                       {
                                                           Plugin = plugin,
                                                           Key = key,
                                                           Plugins = Plugins,
                                                           PluginState = PluginStates,
                                                           Events = new List<EntityEventManager.EntityEvent>( events ),
                                                           ChatEvents = new List<ChatManager.ChatEvent>( chatEvents )
                                                       };

                ThreadPool.QueueUserWorkItem( DoUpdate, parameters );
                //				Thread pluginThread = new Thread(DoUpdate);
                //				pluginThread.Start(parameters);
            }

            //Capture profiling info if debugging is on
            if ( ExtenderOptions.IsDebugging )
            {
                _averageEvents = ( _averageEvents + ( events.Count + chatEvents.Count ) ) / 2;

                TimeSpan updateTime = DateTime.Now - _lastUpdate;
                _averageUpdateTime = ( _averageUpdateTime + updateTime.TotalMilliseconds ) / 2;

                TimeSpan timeSinceAverageOutput = DateTime.Now - _lastAverageOutput;
                if ( timeSinceAverageOutput.TotalSeconds > 30 )
                {
                    _lastAverageOutput = DateTime.Now;

                    ApplicationLog.BaseLog.Debug( "PluginManager - Update interval = {0}ms", _averageUpdateInterval );
                    ApplicationLog.BaseLog.Debug( "PluginManager - Update time = {0}ms", _averageUpdateTime );
                    ApplicationLog.BaseLog.Debug( "PluginManager - Events per update = {0}", _averageEvents );
                }
            }

            //Clean up the event managers
            EntityEventManager.Instance.ClearEvents( );
            EntityEventManager.Instance.ResourceLocked = false;
            ChatManager.Instance.ClearEvents( );
        }
        public static void DoUpdate(object _parameters)
        {
            if (_parameters == null)
            {
                return;
            }
            PluginManagerThreadParams parameters = (PluginManagerThreadParams)_parameters;

            List <EntityEventManager.EntityEvent> events     = parameters.events;
            List <ChatManager.ChatEvent>          chatEvents = parameters.chatEvents;
            Object plugin = parameters.plugin;

            //Run entity events
            foreach (EntityEventManager.EntityEvent entityEvent in events)
            {
                //If this is a cube block created event and the parent cube grid is still loading then defer the event
                if (entityEvent.type == EntityEventManager.EntityEventType.OnCubeBlockCreated)
                {
                    CubeBlockEntity cubeBlock = (CubeBlockEntity)entityEvent.entity;
                    if (cubeBlock.Parent.IsLoading)
                    {
                        EntityEventManager.Instance.AddEvent(entityEvent);
                        continue;
                    }
                }

                switch (entityEvent.type)
                {
                case EntityEventManager.EntityEventType.OnPlayerJoined:
                    try
                    {
                        MethodInfo updateMethod = plugin.GetType().GetMethod("OnPlayerJoined");
                        if (updateMethod != null)
                        {
                            //FIXME - Temporary hack to pass along the player's steam id
                            ulong steamId = (ulong)entityEvent.entity;
                            updateMethod.Invoke(plugin, new object[] { steamId });
                        }
                    }
                    catch (Exception ex)
                    {
                        LogManager.ErrorLog.WriteLine(ex);
                    }
                    break;

                case EntityEventManager.EntityEventType.OnPlayerLeft:
                    try
                    {
                        MethodInfo updateMethod = plugin.GetType().GetMethod("OnPlayerLeft");
                        if (updateMethod != null)
                        {
                            //FIXME - Temporary hack to pass along the player's steam id
                            ulong steamId = (ulong)entityEvent.entity;
                            updateMethod.Invoke(plugin, new object[] { steamId });
                        }
                    }
                    catch (Exception ex)
                    {
                        LogManager.ErrorLog.WriteLine(ex);
                    }
                    break;

                default:
                    try
                    {
                        string     methodName   = entityEvent.type.ToString();
                        MethodInfo updateMethod = plugin.GetType().GetMethod(methodName);
                        if (updateMethod != null)
                        {
                            updateMethod.Invoke(plugin, new object[] { entityEvent.entity });
                        }
                    }
                    catch (Exception ex)
                    {
                        LogManager.ErrorLog.WriteLine(ex);
                    }
                    break;
                }
            }

            //Run chat events
            foreach (ChatManager.ChatEvent chatEvent in chatEvents)
            {
                try
                {
                    string     methodName   = chatEvent.type.ToString();
                    MethodInfo updateMethod = plugin.GetType().GetMethod(methodName);
                    if (updateMethod != null)
                    {
                        updateMethod.Invoke(plugin, new object[] { chatEvent });
                    }
                }
                catch (Exception ex)
                {
                    LogManager.ErrorLog.WriteLine(ex);
                }
            }

            //Run update
            try
            {
                MethodInfo updateMethod = plugin.GetType().GetMethod("Update");
                updateMethod.Invoke(plugin, new object[] { });
            }
            catch (Exception ex)
            {
                LogManager.ErrorLog.WriteLine(ex);
            }
        }
        public void Update()
        {
            if (!Loaded)
            {
                return;
            }
            if (!Initialized)
            {
                return;
            }
            if (!SandboxGameAssemblyWrapper.Instance.IsGameStarted)
            {
                return;
            }

            m_lastUpdateTime        = DateTime.Now - m_lastUpdate;
            m_averageUpdateInterval = (m_averageUpdateTime + m_lastUpdateTime.TotalMilliseconds) / 2;
            m_lastUpdate            = DateTime.Now;

            EntityEventManager.Instance.ResourceLocked = true;

            List <EntityEventManager.EntityEvent> events     = EntityEventManager.Instance.EntityEvents;
            List <ChatManager.ChatEvent>          chatEvents = ChatManager.Instance.ChatEvents;

            //Generate the player join/leave events here
            List <ulong> connectedPlayers = PlayerManager.Instance.ConnectedPlayers;

            try
            {
                foreach (ulong steamId in connectedPlayers)
                {
                    if (!m_lastConnectedPlayerList.Contains(steamId))
                    {
                        EntityEventManager.EntityEvent playerEvent = new EntityEventManager.EntityEvent();
                        playerEvent.priority  = 1;
                        playerEvent.timestamp = DateTime.Now;
                        playerEvent.type      = EntityEventManager.EntityEventType.OnPlayerJoined;
                        //TODO - Find a way to stall the event long enough for a linked character entity to exist - this is impossible because of cockpits and respawnships
                        //For now, create a dummy entity just for passing the player's steam id along
                        playerEvent.entity = (Object)steamId;
                        events.Add(playerEvent);
                    }
                }
                foreach (ulong steamId in m_lastConnectedPlayerList)
                {
                    if (!connectedPlayers.Contains(steamId))
                    {
                        EntityEventManager.EntityEvent playerEvent = new EntityEventManager.EntityEvent();
                        playerEvent.priority  = 1;
                        playerEvent.timestamp = DateTime.Now;
                        playerEvent.type      = EntityEventManager.EntityEventType.OnPlayerLeft;
                        //TODO - Find a way to stall the event long enough for a linked character entity to exist - this is impossible because of cockpits and respawnships
                        //For now, create a dummy entity just for passing the player's steam id along
                        playerEvent.entity = (Object)steamId;
                        events.Add(playerEvent);
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.APILog.WriteLine("PluginManager.Update() Exception in player discovery: " + ex.ToString());
            }
            m_lastConnectedPlayerList = new List <ulong>(connectedPlayers);

            //Run the update threads on the plugins
            foreach (var key in m_plugins.Keys)
            {
                var plugin = m_plugins[key];

                if (!m_pluginState.ContainsKey(key))
                {
                    continue;
                }

                PluginManagerThreadParams parameters = new PluginManagerThreadParams();
                parameters.plugin     = plugin;
                parameters.key        = key;
                parameters.events     = new List <EntityEventManager.EntityEvent>(events);
                parameters.chatEvents = new List <ChatManager.ChatEvent>(chatEvents);

                Thread pluginThread = new Thread(DoUpdate);
                pluginThread.Start(parameters);
            }

            //Capture profiling info if debugging is on
            if (SandboxGameAssemblyWrapper.IsDebugging)
            {
                m_averageEvents = (m_averageEvents + (events.Count + chatEvents.Count)) / 2;

                TimeSpan updateTime = DateTime.Now - m_lastUpdate;
                m_averageUpdateTime = (m_averageUpdateTime + updateTime.TotalMilliseconds) / 2;

                TimeSpan timeSinceAverageOutput = DateTime.Now - m_lastAverageOutput;
                if (timeSinceAverageOutput.TotalSeconds > 30)
                {
                    m_lastAverageOutput = DateTime.Now;

                    LogManager.APILog.WriteLine("PluginManager - Update interval = " + m_averageUpdateInterval.ToString() + "ms");
                    LogManager.APILog.WriteLine("PluginManager - Update time = " + m_averageUpdateTime.ToString() + "ms");
                    LogManager.APILog.WriteLine("PluginManager - Events per update = " + m_averageEvents.ToString());
                }
            }

            //Clean up the event managers
            EntityEventManager.Instance.ClearEvents();
            EntityEventManager.Instance.ResourceLocked = false;
            ChatManager.Instance.ClearEvents();
        }
        public static void DoUpdate(object args)
        {
            try
            {
                if (args == null)
                {
                    return;
                }
                PluginManagerThreadParams parameters = (PluginManagerThreadParams)args;

                List <EntityEventManager.EntityEvent> events     = parameters.Events;
                List <ChatManager.ChatEvent>          chatEvents = parameters.ChatEvents;
                Object plugin = parameters.Plugin;
                Dictionary <Guid, IPlugin> plugins     = parameters.Plugins;
                Dictionary <Guid, bool>    pluginState = parameters.PluginState;

                //Run entity events
                foreach (EntityEventManager.EntityEvent entityEvent in events)
                {
                    //If this is a cube block created event and the parent cube grid is still loading then defer the event
                    if (entityEvent.type == EntityEventManager.EntityEventType.OnCubeBlockCreated)
                    {
                        CubeBlockEntity cubeBlock = (CubeBlockEntity)entityEvent.entity;
                        if (cubeBlock.Parent.IsLoading)
                        {
                            EntityEventManager.Instance.AddEvent(entityEvent);
                            continue;
                        }
                    }

                    switch (entityEvent.type)
                    {
                    case EntityEventManager.EntityEventType.OnPlayerJoined:
                        try
                        {
                            MethodInfo updateMethod = plugin.GetType( ).GetMethod("OnPlayerJoined");
                            if (updateMethod != null)
                            {
                                //FIXME - Temporary hack to pass along the player's steam id
                                ulong steamId = (ulong)entityEvent.entity;
                                updateMethod.Invoke(plugin, new object[] { steamId });
                            }
                        }
                        catch (Exception ex)
                        {
                            ApplicationLog.BaseLog.Error(ex);
                        }
                        break;

                    case EntityEventManager.EntityEventType.OnPlayerLeft:
                        try
                        {
                            MethodInfo updateMethod = plugin.GetType( ).GetMethod("OnPlayerLeft");
                            if (updateMethod != null)
                            {
                                //FIXME - Temporary hack to pass along the player's steam id
                                ulong steamId = (ulong)entityEvent.entity;
                                updateMethod.Invoke(plugin, new object[] { steamId });
                            }
                        }
                        catch (Exception ex)
                        {
                            ApplicationLog.BaseLog.Error(ex);
                        }
                        break;

                    case EntityEventManager.EntityEventType.OnPlayerWorldSent:
                        try
                        {
                            MethodInfo updateMethod = plugin.GetType( ).GetMethod("OnPlayerWorldSent");
                            if (updateMethod != null)
                            {
                                //FIXME - Temporary hack to pass along the player's steam id
                                ulong steamId = (ulong)entityEvent.entity;
                                updateMethod.Invoke(plugin, new object[] { steamId });
                            }
                        }
                        catch (Exception ex)
                        {
                            ApplicationLog.BaseLog.Error(ex);
                        }
                        break;

                    default:
                        try
                        {
                            string     methodName   = entityEvent.type.ToString( );
                            MethodInfo updateMethod = plugin.GetType( ).GetMethod(methodName);
                            if (updateMethod != null)
                            {
                                updateMethod.Invoke(plugin, new[] { entityEvent.entity });
                            }
                        }
                        catch (Exception ex)
                        {
                            ApplicationLog.BaseLog.Error(ex);
                        }
                        break;
                    }
                }

                //Run chat events
                foreach (ChatManager.ChatEvent chatEvent in chatEvents)
                {
                    try
                    {
                        bool discard = false;
                        HookChatMessage(plugin, plugins, pluginState, chatEvent, out discard);

                        if (discard)
                        {
                            continue;
                        }

                        string     methodName   = chatEvent.Type.ToString( );
                        MethodInfo updateMethod = plugin.GetType( ).GetMethod(methodName);
                        if (updateMethod != null)
                        {
                            updateMethod.Invoke(plugin, new object[] { chatEvent });
                        }
                    }
                    catch (Exception ex)
                    {
                        ApplicationLog.BaseLog.Error(ex);
                    }
                }

                //Run update
                try
                {
                    MethodInfo updateMethod = plugin.GetType( ).GetMethod("Update");
                    updateMethod.Invoke(plugin, new object[] { });
                }
                catch (Exception ex)
                {
                    ApplicationLog.BaseLog.Error(ex);
                }
            }
            catch (Exception ex)
            {
                ApplicationLog.BaseLog.Error(ex);
            }
        }
        public void Update( )
        {
            if (!Loaded)
            {
                return;
            }
            if (!Initialized)
            {
                return;
            }
            if (!MySandboxGameWrapper.IsGameStarted)
            {
                return;
            }

            _lastUpdateTime        = DateTime.Now - _lastUpdate;
            _averageUpdateInterval = (_averageUpdateTime + _lastUpdateTime.TotalMilliseconds) / 2;
            _lastUpdate            = DateTime.Now;

            EntityEventManager.Instance.ResourceLocked = true;

            List <EntityEventManager.EntityEvent> events     = EntityEventManager.Instance.EntityEvents;
            List <ChatManager.ChatEvent>          chatEvents = ChatManager.Instance.ChatEvents;

            //Generate the player join/leave events here
            List <ulong> connectedPlayers = PlayerManager.Instance.ConnectedPlayers;

            try
            {
                foreach (ulong steamId in connectedPlayers)
                {
                    if (!_lastConnectedPlayerList.Contains(steamId))
                    {
                        EntityEventManager.EntityEvent playerEvent = new EntityEventManager.EntityEvent
                        {
                            priority  = 1,
                            timestamp = DateTime.Now,
                            type      = EntityEventManager.EntityEventType.OnPlayerJoined,
                            entity    = steamId
                        };
                        //TODO - Find a way to stall the event long enough for a linked character entity to exist - this is impossible because of cockpits and respawnships
                        //For now, create a dummy entity just for passing the player's steam id along
                        events.Add(playerEvent);
                    }
                }
                foreach (ulong steamId in _lastConnectedPlayerList)
                {
                    if (!connectedPlayers.Contains(steamId))
                    {
                        EntityEventManager.EntityEvent playerEvent = new EntityEventManager.EntityEvent
                        {
                            priority  = 1,
                            timestamp = DateTime.Now,
                            type      = EntityEventManager.EntityEventType.OnPlayerLeft,
                            entity    = steamId
                        };
                        //TODO - Find a way to stall the event long enough for a linked character entity to exist - this is impossible because of cockpits and respawnships
                        //For now, create a dummy entity just for passing the player's steam id along
                        events.Add(playerEvent);
                    }
                }
            }
            catch (Exception ex)
            {
                ApplicationLog.BaseLog.Error(ex);
            }
            _lastConnectedPlayerList = new List <ulong>(connectedPlayers);

            //Run the update threads on the plugins
            foreach (Guid key in Plugins.Keys)
            {
                object plugin = Plugins[key];

                if (!PluginStates.ContainsKey(key))
                {
                    continue;
                }

                PluginManagerThreadParams parameters = new PluginManagerThreadParams
                {
                    Plugin      = plugin,
                    Key         = key,
                    Plugins     = Plugins,
                    PluginState = PluginStates,
                    Events      = new List <EntityEventManager.EntityEvent>(events),
                    ChatEvents  = new List <ChatManager.ChatEvent>(chatEvents)
                };

                ThreadPool.QueueUserWorkItem(DoUpdate, parameters);
                //				Thread pluginThread = new Thread(DoUpdate);
                //				pluginThread.Start(parameters);
            }

            //Capture profiling info if debugging is on
            if (ExtenderOptions.IsDebugging)
            {
                _averageEvents = (_averageEvents + (events.Count + chatEvents.Count)) / 2;

                TimeSpan updateTime = DateTime.Now - _lastUpdate;
                _averageUpdateTime = (_averageUpdateTime + updateTime.TotalMilliseconds) / 2;

                TimeSpan timeSinceAverageOutput = DateTime.Now - _lastAverageOutput;
                if (timeSinceAverageOutput.TotalSeconds > 30)
                {
                    _lastAverageOutput = DateTime.Now;

                    ApplicationLog.BaseLog.Debug("PluginManager - Update interval = {0}ms", _averageUpdateInterval);
                    ApplicationLog.BaseLog.Debug("PluginManager - Update time = {0}ms", _averageUpdateTime);
                    ApplicationLog.BaseLog.Debug("PluginManager - Events per update = {0}", _averageEvents);
                }
            }

            //Clean up the event managers
            EntityEventManager.Instance.ClearEvents( );
            EntityEventManager.Instance.ResourceLocked = false;
            ChatManager.Instance.ClearEvents( );
        }
        public void Update()
        {
            if (!Initialized)
                return;
            if (!SandboxGameAssemblyWrapper.Instance.IsGameStarted)
                return;

            m_lastUpdateTime = DateTime.Now - m_lastUpdate;
            m_averageUpdateInterval = (m_averageUpdateTime + m_lastUpdateTime.TotalMilliseconds) / 2;
            m_lastUpdate = DateTime.Now;

            EntityEventManager.Instance.ResourceLocked = true;

            List<EntityEventManager.EntityEvent> events = EntityEventManager.Instance.EntityEvents;
            List<ChatManager.ChatEvent> chatEvents = ChatManager.Instance.ChatEvents;

            //Generate the player join/leave events here
            List<ulong> connectedPlayers = PlayerManager.Instance.ConnectedPlayers;
            try
            {
                foreach (ulong steamId in connectedPlayers)
                {
                    if (!m_lastConnectedPlayerList.Contains(steamId))
                    {
                        EntityEventManager.EntityEvent playerEvent = new EntityEventManager.EntityEvent();
                        playerEvent.priority = 1;
                        playerEvent.timestamp = DateTime.Now;
                        playerEvent.type = EntityEventManager.EntityEventType.OnPlayerJoined;
                        //TODO - Find a way to stall the event long enough for a linked character entity to exist - this is impossible because of cockpits and respawnships
                        //For now, create a dummy entity just for passing the player's steam id along
                        playerEvent.entity = (Object)steamId;
                        events.Add(playerEvent);
                    }
                }
                foreach (ulong steamId in m_lastConnectedPlayerList)
                {
                    if (!connectedPlayers.Contains(steamId))
                    {
                        EntityEventManager.EntityEvent playerEvent = new EntityEventManager.EntityEvent();
                        playerEvent.priority = 1;
                        playerEvent.timestamp = DateTime.Now;
                        playerEvent.type = EntityEventManager.EntityEventType.OnPlayerLeft;
                        //TODO - Find a way to stall the event long enough for a linked character entity to exist - this is impossible because of cockpits and respawnships
                        //For now, create a dummy entity just for passing the player's steam id along
                        playerEvent.entity = (Object)steamId;
                        events.Add(playerEvent);
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.APILog.WriteLine("PluginManager.Update() Exception in player discovery: " + ex.ToString());
            }
            m_lastConnectedPlayerList = new List<ulong>(connectedPlayers);

            //Run the update threads on the plugins
            foreach (var key in m_plugins.Keys)
            {
                var plugin = m_plugins[key];

                if (!m_pluginState.ContainsKey(key))
                    continue;

                PluginManagerThreadParams parameters = new PluginManagerThreadParams();
                parameters.plugin = plugin;
                parameters.key = key;
                parameters.events = new List<EntityEventManager.EntityEvent>(events);
                parameters.chatEvents = new List<ChatManager.ChatEvent>(chatEvents);

                Thread pluginThread = new Thread(DoUpdate);
                pluginThread.Start(parameters);
            }

            //Capture profiling info if debugging is on
            if (SandboxGameAssemblyWrapper.IsDebugging)
            {
                m_averageEvents = (m_averageEvents + (events.Count + chatEvents.Count)) / 2;

                TimeSpan updateTime = DateTime.Now - m_lastUpdate;
                m_averageUpdateTime = (m_averageUpdateTime + updateTime.TotalMilliseconds) / 2;

                TimeSpan timeSinceAverageOutput = DateTime.Now - m_lastAverageOutput;
                if (timeSinceAverageOutput.TotalSeconds > 30)
                {
                    m_lastAverageOutput = DateTime.Now;

                    LogManager.APILog.WriteLine("PluginManager - Update interval = " + m_averageUpdateInterval.ToString() + "ms");
                    LogManager.APILog.WriteLine("PluginManager - Update time = " + m_averageUpdateTime.ToString() + "ms");
                    LogManager.APILog.WriteLine("PluginManager - Events per update = " + m_averageEvents.ToString());
                }
            }

            //Clean up the event managers
            EntityEventManager.Instance.ClearEvents();
            EntityEventManager.Instance.ResourceLocked = false;
            ChatManager.Instance.ClearEvents();
        }