PRoConEvents.MULTIbalancer.OnServerInfo C# (CSharp) Method

OnServerInfo() public method

public OnServerInfo ( PRoCon.Core.CServerInfo serverInfo ) : void
serverInfo PRoCon.Core.CServerInfo
return void
        public override void OnServerInfo(CServerInfo serverInfo)
        {
            if (!fIsEnabled || serverInfo == null) return;

            DebugWrite("^9^bGot OnServerInfo^n: Debug level = " + DebugLevel, 8);

            DateTime debugTime = DateTime.Now;

            try {
            double elapsedTimeInSeconds = DateTime.Now.Subtract(fLastServerInfoTimestamp).TotalSeconds;
            fLastServerInfoTimestamp = DateTime.Now;
            if (fUpdateTicketsRequest != null) fUpdateTicketsRequest.LastUpdate = fLastServerInfoTimestamp;

            // Update game state if just enabled (as of R38, CTF TeamScores may be null, does not mean round end)
            if (fGameState == GameState.Unknown && serverInfo.GameMode != "CaptureTheFlag0") {
            if (serverInfo.TeamScores == null || serverInfo.TeamScores.Count < 2) {
                if (fGameVersion == GameVersion.BFH && Regex.Match(serverInfo.GameMode, @"(Heist|Hotwire|Bloodmoney)", RegexOptions.IgnoreCase).Success) {
                    // Special handling for BFH until bugs with TeamScores are fixed for these modes
                    DebugWrite("OnServerInfo: Ignoring null TeamScores for BFH mode: " + serverInfo.GameMode, 8);
                } else {
                    fGameState = GameState.RoundEnding;
                    DebugWrite("OnServerInfo: ^b^3Game state = " + fGameState, 6);
                }
            }
            }

            // Show final status
            if (fFinalStatus != null) {
            try {
                DebugWrite("^bFINAL STATUS FOR PREVIOUS ROUND:^n", 2);
                foreach (TeamScore ts in fFinalStatus) {
                    if (ts.TeamID >= fTickets.Length) break;
                    fTickets[ts.TeamID] = (ts.Score == 1) ? 0 : ts.Score; // fix rounding
                }
                LogStatus(true, DebugLevel);
                DebugWrite("+------------------------------------------------+", 2);
                if (DebugLevel >= 3) CommandToLog("bad tags");
            } catch (Exception) {}
            fFinalStatus = null;
            }

            if (fServerInfo == null || fServerInfo.GameMode != serverInfo.GameMode || fServerInfo.Map != serverInfo.Map) {
            ConsoleDebug("ServerInfo update: " + serverInfo.Map + "/" + serverInfo.GameMode);
            }

            // Check for server crash
            if (fServerUptime > 0 && fServerUptime > serverInfo.ServerUptime + 2) { // +2 secs for rounding error in server!
            fServerCrashed = true;
            DebugWrite("^1^bDETECTED GAME SERVER CRASH^n (recorded uptime longer than latest serverInfo uptime)", 3);
            }
            fServerInfo = serverInfo;
            fServerUptime = serverInfo.ServerUptime;

            // Update max tickets
            int totalPlayers = TotalPlayerCount();
            PerModeSettings perMode = GetPerModeSettings();
            bool isRush = IsRush();
            double minTickets = Double.MaxValue;
            double maxTickets = 0;
            double attacker = 0;
            double defender = 0;
            double[] oldTickets = new double[]{0, fTickets[1], fTickets[2]};
            if (fServerInfo.TeamScores == null || fServerInfo.TeamScores.Count < 2)  return;
            foreach (TeamScore ts in fServerInfo.TeamScores) {
            if (ts.TeamID >= fTickets.Length) break;
            fTickets[ts.TeamID] = ts.Score;
            if (ts.Score > maxTickets) maxTickets = ts.Score;
            if (ts.Score < minTickets) minTickets = ts.Score;
            }

            if (isRush) {
            foreach (TeamScore ts in fServerInfo.TeamScores) {
                if (ts.TeamID == 1) {
                    attacker = ts.Score;
                } else if (ts.TeamID == 2) {
                    defender = ts.Score;
                }
            }
            //attacker = fServerInfo.TeamScores[0].Score;
            //defender = fServerInfo.TeamScores[1].Score;
            if (fStageInProgress) {
                if (attacker < fRushPrevAttackerTickets && attacker > 0) {
                    fRushAttackerStageLoss = fRushAttackerStageLoss + (fRushPrevAttackerTickets - attacker);
                    ++fRushAttackerStageSamples;
                }
            }
            String avl = String.Empty;
            if (fStageInProgress) avl = ", avg loss = " + RushAttackerAvgLoss().ToString("F1") + "/" + Math.Min(perMode.SecondsToCheckForNewStage, elapsedTimeInSeconds).ToString("F0") + " secs";
            if (totalPlayers > 3) DebugWrite("^7serverInfo: Rush attacker = " + attacker + ", was = " + fMaxTickets + avl + ", defender = " + defender, 7);
            }

            if (fMaxTickets == -1) {
            if (!isRush) {
                fMaxTickets = maxTickets;
                ConsoleDebug("ServerInfo update: fMaxTickets = " + fMaxTickets.ToString("F0"));
            } else {
                fRushMaxTickets = defender;
                fMaxTickets = attacker;
                fRushStage = 1;
                fRushPrevAttackerTickets = attacker;
                fRushAttackerStageSamples = 0;
                fRushAttackerStageLoss = 0;
                fStageInProgress = false;
                ConsoleDebug("ServerInfo update: fMaxTickets = " + fMaxTickets.ToString("F0") + ", fRushMaxTickets = " + fRushMaxTickets + ", fRushStage = " + fRushStage);
            }
            }

            // Rush heuristic: if attacker tickets are higher than last check, new stage started
            if (isRush && fServerInfo != null && !String.IsNullOrEmpty(fServerInfo.Map)) {
            int maxStages = GetRushMaxStages(fServerInfo.Map);
            if (fRushStage == 0) {
                fRushMaxTickets = defender;
                fMaxTickets = attacker;
                fRushStage = 1;
                fRushPrevAttackerTickets = attacker;
                fRushAttackerStageSamples = 0;
                fRushAttackerStageLoss = 0;
            }
            if (!fStageInProgress) {
                // hysteresis, wait for attacker tickets to go below threshold before stage is in progress for sure
                fStageInProgress = ((attacker + (2 * perMode.SecondsToCheckForNewStage / 5)) < fMaxTickets);
                if (fStageInProgress) {
                    DebugWrite("^7serverInfo: stage " + fRushStage + " in progress!", 7);
                }
            } else if (attacker > fRushPrevAttackerTickets
            && (attacker - fRushPrevAttackerTickets) >= Math.Min(12, 2 * perMode.SecondsToCheckForNewStage / 5)
            && AttackerTicketsWithinRangeOfMax(attacker)
            && fRushStage < 5) {
                fStageInProgress = false;
                fRushMaxTickets = defender;
                fMaxTickets = attacker;
                fRushPrevAttackerTickets = attacker;
                fRushStage = fRushStage + 1;
                fRushAttackerStageSamples = 0;
                fRushAttackerStageLoss = 0;
                DebugWrite(".................................... ^b^1New rush stage detected^0^n ....................................", 3);
                DebugBalance("Rush Stage " + fRushStage + " of " + maxStages);
            }
            // update last known attacker ticket value
            fRushPrevAttackerTickets = attacker;
            }

            // Ticket loss rate updates
            if ((EnableTicketLossRateLogging || perMode.EnableTicketLossRatio) && fGameState == GameState.Playing && totalPlayers >= 4) {
            if (fUpdateTicketsRequest == null) SetupUpdateTicketsRequest();
            AddTicketLossSample(1, oldTickets[1], fTickets[1], elapsedTimeInSeconds);
            AddTicketLossSample(2, oldTickets[2], fTickets[2], elapsedTimeInSeconds);
            } else {
            ResetAverageTicketLoss();
            }

            if (EnableTicketLossRateLogging && IsConquest()) {
            UpdateTicketLossRateLog(DateTime.Now, 0, 0);
            }

            if ((EnableTicketLossRateLogging || perMode.EnableTicketLossRatio) && fGameState == GameState.Playing && totalPlayers >= 4) {
            try {
                double a1 = GetAverageTicketLossRate(1, false);
                double a2 = GetAverageTicketLossRate(2, false);
                double ratio = (a1 > a2) ? (a1/Math.Max(1, a2)) : (a2/Math.Max(1, a1));
                ratio = Math.Min(ratio, 50.0); // cap at 50x
                ratio = ratio * 100.0;
                fTicketLossHistogram.Add(Convert.ToInt32(Math.Round(ratio)));
            } catch (Exception e) {
                ConsoleException(e);
            }
            }

            // Check for plugin updates periodically
            if (fLastVersionCheckTimestamp != DateTime.MinValue
            && DateTime.Now.Subtract(fLastVersionCheckTimestamp).TotalMinutes > CHECK_FOR_UPDATES_MINS) {
            LaunchCheckForPluginUpdate();
            }
            } catch (Exception e) {
            ConsoleException(e);
            } finally {
            double elapsedTime = DateTime.Now.Subtract(debugTime).TotalMilliseconds;
            if (DebugLevel >= 8 || (DebugLevel >= 7 && elapsedTime > 100.0)) {
            DebugWrite("^8OnServerInfo took ^b" + elapsedTime.ToString("F0") + "^n ms", 1);
            }
            }
        }
MULTIbalancer