This commit is contained in:
root
2026-04-26 12:44:06 +02:00
commit 9590629795
398 changed files with 26617 additions and 0 deletions

192
AntiCheat.cs Normal file
View File

@@ -0,0 +1,192 @@
namespace GeoSus.Server;
using Microsoft.Extensions.Logging;
// Anti-cheat validace pohybu
public class AntiCheat
{
private readonly ServerConfig _config;
private readonly ILogger _logger;
private const int PositionHistorySize = 20;
public AntiCheat(ServerConfig config, ILogger logger)
{
_config = config;
_logger = logger;
}
// Validuje pohyb hráče a vrací případné cheat violation
public CheatViolation? ValidateMovement(Player player, Position newPosition)
{
var now = DateTime.UtcNow;
var timeSinceLastUpdate = (now - player.LastPositionUpdate).TotalSeconds;
// Příliš krátký interval ignorujeme
if (timeSinceLastUpdate < 0.1)
return null;
var distance = player.Position.DistanceTo(newPosition);
// Teleport detekce
if (distance > _config.TeleportThresholdMeters)
{
var violation = new CheatViolation
{
Type = CheatViolationType.Teleport,
Description = $"Teleport detekován: {distance:F1}m za {timeSinceLastUpdate:F2}s",
Severity = 10
};
ApplyViolation(player, violation);
return violation;
}
// Speed check
var speed = distance / timeSinceLastUpdate;
var maxAllowedSpeed = _config.MaxSpeedMps * 1.5; // 50% tolerance
if (speed > maxAllowedSpeed)
{
var violation = new CheatViolation
{
Type = CheatViolationType.SpeedHack,
Description = $"Podezřelá rychlost: {speed:F1}m/s (max {_config.MaxSpeedMps}m/s)",
Severity = 3
};
ApplyViolation(player, violation);
return violation;
}
// Historie pro detekci pattern
UpdatePositionHistory(player, newPosition, now);
// Validace historie - průměrná rychlost za delší období
var historyViolation = ValidatePositionHistory(player);
if (historyViolation != null)
{
ApplyViolation(player, historyViolation);
return historyViolation;
}
// Pokud je OK, pomalu snižujeme cheat score
if (player.CheatScore > 0 && timeSinceLastUpdate > 1)
{
player.CheatScore = Math.Max(0, player.CheatScore - 1);
UpdateCheatStatus(player);
}
return null;
}
private void ApplyViolation(Player player, CheatViolation violation)
{
player.CheatScore += violation.Severity;
var previousStatus = player.CheatStatus;
UpdateCheatStatus(player);
if (player.CheatStatus != previousStatus)
{
_logger.LogWarning("Cheat status změněn: {Player} -> {Status} (score: {Score})",
player.ClientUuid, player.CheatStatus, player.CheatScore);
}
_logger.LogWarning("Cheat violation: {Player} - {Type}: {Description}",
player.ClientUuid, violation.Type, violation.Description);
}
private void UpdateCheatStatus(Player player)
{
player.CheatStatus = player.CheatScore switch
{
>= 50 => CheatStatus.Kicked,
>= 25 => CheatStatus.Restrict,
>= 10 => CheatStatus.Warn,
_ => CheatStatus.Ok
};
}
private void UpdatePositionHistory(Player player, Position position, DateTime time)
{
player.PositionHistory.Enqueue((position, time));
while (player.PositionHistory.Count > PositionHistorySize)
{
player.PositionHistory.Dequeue();
}
}
private CheatViolation? ValidatePositionHistory(Player player)
{
if (player.PositionHistory.Count < 5)
return null;
var history = player.PositionHistory.ToArray();
var first = history[0];
var last = history[^1];
var totalTime = (last.Time - first.Time).TotalSeconds;
if (totalTime < _config.MovementValidationWindowSec)
return null;
// Spočítáme celkovou ujetou vzdálenost
double totalDistance = 0;
for (int i = 1; i < history.Length; i++)
{
totalDistance += history[i - 1].Pos.DistanceTo(history[i].Pos);
}
var avgSpeed = totalDistance / totalTime;
// Pokud průměrná rychlost za celé období překračuje limit
if (avgSpeed > _config.MaxSpeedMps * 1.2)
{
return new CheatViolation
{
Type = CheatViolationType.SustainedSpeedHack,
Description = $"Dlouhodobě vysoká rychlost: {avgSpeed:F1}m/s za {totalTime:F0}s",
Severity = 5
};
}
return null;
}
// Validace akce - zda hráč může provést danou akci
public bool CanPerformAction(Player player, string actionType)
{
if (player.CheatStatus == CheatStatus.Kicked)
return false;
if (player.CheatStatus == CheatStatus.Restrict)
{
// Omezené akce pro podezřelé hráče
var restrictedActions = new[] { "TaskComplete", "Kill", "EmergencyMeeting" };
if (restrictedActions.Contains(actionType))
{
_logger.LogWarning("Akce {Action} blokována pro hráče {Player} (Restrict status)",
actionType, player.ClientUuid);
return false;
}
}
return true;
}
}
public class CheatViolation
{
public CheatViolationType Type { get; set; }
public required string Description { get; set; }
public int Severity { get; set; }
}
public enum CheatViolationType
{
SpeedHack,
Teleport,
SustainedSpeedHack,
ActionSpam,
InvalidAction
}