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 System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Pun.UtilityScripts;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("CharlesE2")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Client-side anticheat mod.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+8335785c28fd88f3e4671c255a2624adbe4943ea")]
[assembly: AssemblyProduct("RepoAntiCheat")]
[assembly: AssemblyTitle("com.github.CharlesE2.RepoAntiCheat")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Charlese2/RepoAntiCheat")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 RepoAntiCheat
{
[BepInPlugin("com.github.CharlesE2.RepoAntiCheat", "RepoAntiCheat", "1.0.0")]
public class RepoAntiCheat : BaseUnityPlugin
{
[CompilerGenerated]
private static class <>O
{
public static PlayerNumberingChanged <0>__PlayerNumberingChanged;
}
public static Dictionary<int, PlayerAvatar> playerActorNrToPlayerAvatarMap = new Dictionary<int, PlayerAvatar>();
public static RepoAntiCheat Instance { get; private set; } = null;
internal static ManualLogSource Log { get; private set; } = null;
internal static Harmony? Harmony { get; set; }
private static void PlayerNumberingChanged()
{
Log.LogInfo((object)"PlayerNumberingChanged");
playerActorNrToPlayerAvatarMap.Clear();
}
public static PlayerAvatar? GetPlayerAvatarFromActorNumber(int actorNumber)
{
if (!playerActorNrToPlayerAvatarMap.TryGetValue(actorNumber, out PlayerAvatar value))
{
foreach (PlayerAvatar player in GameDirector.instance.PlayerList)
{
if (player.photonView.OwnerActorNr == actorNumber)
{
playerActorNrToPlayerAvatarMap.Add(actorNumber, player);
return player;
}
}
}
return value;
}
private void Awake()
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
Instance = this;
((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
Patch();
object obj = <>O.<0>__PlayerNumberingChanged;
if (obj == null)
{
PlayerNumberingChanged val = PlayerNumberingChanged;
<>O.<0>__PlayerNumberingChanged = val;
obj = (object)val;
}
PlayerNumbering.OnPlayerNumberingChanged += (PlayerNumberingChanged)obj;
Log.LogInfo((object)"com.github.CharlesE2.RepoAntiCheat v1.0.0 has loaded!");
}
private void OnDestroy()
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Expected O, but got Unknown
object obj = <>O.<0>__PlayerNumberingChanged;
if (obj == null)
{
PlayerNumberingChanged val = PlayerNumberingChanged;
<>O.<0>__PlayerNumberingChanged = val;
obj = (object)val;
}
PlayerNumbering.OnPlayerNumberingChanged -= (PlayerNumberingChanged)obj;
Unpatch();
Log.LogInfo((object)"com.github.CharlesE2.RepoAntiCheat v1.0.0 has unloaded!");
}
internal static void Patch()
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Expected O, but got Unknown
if (Harmony == null)
{
Harmony = new Harmony("com.github.CharlesE2.RepoAntiCheat");
}
Log.LogDebug((object)"Patching...");
Harmony.PatchAll();
Log.LogDebug((object)"Finished patching!");
}
internal static void Unpatch()
{
Log.LogDebug((object)"Unpatching...");
Harmony? harmony = Harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
Log.LogDebug((object)"Finished unpatching!");
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "com.github.CharlesE2.RepoAntiCheat";
public const string PLUGIN_NAME = "RepoAntiCheat";
public const string PLUGIN_VERSION = "1.0.0";
}
}
namespace RepoAntiCheat.Patches
{
internal class PlayerNamePatch
{
[HarmonyPatch(typeof(WorldSpaceUIParent), "PlayerName")]
internal static class SanitizePlayerName
{
public static void Prefix(ref PlayerAvatar _player)
{
string text = Regex.Replace(_player.playerName, "<(\\S+?)>", "");
if (text.Length > 32)
{
text = text.Substring(0, 32);
}
_player.playerName = text;
}
}
}
internal class RPCPatches
{
[HarmonyPatch(typeof(PlayerAvatar), "ChatMessageSendRPC")]
internal static class ChatMesageSend
{
public static bool Prefix(PlayerAvatar __instance, ref string _message, ref PhotonMessageInfo info)
{
if (__instance.photonView.Owner != info.Sender)
{
RepoAntiCheat.Log.LogInfo((object)$"ChatMessage ({_message}) owner ({info.photonView.Owner}) does not match sender ({info.Sender}).");
return false;
}
string text = Regex.Replace(_message, "<(\\S+?)>", "");
if (text.Length > 50)
{
text = text.Substring(0, 50);
}
if (string.IsNullOrWhiteSpace(text))
{
RepoAntiCheat.Log.LogInfo((object)$"{info.Sender} Chat message was empty. Original Message: ({_message})");
return false;
}
_message = text;
return true;
}
}
[HarmonyPatch(typeof(PlayerAvatar), "AddToStatsManagerRPC")]
internal static class AddToStatsManager
{
public static bool Prefix(PlayerAvatar __instance, ref string _playerName, ref PhotonMessageInfo info)
{
if (info.Sender == null)
{
return true;
}
if (__instance.photonView.Owner != info.Sender)
{
return false;
}
string text = Regex.Replace(_playerName, "<(\\S+?)>", "");
if (text.Length > 32)
{
text = text.Substring(0, 32);
}
_playerName = text;
return true;
}
}
[HarmonyPatch(typeof(PlayerAvatar), "SpawnRPC")]
internal static class SpawnPlayer
{
public static bool Prefix(PlayerAvatar __instance, Vector3 position, ref PhotonMessageInfo info)
{
if (info.Sender == null)
{
return true;
}
if (info.Sender != PhotonNetwork.MasterClient)
{
RepoAntiCheat.Log.LogInfo((object)($"Player ({info.Sender}) tried to call SpawnRPC " + $"for ({__instance.photonView.Owner}) while not the master client ({PhotonNetwork.MasterClient})."));
return false;
}
return true;
}
}
[HarmonyPatch(typeof(PlayerAvatar), "PlayerDeathRPC")]
internal static class PlayerDeath
{
public static bool Prefix(PlayerAvatar __instance, ref PhotonMessageInfo info)
{
if (info.Sender == null)
{
return true;
}
if (info.Sender != PhotonNetwork.MasterClient && info.Sender != __instance.photonView.Owner)
{
RepoAntiCheat.Log.LogInfo((object)($"Player ({info.Sender}) tried to call PlayerDeathRPC " + $"while not the master client ({PhotonNetwork.MasterClient}) " + $"or the the owner ({__instance.photonView.Owner})."));
return false;
}
return true;
}
}
[HarmonyPatch(typeof(PlayerAvatar), "ReviveRPC")]
internal static class Revive
{
public static bool Prefix(PlayerAvatar __instance, bool _revivedByTruck, ref PhotonMessageInfo info)
{
if (info.Sender != PhotonNetwork.MasterClient)
{
RepoAntiCheat.Log.LogInfo((object)$"[ReviveRPC] STOPPED Player: ({__instance}) Sender: ({info.Sender}) _revivedByTruck: ({_revivedByTruck})");
return false;
}
RepoAntiCheat.Log.LogInfo((object)$"[ReviveRPC] Player: ({__instance}) Sender: ({info.Sender}) _revivedByTruck: ({_revivedByTruck})");
return true;
}
}
[HarmonyPatch(typeof(PlayerAvatar), "OutroStartRPC")]
internal static class OutroStart
{
public static bool Prefix(PlayerAvatar __instance, ref PhotonMessageInfo info)
{
if (info.Sender == null)
{
return true;
}
if (info.Sender != PhotonNetwork.MasterClient)
{
RepoAntiCheat.Log.LogInfo((object)($"Player ({info.Sender}) tried to call OutroStartRPC " + $"for ({__instance.photonView.Owner}) while not the master client ({PhotonNetwork.MasterClient})."));
return false;
}
return true;
}
}
[HarmonyPatch(typeof(ExtractionPoint), "HaulGoalSetRPC")]
internal static class HaulGoalSet
{
public static bool Prefix(int value, ref PhotonMessageInfo info)
{
if (info.Sender == null)
{
return true;
}
if (info.Sender != PhotonNetwork.MasterClient)
{
RepoAntiCheat.Log.LogInfo((object)($"Player ({info.Sender}) tried to call HaulGoalSetRPC " + $"while not the master client ({PhotonNetwork.MasterClient})."));
return false;
}
return true;
}
}
[HarmonyPatch(typeof(ExtractionPoint), "ExtractionPointSurplusRPC")]
internal static class ExtractionPointSurplus
{
public static bool Prefix(int surplus, ref PhotonMessageInfo info)
{
if (info.Sender == null)
{
return true;
}
if (info.Sender != PhotonNetwork.MasterClient)
{
RepoAntiCheat.Log.LogInfo((object)($"Player ({info.Sender}) tried to call ExtractionPointSurplusRPC " + $"while not the master client ({PhotonNetwork.MasterClient})" + $"with a surplus of ({surplus})"));
return false;
}
return true;
}
}
[HarmonyPatch(typeof(RoundDirector), "ExtractionPointActivateRPC")]
internal static class ExtractionPointActivate
{
public static bool Prefix(ref PhotonMessageInfo info)
{
if (info.Sender == null)
{
return true;
}
if (info.Sender != PhotonNetwork.MasterClient)
{
RepoAntiCheat.Log.LogInfo((object)($"Player ({info.Sender}) tried to call ExtractionPointActivateRPC " + $"while not the master client ({PhotonNetwork.MasterClient})."));
return false;
}
return true;
}
}
[HarmonyPatch(typeof(PlayerHealth), "UpdateHealthRPC")]
internal static class UpdateHealth
{
public static bool Prefix(PlayerHealth __instance, int healthNew, int healthMax, ref PhotonMessageInfo info)
{
if (info.Sender == null)
{
return true;
}
if (info.Sender != __instance.photonView.Owner)
{
return false;
}
return true;
}
}
[HarmonyPatch(typeof(PlayerHealth), "HealOtherRPC")]
internal static class HealOther
{
public static bool Prefix(PlayerHealth __instance, int healAmount, ref PhotonMessageInfo info)
{
RepoAntiCheat.Log.LogInfo((object)($"[HealOtherRPC] __instance.photonView.Owner ({__instance.photonView.Owner}) info.Sender: ({info.Sender})" + $"healAmount: ({healAmount})."));
_ = info.Sender;
return true;
}
}
[HarmonyPatch(typeof(PlayerHealth), "HurtOtherRPC")]
internal static class HurtOther
{
public static bool Prefix(PlayerHealth __instance, int damage, ref PhotonMessageInfo info)
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
if (info.Sender == PhotonNetwork.MasterClient)
{
return true;
}
PlayerAvatar playerAvatarFromActorNumber = RepoAntiCheat.GetPlayerAvatarFromActorNumber(info.Sender.ActorNumber);
if ((Object)(object)playerAvatarFromActorNumber != (Object)null && Vector3.Distance(((Component)playerAvatarFromActorNumber).transform.position, ((Component)__instance).transform.position) > 2f)
{
RepoAntiCheat.Log.LogInfo((object)($"{info.Sender} sent HurtOtherRPC with damage ({damage}) from too far away " + $"({Vector3.Distance(((Component)playerAvatarFromActorNumber).transform.position, ((Component)__instance).transform.position)})."));
return false;
}
return true;
}
}
[HarmonyPatch(typeof(RoundDirector), "ExtractionCompletedAllRPC")]
internal static class ExtractionCompleteAll
{
public static bool Prefix(RoundDirector __instance, ref PhotonMessageInfo info)
{
if (info.Sender == null)
{
return true;
}
if (info.Sender != PhotonNetwork.MasterClient)
{
RepoAntiCheat.Log.LogInfo((object)($"Player ({info.Sender}) tried to call ExtractionCompletedAllRPC " + $"while not the master client ({PhotonNetwork.MasterClient})."));
return false;
}
return true;
}
}
[HarmonyPatch(typeof(TruckScreenText), "SelfDestructPlayersOutsideTruckRPC")]
internal static class SelfDestructPlayersOutsideTruck
{
public static bool Prefix(ref PhotonMessageInfo info)
{
if (info.Sender == null)
{
return true;
}
if (info.Sender != PhotonNetwork.MasterClient)
{
RepoAntiCheat.Log.LogInfo((object)($"Player ({info.Sender}) tried to call SelfDestructPlayersOutsideTruckRPC " + $"while not the master client ({PhotonNetwork.MasterClient})."));
return false;
}
return true;
}
}
}
}