using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ComputerysModdingUtilities;
using FishNet;
using FishNet.Connection;
using FishNet.Object;
using HarmonyLib;
using HeathenEngineering.SteamworksIntegration;
using Microsoft.CodeAnalysis;
using Steamworks;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: StraftatMod(true)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("AutoScoreBan")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Automatically bans players with score below a configurable threshold when hosting")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("AutoScoreBan")]
[assembly: AssemblyTitle("AutoScoreBan")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace AutoScoreBan
{
[BepInPlugin("com.balu.straftat.autoscoreban", "AutoScoreBan", "1.0.1")]
public class Plugin : BaseUnityPlugin
{
public const string PLUGIN_GUID = "com.balu.straftat.autoscoreban";
public const string PLUGIN_NAME = "AutoScoreBan";
public const string PLUGIN_VERSION = "1.0.1";
internal static ManualLogSource Log;
private Harmony _harmony;
public static ConfigEntry<bool> ModEnabled;
public static ConfigEntry<int> MinScore;
public static ConfigEntry<bool> IgnoreFriends;
public static ConfigEntry<bool> BanUnranked;
public static ConfigEntry<string> BanReason;
public static ConfigEntry<bool> NotifyInChat;
private void Awake()
{
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Whether auto-banning players by score is enabled.");
MinScore = ((BaseUnityPlugin)this).Config.Bind<int>("Settings", "MinScore", 1000, "Minimum required score. Players with a score below this value will be automatically banned when you host a lobby.");
IgnoreFriends = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "IgnoreFriends", true, "Ignore Steam friends (never ban them regardless of their score).");
BanUnranked = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "BanUnranked", true, "Treat players without a leaderboard entry as having 0 score (and ban them if MinScore > 0).");
BanReason = ((BaseUnityPlugin)this).Config.Bind<string>("Settings", "BanReason", "I'm doing this for your own good", "Kick/ban message displayed to the player upon being banned.");
NotifyInChat = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "NotifyInChat", true, "Whether to display an auto-ban notification in the in-game chat / pause log.");
_harmony = new Harmony("com.balu.straftat.autoscoreban");
_harmony.PatchAll();
Log.LogInfo((object)string.Format("[{0}] Plugin initialized successfully! Score threshold: {1}, friends protected: {2}", "AutoScoreBan", MinScore.Value, IgnoreFriends.Value));
}
private void OnDestroy()
{
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
}
public static class ScoreAutoBanManager
{
private static readonly Dictionary<ulong, int> CachedScores = new Dictionary<ulong, int>();
private static readonly HashSet<ulong> InFlightFetches = new HashSet<ulong>();
private static readonly HashSet<ulong> BannedThisSession = new HashSet<ulong>();
private static readonly FieldRef<Settings, LeaderboardManager> GetLeaderboardManagerRef = AccessTools.FieldRefAccess<Settings, LeaderboardManager>("leaderboardManager");
public static bool IsHost()
{
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
try
{
if ((Object)(object)InstanceFinder.NetworkManager != (Object)null && InstanceFinder.NetworkManager.IsServer)
{
return true;
}
if ((Object)(object)ClientInstance.Instance != (Object)null && ((NetworkBehaviour)ClientInstance.Instance).IsServer)
{
return true;
}
if ((Object)(object)SteamLobby.Instance != (Object)null && SteamLobby.Instance.CurrentLobbyID != 0)
{
CSteamID lobbyOwner = SteamMatchmaking.GetLobbyOwner(new CSteamID(SteamLobby.Instance.CurrentLobbyID));
if (lobbyOwner == SteamUser.GetSteamID())
{
return true;
}
}
}
catch (Exception ex)
{
Plugin.Log.LogError((object)("[AutoScoreBan] Error checking host status: " + ex.Message));
}
return false;
}
public static bool IsFriend(ulong steamId)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Invalid comparison between Unknown and I4
try
{
EFriendRelationship friendRelationship = SteamFriends.GetFriendRelationship((CSteamID)steamId);
return (int)friendRelationship == 3;
}
catch (Exception ex)
{
Plugin.Log.LogError((object)$"[AutoScoreBan] Error checking friend relationship for {steamId}: {ex.Message}");
return false;
}
}
public static LeaderboardManager GetLeaderboardManager()
{
if ((Object)(object)Settings.Instance == (Object)null)
{
return null;
}
try
{
LeaderboardManager val = GetLeaderboardManagerRef.Invoke(Settings.Instance);
if ((Object)(object)val != (Object)null)
{
return val;
}
}
catch
{
}
return ((Component)Settings.Instance).GetComponentInChildren<LeaderboardManager>();
}
public static void CheckPlayer(PlayerListItem listItem)
{
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
if (!Plugin.ModEnabled.Value || !IsHost() || (Object)(object)listItem == (Object)null)
{
return;
}
ulong steamId = listItem.PlayerSteamID;
if (steamId == 0)
{
return;
}
ulong num = 0uL;
try
{
num = (ulong)SteamUser.GetSteamID();
}
catch
{
}
if (steamId == num)
{
return;
}
string playerName = listItem.PlayerName ?? $"SteamID_{steamId}";
if (BannedThisSession.Contains(steamId))
{
CachedScores.TryGetValue(steamId, out var value);
EnsurePlayerKicked(steamId, playerName, value);
}
else
{
if (Plugin.IgnoreFriends.Value && IsFriend(steamId))
{
return;
}
if (CachedScores.TryGetValue(steamId, out var value2))
{
EvaluateScoreAndBan(steamId, playerName, value2);
}
else
{
if (InFlightFetches.Contains(steamId))
{
return;
}
LeaderboardManager leaderboardManager = GetLeaderboardManager();
if ((Object)(object)leaderboardManager == (Object)null || (Object)(object)leaderboardManager.leaderboard == (Object)null || !leaderboardManager.leaderboard.Valid)
{
return;
}
InFlightFetches.Add(steamId);
Plugin.Log.LogInfo((object)$"[AutoScoreBan] Fetching score for player '{playerName}' ({steamId}) from Steam Leaderboard...");
UserData val = UserData.Get(steamId);
leaderboardManager.leaderboard.GetEntries((UserData[])(object)new UserData[1] { val }, (Action<LeaderboardEntry[], bool>)delegate(LeaderboardEntry[] results, bool error)
{
InFlightFetches.Remove(steamId);
try
{
if (error || results == null || results.Length == 0)
{
Plugin.Log.LogInfo((object)$"[AutoScoreBan] Player '{playerName}' ({steamId}) has no entry on leaderboard (error={error}).");
if (Plugin.BanUnranked.Value)
{
CachedScores[steamId] = 0;
EvaluateScoreAndBan(steamId, playerName, 0);
}
}
else
{
int score = results[0].Score;
int rank = results[0].Rank;
Plugin.Log.LogInfo((object)$"[AutoScoreBan] Retrieved data for player '{playerName}' ({steamId}): Score={score}, Rank={rank}.");
CachedScores[steamId] = score;
EvaluateScoreAndBan(steamId, playerName, score);
}
}
catch (Exception arg)
{
Plugin.Log.LogError((object)$"[AutoScoreBan] Error processing score callback for {playerName} ({steamId}): {arg}");
}
});
}
}
}
private static void EvaluateScoreAndBan(ulong steamId, string playerName, int score)
{
if (Plugin.ModEnabled.Value && IsHost() && (!Plugin.IgnoreFriends.Value || !IsFriend(steamId)))
{
int value = Plugin.MinScore.Value;
if (score < value && BannedThisSession.Add(steamId))
{
ExecuteBan(steamId, playerName, score, value);
}
}
}
private static void ExecuteBan(ulong steamId, string playerName, int score, int threshold)
{
Plugin.Log.LogWarning((object)$"[AutoScoreBan] Auto-banning player '{playerName}' ({steamId}): score {score} < {threshold}.");
try
{
if ((Object)(object)SteamLobby.Instance != (Object)null)
{
SteamLobby.Instance.AddLobbyBan(steamId);
}
}
catch (Exception ex)
{
Plugin.Log.LogError((object)("[AutoScoreBan] Error in SteamLobby.AddLobbyBan: " + ex.Message));
}
if (Plugin.NotifyInChat.Value)
{
try
{
if ((Object)(object)PauseManager.Instance != (Object)null)
{
PauseManager.Instance.WriteLog($"[AutoScoreBan] <color=#ff4444>{playerName}</color> was banned by the host (Score: {score} < {threshold})");
}
}
catch
{
}
}
EnsurePlayerKicked(steamId, playerName, score);
}
private static void EnsurePlayerKicked(ulong steamId, string playerName, int score)
{
if ((Object)(object)GameManager.Instance == (Object)null)
{
return;
}
NetworkConnection val = FindNetworkConnection(steamId);
if (!(val != (NetworkConnection)null))
{
return;
}
string text = ((!string.IsNullOrEmpty(Plugin.BanReason.Value)) ? Plugin.BanReason.Value : "I'm doing this for your own good");
Plugin.Log.LogInfo((object)$"[AutoScoreBan] Kicking network client ConnId={val.ClientId} ({playerName}) with reason: '{text}'");
try
{
GameManager.Instance.CmdKickPlayer(val, text);
}
catch (Exception ex)
{
Plugin.Log.LogError((object)("[AutoScoreBan] Error calling CmdKickPlayer: " + ex.Message));
}
}
private static NetworkConnection FindNetworkConnection(ulong steamId)
{
if (ClientInstance.playerInstances != null)
{
foreach (ClientInstance value in ClientInstance.playerInstances.Values)
{
if ((Object)(object)value != (Object)null && value.PlayerSteamID == steamId)
{
return ((NetworkBehaviour)value).Owner;
}
}
}
if ((Object)(object)SteamLobby.Instance != (Object)null && SteamLobby.Instance.players != null)
{
for (int i = 0; i < SteamLobby.Instance.players.Count; i++)
{
NetworkObject val = SteamLobby.Instance.players[i];
if ((Object)(object)val != (Object)null)
{
ClientInstance component = ((Component)val).GetComponent<ClientInstance>();
if ((Object)(object)component != (Object)null && component.PlayerSteamID == steamId)
{
return val.Owner;
}
}
}
}
return null;
}
public static void OnLeaveLobby()
{
BannedThisSession.Clear();
InFlightFetches.Clear();
Plugin.Log.LogInfo((object)"[AutoScoreBan] Left lobby: session state cleared.");
}
}
[HarmonyPatch(typeof(PlayerListItem), "SetPlayerValues")]
public static class PlayerListItem_SetPlayerValues_Patch
{
[HarmonyPostfix]
public static void Postfix(PlayerListItem __instance)
{
try
{
ScoreAutoBanManager.CheckPlayer(__instance);
}
catch (Exception arg)
{
Plugin.Log.LogError((object)$"[AutoScoreBan] Error in SetPlayerValues hook: {arg}");
}
}
}
[HarmonyPatch(typeof(SteamLobby), "LeaveLobby")]
public static class SteamLobby_LeaveLobby_Patch
{
[HarmonyPostfix]
public static void Postfix()
{
try
{
ScoreAutoBanManager.OnLeaveLobby();
}
catch (Exception arg)
{
Plugin.Log.LogError((object)$"[AutoScoreBan] Error in LeaveLobby hook: {arg}");
}
}
}
}