using asap.core; using cfg; using game; using GameCore; using System; using System.Collections.Generic; using System.Threading.Tasks; using UnityEngine; public class BanServerConfig { public bool AntiCheatOn { get; set; } public Dictionary> AntiCheatParam { get; set; } public List GetParam(int key) { if (AntiCheatParam != null && AntiCheatParam.ContainsKey(key)) { return AntiCheatParam[key]; } return null; } } public class AntiCheatRequest { public string playerID { get; set; } public int banType { get; set; } public string deviceId { get; set; } public bool gm { get; set; } } public class AntiCheatResponse { public string playerID { get; set; } public int banTypeCode { get; set; } // 封禁类型编码(如101) public bool isBanned { get; set; } } public class AntiCheatManager { [Inject] public IUserService userService { get; set; } [Inject] public ICustomServerMgr customServerMgr { get; set; } bool IsAnti = false; string DeviceId { get { #if UNITY_IOS return UnityEngine.iOS.Device.advertisingIdentifier; #elif UNITY_ANDROID return SystemInfo.deviceUniqueIdentifier; #endif } } #region 行为检测核心方法 // 检测登录/钓鱼行为(101)检查是否已经被封 // 获取服务器表配置 public async Task CheckLoginPhishingBehavior() { if (tbServerConfig == null) { try { var json = await customServerMgr.GetStringAsync("anti-cheat/GetConfigRequest"); if (!string.IsNullOrEmpty(json) && json != "[]") { tbServerConfig = Newtonsoft.Json.JsonConvert.DeserializeObject(json); } } catch { Debug.LogWarning("[AntiCheat] Failed to fetch server config."); } } if (IsAnti) { return; } if (tbServerConfig == null) { return; } bool AntiCheatOn = tbServerConfig.AntiCheatOn; if (!AntiCheatOn) { return; } int buildCount = GetDailyBuildCount(); int vip = GContext.container.Resolve().vip; int maxLevel = GContext.container.Resolve().TbMapData.DataList[^1].LevelRequired; int level = GContext.container.Resolve().lv; if (level > maxLevel) { //建造等级超出已解锁地图的最大建造等级-303 TriggerBanEvent(303); } else { //0付费,vip等级>=5 -101 float payAmount = GContext.container.Resolve().GetBuyData(); var Param = tbServerConfig.GetParam(101); if (Param != null && Param.Count == 2 && payAmount <= Param[0] && vip >= Param[1]) { TriggerBanEvent(101); } } } // 检测道具获取行为(201/202/203) public void CheckItemChangeBehavior(int id, int count) { if (tbServerConfig == null) { return; } bool AntiCheatOn = tbServerConfig.AntiCheatOn; if (!AntiCheatOn) { return; } float payAmount = GContext.container.Resolve().GetBuyData(); int createRoleDays = (int)((DateTime.UtcNow.Ticks - userService.CreateTime.Ticks) / TimeSpan.TicksPerDay); //玩家行为 item_change if (id == 1001) { //付费为0,距离创角小于等于7天,单次获取5000及以上鱼钩-201 var Param = tbServerConfig.GetParam(201); if (Param != null && Param.Count == 3 && payAmount <= Param[0] && createRoleDays <= Param[1] && count >= Param[2]) { TriggerBanEvent(201); return; } //付费为0,单次获取15000及以上鱼钩-202 Param = tbServerConfig.GetParam(202); if (Param != null && Param.Count == 2 && payAmount <= Param[0] && count >= Param[1]) { TriggerBanEvent(202); } } else if (id == 1005) { //付费为0,单次获取5000及以上钻石 - 203 var Param = tbServerConfig.GetParam(203); if (Param != null && Param.Count == 2 && payAmount <= Param[0] && count >= Param[1]) { TriggerBanEvent(203); } } } // 检测建造行为(301/302/303/304) public void CheckBuildBehavior(int addLevel) { if (tbServerConfig == null) { return; } bool AntiCheatOn = tbServerConfig.AntiCheatOn; if (!AntiCheatOn) { return; } float payAmount = GContext.container.Resolve().GetBuyData(); int createRoleDays = (int)((DateTime.UtcNow.Ticks - userService.CreateTime.Ticks) / TimeSpan.TicksPerDay); int buildCount = GetDailyBuildCount(); int level = GContext.container.Resolve().lv; //付费为0,距离创角<10天,建造等级达到10000及以上-302 var Param = tbServerConfig.GetParam(302); if (Param != null && Param.Count == 3 && payAmount <= Param[0] && createRoleDays <= Param[1] && level >= Param[2]) { TriggerBanEvent(302); return; } //付费为0,单日build_upgrade1000次及以上-301 Param = tbServerConfig.GetParam(301); if (Param != null && Param.Count == 2 && payAmount <= Param[0] && level - buildCount >= Param[1]) { TriggerBanEvent(301); return; } //前后两次建造building times差值大于1(第二次减第一次大于1)-304 Param = tbServerConfig.GetParam(304); if (Param != null && Param.Count == 1 && addLevel > Param[0]) { TriggerBanEvent(304); return; } } int GetDailyBuildCount() { string key = $"BuildCount_{userService.UserId}"; string dayBuildData = PlayerPrefs.GetString(key, ""); var currentDays = (DateTime.UtcNow.Date - new DateTime(2026, 1, 1)).TotalDays; if (!string.IsNullOrEmpty(dayBuildData)) { var parts = dayBuildData.Split('_'); if (parts.Length == 2) { double savedDays; if (double.TryParse(parts[0], out savedDays)) { int savedLevel; if (int.TryParse(parts[1], out savedLevel)) { if (savedDays == currentDays) { //同一天,返回保存的建造次数 return savedLevel; } } } } } int level = GContext.container.Resolve().lv; PlayerPrefs.SetString(key, $"{currentDays}_{level}"); //获取单日建造次数逻辑 return level; } BanServerConfig tbServerConfig = null; void TriggerBanEvent(int banType) { if (IsAnti || banType == 0) { return; } OnBan("anti-cheat/SendClientBan", banType); } public void CheckBan() { if (IsAnti) { return; } OnBan("anti-cheat/CheckBan", 0); } async void OnBan(string url, int banType) { IConfig config = GContext.container.Resolve(); AntiCheatRequest evt = new AntiCheatRequest { playerID = userService.UserId, banType = banType, deviceId = DeviceId, gm = config != null && (config.Get("DEBUG", "0") == "1" || config.Get("GM", "0") == "1") }; string json = await customServerMgr.CustomServerPost(url, Newtonsoft.Json.JsonConvert.SerializeObject(evt)); if (IsAnti) { return; } if (!string.IsNullOrEmpty(json) && json != "[]") { AntiCheatResponse response = Newtonsoft.Json.JsonConvert.DeserializeObject(json); Debug.Log($"[AntiCheat] PlayerID: {response.playerID} DeviceId: {DeviceId} banned for reason: {response.banTypeCode}"); #if !UNITY_EDITOR if (response.banTypeCode > 0) { #if AGG using (var e = GEvent.GameEvent("Anti_cheating")) { e.AddContent("type", response.banTypeCode) .AddContent("deviceId", DeviceId) .AddContent("is_first_ban", !response.isBanned); } #endif IsAnti = true; await UIManager.Instance.ShowUI(UITypes.AccountAbnormalityPopupPanel); } #endif } } #endregion }