Example #1
0
        private async Task RestartServer()
        {
            // get new overlay data
            await OverlaysCustom.FetchOverlayData();

            if (serverRestarting)
            {
                Logger.LogRow(Logger.LogType.Error, "Already restarting server. Cancelling this restart.");
                return;
            }

            // stop the server
            serverRestarting = true;
            // TODO this is race condition because it is started from somewhere else
            if (server != null)
            {
                await server.StopAsync();
            }

            // restart the server
            server = WebHost
                     .CreateDefaultBuilder()
                     .UseKestrel(x =>
            {
                x.ListenAnyIP(6724);
            })
                     .UseStartup <Routes>()
                     .Build();

            await server.RunAsync();

            serverRestarting = false;
        }
Example #2
0
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }

                app.UseDefaultFiles();
                //app.UseStaticFiles();
                app.UseRouting();

                app.UseEndpoints(endpoints =>
                {
                    SparkAPI.MapRoutes(endpoints);

                    // OverlaysVRML.MapRoutes(endpoints);
                    OverlaysCustom.MapRoutes(endpoints);


                    endpoints.MapGet("/spark_info", async context =>
                    {
                        context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
                        context.Response.Headers.Add("Access-Control-Allow-Headers",
                                                     "Content-Type, Accept, X-Requested-With");

                        await context.Response.WriteAsJsonAsync(
                            new Dictionary <string, object>
                        {
                            { "version", Program.AppVersionString() },
                            { "windows_store", Program.IsWindowsStore() },
                            { "ess_version", Program.InstalledSpeakerSystemVersion },
                        });
                    });


                    endpoints.MapGet("/session", async context =>
                    {
                        context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
                        context.Response.Headers.Add("Access-Control-Allow-Headers",
                                                     "Content-Type, Accept, X-Requested-With");
                        context.Response.Headers.Add("Content-Type", "application/json");

                        if (Program.InGame)
                        {
                            await context.Response.WriteAsync(Program.lastJSON);
                        }
                        else
                        {
                            context.Response.StatusCode = 404;
                            await context.Response.WriteAsync("");
                        }
                    });


                    endpoints.MapGet("/stats", async context =>
                    {
                        context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
                        context.Response.Headers.Add("Access-Control-Allow-Headers",
                                                     "Content-Type, Accept, X-Requested-With");

                        Dictionary <string, object> response = GetStatsResponse();
                        await context.Response.WriteAsJsonAsync(response);
                    });


                    // TODO in progress. This will have settings for the overlay replacement
                    endpoints.MapGet("/overlay_info", async context =>
                    {
                        try
                        {
                            context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
                            context.Response.Headers.Add("Access-Control-Allow-Headers",
                                                         "Content-Type, Accept, X-Requested-With");

                            Dictionary <string, object> response = new Dictionary <string, object>();

                            response["stats"]      = GetStatsResponse();
                            response["visibility"] = new Dictionary <string, object>()
                            {
                                { "minimap", true },
                                { "main_banner", true },
                                { "neutral_jousts", true },
                                { "defensive_jousts", true },
                                { "event_log", true },
                                { "playspace", true },
                                { "player_speed", true },
                                { "disc_speed", true },
                            };
                            response["caster_prefs"] = SparkSettings.instance.casterPrefs;

                            if (Program.InGame)
                            {
                                response["session"] = Program.lastJSON;
                            }

                            await context.Response.WriteAsJsonAsync(response);
                        }
                        catch (Exception e)
                        {
                            Logger.LogRow(Logger.LogType.Error, e.ToString());
                        }
                    });

                    endpoints.MapGet("/midmatch_overlay", async context =>
                    {
                        string file = ReadResource("midmatch_overlay.html");
                        await context.Response.WriteAsync(file);
                    });


                    endpoints.MapGet("/scoreboard", async context =>
                    {
                        string file = ReadResource("default_scoreboard.html");

                        string[] columns =
                        {
                            "player_name",
                            "points",
                            "assists",
                            "saves",
                            "stuns",
                        };

                        List <List <Dictionary <string, object> > > matchStats = GetMatchStats();


                        string overlayOrangeTeamName = "";
                        string overlayBlueTeamName   = "";
                        switch (SparkSettings.instance.overlaysTeamSource)
                        {
                        case 0:
                            overlayOrangeTeamName = SparkSettings.instance.overlaysManualTeamNameOrange;
                            overlayBlueTeamName   = SparkSettings.instance.overlaysManualTeamNameBlue;
                            break;

                        case 1:
                            overlayOrangeTeamName = Program.CurrentRound.teams[Team.TeamColor.orange].vrmlTeamName;
                            overlayBlueTeamName   = Program.CurrentRound.teams[Team.TeamColor.blue].vrmlTeamName;
                            break;
                        }

                        if (string.IsNullOrWhiteSpace(overlayOrangeTeamName))
                        {
                            overlayOrangeTeamName = "ORANGE TEAM";
                        }

                        if (string.IsNullOrWhiteSpace(overlayBlueTeamName))
                        {
                            overlayBlueTeamName = "BLUE TEAM";
                        }

                        string[] teamHTMLs = new string[2];
                        for (int i = 0; i < 2; i++)
                        {
                            StringBuilder html = new StringBuilder();
                            html.Append("<thead>");
                            foreach (string column in columns)
                            {
                                html.Append("<th>");
                                if (column == "player_name")
                                {
                                    html.Append(i == 0 ? overlayBlueTeamName : overlayOrangeTeamName);
                                }
                                else
                                {
                                    html.Append(column);
                                }

                                html.Append("</th>");
                            }

                            html.Append("</thead>");

                            html.Append("<body>");


                            if (matchStats[i].Count >= 8)
                            {
                                Logger.LogRow(Logger.LogType.Error, "8 or more players on a team. Must have failed to split.");
                            }

                            // cap out at 8 players. Anything more breaks the layout
                            for (int playerIndex = 0; playerIndex < matchStats[i].Count && playerIndex < 8; playerIndex++)
                            {
                                Dictionary <string, object> player = matchStats[i][playerIndex];
                                html.Append("<tr>");
                                foreach (string column in columns)
                                {
                                    html.Append("<td>");
                                    html.Append(player[column]);
                                    html.Append("</td>");
                                }

                                html.Append("</tr>");
                            }

                            html.Append("<body>");
                            teamHTMLs[i] = html.ToString();
                        }

                        file = file.Replace("{{ BLUE_TEAM }}", teamHTMLs[0]);
                        file = file.Replace("{{ ORANGE_TEAM }}", teamHTMLs[1]);

                        await context.Response.WriteAsync(file);
                    });


                    endpoints.MapGet("/disc_positions",
                                     async context =>
                    {
                        context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
                        context.Response.Headers.Add("Access-Control-Allow-Headers",
                                                     "Content-Type, Accept, X-Requested-With");
                        List <Dictionary <string, float> > positions = await GetDiscPositions();
                        await context.Response.WriteAsJsonAsync(positions);
                    });

                    endpoints.MapGet("/disc_position_heatmap",
                                     async context =>
                    {
                        string file = ReadResource("disc_position_heatmap.html");
                        await context.Response.WriteAsync(file);
                    });


                    endpoints.MapGet("/get_player_speed", async context =>
                    {
                        context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
                        context.Response.Headers.Add("Access-Control-Allow-Headers",
                                                     "Content-Type, Accept, X-Requested-With");

                        await context.Response.WriteAsJsonAsync(
                            new Dictionary <string, object>
                        {
                            {
                                "speed",
                                Program.lastFrame?.GetPlayer(Program.lastFrame.client_name)?.velocity.ToVector3()
                                .Length() ?? -1
                            },
                        });
                    });
                    endpoints.MapGet("/get_disc_speed", async context =>
                    {
                        context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
                        context.Response.Headers.Add("Access-Control-Allow-Headers",
                                                     "Content-Type, Accept, X-Requested-With");

                        await context.Response.WriteAsJsonAsync(
                            new Dictionary <string, object>
                        {
                            {
                                "speed", Program.lastFrame?.disc.velocity.ToVector3().Length() ?? -1
                            },
                        });
                    });

                    endpoints.MapGet("/speedometer/player",
                                     async context =>
                    {
                        string file = ReadResource("speedometer.html");
                        file        = file.Replace("FETCH_URL", "/get_player_speed");
                        await context.Response.WriteAsync(file);
                    });

                    endpoints.MapGet("/speedometer/lone_echo_1",
                                     async context =>
                    {
                        string file = ReadResource("speedometer.html");
                        file        = file.Replace("FETCH_URL", "http://127.0.0.1:6723/le1/speed/");
                        await context.Response.WriteAsync(file);
                    });

                    endpoints.MapGet("/speedometer/lone_echo_2",
                                     async context =>
                    {
                        string file = ReadResource("speedometer.html");
                        file        = file.Replace("FETCH_URL", "http://127.0.0.1:6723/le2/speed/");
                        await context.Response.WriteAsync(file);
                    });

                    endpoints.MapGet("/speedometer/disc",
                                     async context =>
                    {
                        string file = ReadResource("speedometer.html");
                        file        = file.Replace("FETCH_URL", "/get_disc_speed");
                        await context.Response.WriteAsync(file);
                    });

                    endpoints.MapGet("/minimap",
                                     async context =>
                    {
                        string file = ReadResource("default_minimap.html");
                        await context.Response.WriteAsync(file);
                    });


                    endpoints.MapGet("/full_overlay",
                                     async context =>
                    {
                        string file = ReadResource("full_overlay.html");
                        await context.Response.WriteAsync(file);
                    });


                    // add all the stuff in wwwroot

                    // Determine path
                    Assembly assembly = Assembly.GetExecutingAssembly();
                    string sparkPath  = Path.GetDirectoryName(assembly.Location);
                    if (sparkPath != null)
                    {
                        // Format: "{Namespace}.{Folder}.{filename}.{Extension}"
                        foreach (string str in assembly.GetManifestResourceNames())
                        {
                            string[] pieces = str.Split('.');
                            if (pieces.Length > 2 && pieces?[1] == "wwwroot_resources")
                            {
                                List <string> folderPieces = pieces.Skip(2).SkipLast(2).Append(string.Join('.', pieces.TakeLast(2))).ToList();
                                string url;

                                if (folderPieces.Count > 1 && folderPieces[^ 1].Contains("min."))
                                {
                                    // combine the min into the filename
                                    folderPieces[^ 2] = string.Join('.', folderPieces.TakeLast(2));