public async Task Startup()
        {
            Logger.LogInfo("Core", "Starting up");
            worldStateService.GenerateStartingWorld();
            Logger.LogInfo("Core", "World Generated");

            var ip = Environment.GetEnvironmentVariable("RunnerIp");

            ip = string.IsNullOrWhiteSpace(ip)
                ? engineConfig.RunnerUrl
                : ip.StartsWith("http://")
                    ? ip
                    : "http://" + ip;

            runnerUrl = ip + ":" + engineConfig.RunnerPort;

            var canSeeRunner = false;

            using (var httpClient = new HttpClient())
            {
                while (!canSeeRunner)
                {
                    Logger.LogDebug("Core.Startup", "Testing network visibility of Runner");
                    Logger.LogDebug("Core.Startup", $"Testing URL: {runnerUrl}");
                    try
                    {
                        var result = await httpClient.GetAsync($"{runnerUrl}/api/health/runner");

                        if (result.StatusCode != HttpStatusCode.OK)
                        {
                            Logger.LogDebug(
                                "Core.Startup",
                                $"Can not see runner at {runnerUrl}/api/health/runner. Waiting 1 second and trying again.");
                            Thread.Sleep(1000);
                            continue;
                        }
                    }
                    catch (Exception)
                    {
                        Logger.LogDebug(
                            "Core.Startup",
                            $"Can not see runner at {runnerUrl}/api/health/runner. Waiting 1 second and trying again.");
                        Thread.Sleep(1000);
                        continue;
                    }
                    Logger.LogDebug("Core.Startup", $"Can see runner at {runnerUrl}");
                    canSeeRunner = true;
                }
            }

            Logger.LogDebug("SignalR.Startup", $"Connecting SignalR to {runnerUrl}");
            connection = new HubConnectionBuilder().WithUrl($"{runnerUrl}/runnerhub")
                         .AddJsonProtocol(options => { options.PayloadSerializerOptions.Converters.Add(new JsonStringEnumConverter()); })
                         .ConfigureLogging(logging =>
            {
                logging.SetMinimumLevel(LogLevel.Information);
            })
                         .Build();
            try
            {
                await connection.StartAsync()
                .ContinueWith(
                    async task =>
                {
                    Logger.LogDebug("SignalR.Startup", "SignalR Started");
                    Logger.LogDebug("SignalR.Startup", $"Connection State: {connection.State}");

                    await connection.InvokeAsync("RegisterGameEngine");

                    /* Disconnect Request Handler */
                    connection.On <Guid>("Disconnect", OnDisconnect);

                    /* New Bot Command Handler*/
                    connection.On <Guid, PlayerAction>("BotCommandReceived", OnBotCommandReceived);

                    connection.On <Guid>("BotRegistered", OnRegisterBot);

                    connection.On("StartGame", OnStartGame);
                    connection.On <int>("TickAck", OnTickAck);

                    try
                    {
                        engineService.SetHubConnection(ref connection);
                        await engineService.GameRunLoop();
                    }
                    catch (Exception e)
                    {
                        Logger.LogError("Core", $"Failed to run GameRunLoop with error: {e.Message}");
                        await ShutdownWithError(e);
                    }
                });
            }
            catch (Exception e)
            {
                Logger.LogError("Core", $"Failed to run SignalR with error: {e.Message}");
                await ShutdownWithError(e);
            }
        }