public void LogMetrics() { if (_currentTableFileName == "") { return; } while (!created) { Thread.Sleep(2); } var nowSinceEpoch = _nowSinceEpoch; var timeString = "" + (long)nowSinceEpoch.TotalMilliseconds; var playerIds = _playerData.GetKeys(); var nowTurn = Time.CurrentTurn; var nowEvents = _eventMap.GetEventsForTurn(nowTurn); Polygon[] nowPolygons = new Polygon[playerIds.Count]; foreach (TimedEvent nowEvent in nowEvents) { TimedArea nowArea = null; if (nowEvent.EventType == EventType.Area) { nowArea = nowEvent as TimedArea; } else if (nowEvent.EventType == EventType.Transition) { Transition nowTransition = (Transition)nowEvent; TransitionFrame nowFrame = nowTransition.Frames.Find(frame => frame.Area != null && frame.Area.IsActiveAt(nowTurn)); if (nowFrame == null) { continue; } nowArea = nowFrame.Area; } if (nowArea == null) { continue; } var playerIndex = playerIds.IndexOf(nowEvent.PlayerId); if (playerIndex < 0) { continue; } nowPolygons[playerIndex] = nowArea.Area; } for (int playerIndex = 0; playerIndex < playerIds.Count; playerIndex++) { if (nowPolygons[playerIndex] == null) { nowPolygons[playerIndex] = new Polygon(); } } Vector[] nowPositions = new Vector[playerIds.Count]; // append empty when player is not logged in for (int playerNum = 0; playerNum < playerIds.Count; playerNum++) { var playerId = playerIds[playerNum]; if (_playerData.TryGetEntry(playerId, out PlayerDataEntry player)) { var position = player.Position; nowPositions[playerNum] = position; } } UpdateBreaches(playerIds, nowPositions, nowPolygons, out float[] minimalDistanceToOther, out bool[] isBreaching, out double[] minDistPerUser, out double[] maxDistPerUser); // appending to file PrepareAppend(); for (int userNum = 0; userNum < playerIds.Count; userNum++) { AppendSingle(timeString); var playerId = playerIds[userNum]; AppendSingle($"{playerId}"); var position = nowPositions[userNum]; if (position == null) { AppendSingle(); AppendSingle(); } else { AppendSingle(position.X.ToString("0.000")); AppendSingle(position.Z.ToString("0.000")); } var playerPolygon = nowPolygons[userNum]; var playerPoints = playerPolygon.Points; for (int nodeNum = 0; nodeNum < MaxPolyPoints; nodeNum++) { if (nodeNum < playerPoints.Count && playerPoints[nodeNum] != null) { var nodePosition = playerPoints[nodeNum]; AppendSingle(nodePosition.X.ToString("0.000")); AppendSingle(nodePosition.Z.ToString("0.000")); } else { AppendSingle(); AppendSingle(); } } AppendSingle(isBreaching[userNum] ? "1" : "0"); AppendSingle(minimalDistanceToOther[userNum] > 10 ? "" : minimalDistanceToOther[userNum].ToString("0.000")); AppendSingle(minDistPerUser[userNum] > 10 ? "" : minDistPerUser[userNum].ToString("0.000")); AppendSingle(maxDistPerUser[userNum] > 10 ? "" : maxDistPerUser[userNum].ToString("0.000"), userNum == MaxPlayers - 1 ? false : true); AppendSingle(seperator: false, newLine: true); } FinalizeAppend(); }