/// <summary>
        ///     Runs the game mode of this runner.
        /// </summary>
        /// <returns>true if shut down by the game mode, false otherwise.</returns>
        /// <exception cref="Exception">Thrown if a game mode is already running.</exception>
        public bool Run()
        {
            InternalStorage.RunningClient = this;

            // Prepare the syncronization context
            _messageQueue           = new NoWaitMessageQueue();
            _synchronizationContext = new SampSharpSynchronizationContext(_messageQueue);

            SynchronizationContext.SetSynchronizationContext(_synchronizationContext);

            _mainThread = Thread.CurrentThread.ManagedThreadId;
            _running    = true;

            CoreLog.Log(CoreLogLevel.Initialisation, "SampSharp GameMode Client");
            CoreLog.Log(CoreLogLevel.Initialisation, "-------------------------");
            CoreLog.Log(CoreLogLevel.Initialisation, $"v{CoreVersion.Version.ToString(3)}, (C)2014-2020 Tim Potze");
            CoreLog.Log(CoreLogLevel.Initialisation, "Hosted run mode is active.");
            CoreLog.Log(CoreLogLevel.Initialisation, "");

            // TODO: Verify plugin version

            _gameModeProvider.Initialize(this);

            return(true);
        }
        /// <inheritdoc />
        public bool Run()
        {
            if (InternalStorage.RunningClient != null)
            {
                throw new Exception("A game mode is already running!");
            }

            InternalStorage.RunningClient = this;

            // Prepare the synchronization context
            var queue = new SemaphoreMessageQueue();

            _synchronizationContext = new SampSharpSynchronizationContext(queue);
            _messagePump            = new MessagePump(queue);

            SynchronizationContext.SetSynchronizationContext(_synchronizationContext);

            // Initialize the game mode and start the main routine
            Initialize();

            // Pump new tasks
            _messagePump.Pump(e => OnUnhandledException(new UnhandledExceptionEventArgs("async", e)));

            // Clean up
            InternalStorage.RunningClient = null;
            CommunicationClient.Disconnect();

            return(_shuttingDown);
        }