////////////////

        private void InitializeLoopingServerAnnounce()
        {
            if (Main.netMode == 0)
            {
                return;
            }

            Action alert_privacy = delegate {
                string msg = "Mod Helpers would like to list your servers in the Server Browser mod. Type '/hhprivateserver' in the chat or server console to cancel this. Otherwise, do nothing for 60 seconds.";

                Main.NewText(msg, Color.Yellow);
                Console.WriteLine(msg);
            };

            if (Main.netMode == 1)
            {
                if (ServerBrowserReporter.CanPromptForBrowserAdd())
                {
                    //	3 seconds
                    Timers.SetTimer("server_browser_intro", 60 * 3, delegate {
                        alert_privacy();
                        return(false);
                    });
                }
            }

            if (ServerBrowserReporter.CanAnnounceServer())
            {
                if (ServerBrowserReporter.CanPromptForBrowserAdd())
                {
                    Timers.SetTimer("server_browser_report", 60 * 60, delegate {                        // 1 minute, no repeat
                        if (ServerBrowserReporter.CanPromptForBrowserAdd())
                        {
                            ServerBrowserReporter.EndPrompts();
                        }

                        try {
                            this.BeginLoopingServerAnnounce();
                        } catch { }

                        return(false);
                    });
                }
                else
                {
                    this.BeginLoopingServerAnnounce();
                }
            }
        }
        private static void HandleServerAnnounceOutputAsync(ServerBrowserEntry server_data, string output)
        {
            try {
                var reply = JsonConvert.DeserializeObject <ServerBrowserWorkAssignment>(output);

                if (reply.ProofOfWorkNeeded)
                {
                    ServerBrowserReporter.DoWorkToValidateServer(server_data, reply.Hash);

                    LogHelpers.Log("Server data added to browser? " + reply.Success + " - Beginning validation...");
                }
                else
                {
                    LogHelpers.Log("Server updated on browser? " + reply.Success);
                }
            } catch (Exception e) {
                if (!(e is JsonReaderException))
                {
                    LogHelpers.Log("HandleServerAnnounceOutput - " + e.ToString() + " - " + (output.Length > 256 ? output.Substring(0, 256) : output));
                }
            }
        }
        private void BeginLoopingServerAnnounce()
        {
            if (Main.netMode != 2)
            {
                return;
            }

            // First time no timer
            if (ServerBrowserReporter.CanAnnounceServer())
            {
                ServerBrowserReporter.AnnounceServer();
            }

            Timers.SetTimer("server_browser_report", (60 * 10) * 60, delegate {               // 10 minutes
                if (ServerBrowserReporter.CanAnnounceServer())
                {
                    if (!ServerBrowserReporter.IsHammering())
                    {
                        ServerBrowserReporter.AnnounceServer();
                    }
                }
                return(true);
            });
        }
        ////////////////

        public static void AnnounceServer()
        {
            HamstarHelpersMod mymod = HamstarHelpersMod.Instance;
            Version           vers  = mymod.Version;

            int port = Netplay.ListenPort;

            if (mymod.Config.ServerBrowserCustomPort != -1)
            {
                port = mymod.Config.ServerBrowserCustomPort;
            }

            int pvp = 0;

            bool[] team_checks = new bool[10];
            ServerBrowserReporter server_browser = mymod.ServerBrowser;

            for (int i = 0; i < Main.player.Length; i++)
            {
                Player player = Main.player[i];
                if (player == null || !player.active)
                {
                    continue;
                }

                if (player.hostile)
                {
                    pvp++;
                }
                team_checks[player.team] = true;
            }

            int team_count = 0;

            for (int i = 1; i < team_checks.Length; i++)
            {
                if (team_checks[i])
                {
                    team_count++;
                }
            }

            try {
                var server_data = new ServerBrowserEntry();
                server_data.ServerIP       = NetHelpers.NetHelpers.GetPublicIP();
                server_data.Port           = port;
                server_data.IsPassworded   = Netplay.ServerPassword != "";
                server_data.Motd           = Main.motd;
                server_data.WorldName      = Main.worldName;
                server_data.WorldProgress  = InfoHelpers.GetVanillaProgress();
                server_data.WorldEvent     = string.Join(", ", InfoHelpers.GetCurrentVanillaEvents().ToArray());
                server_data.MaxPlayerCount = Main.maxNetPlayers;
                server_data.PlayerCount    = Main.ActivePlayersCount;
                server_data.PlayerPvpCount = pvp;
                server_data.TeamsCount     = team_count;
                server_data.AveragePing    = mymod.ServerBrowser.AveragePing;
                server_data.Mods           = new Dictionary <string, string>();
                server_data.Version        = (vers.Major * 1000000) + (vers.Minor * 10000) + (vers.Build * 100) + vers.Revision;

                foreach (Mod mod in ModLoader.LoadedMods)
                {
                    if (mod.File == null)
                    {
                        continue;
                    }
                    server_data.Mods[mod.DisplayName] = mod.Version.ToString();
                }

                string json_str   = JsonConvert.SerializeObject(server_data, Formatting.None);
                byte[] json_bytes = Encoding.UTF8.GetBytes(json_str);

                Action <string> on_response = delegate(string output) {
                    ServerBrowserReporter.HandleServerAnnounceOutputAsync(server_data, output);
                };
                Action <Exception, string> on_error = delegate(Exception e, string output) {
                    LogHelpers.Log("Server browser returned error: " + e.ToString());
                };

                NetHelpers.NetHelpers.MakePostRequestAsync(ServerBrowserReporter.URL, json_bytes, on_response, on_error);

                ServerBrowserReporter.LastSendTimestamp = SystemHelpers.TimeStampInSeconds();
            } catch (Exception e) {
                LogHelpers.Log("AnnounceServer - " + e.ToString());
                return;
            }
        }