Decompiled source of FusionGuard Quest v8.4.9
Mods/FusionGuard.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Net.Http; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.Json; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using BoneLib; using BoneLib.BoneMenu; using BoneLib.Notifications; using FusionGuard; using HarmonyLib; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSLZ.Marrow; using Il2CppSLZ.Marrow.Combat; using Il2CppSLZ.Marrow.Data; using Il2CppSLZ.Marrow.Interaction; using Il2CppSLZ.Marrow.Pool; using Il2CppSLZ.Marrow.VFX; using Il2CppSLZ.Marrow.Warehouse; using Il2CppSLZ.VRMK; using Il2CppSystem.Collections.Generic; using LabFusion.Data; using LabFusion.Entities; using LabFusion.Extensions; using LabFusion.Marrow.Extenders; using LabFusion.Marrow.Messages; using LabFusion.Marrow.Serialization; using LabFusion.Network; using LabFusion.Player; using LabFusion.Preferences; using LabFusion.Preferences.Server; using LabFusion.Representation; using LabFusion.SDK.Gamemodes; using LabFusion.SDK.Metadata; using LabFusion.Senders; using LabFusion.Utilities; using LabFusion.Voice; using MelonLoader; using MelonLoader.Preferences; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.VFX; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(Core), "FusionGuard Quest", "8.4.9", "DragonBird", null)] [assembly: MelonGame("Stress Level Zero", "BONELAB")] [assembly: MelonAdditionalDependencies(new string[] { "LabFusion" })] [assembly: AssemblyMetadata("AIGenerated", "Code written with the help of Claude (Anthropic)")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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 FusionGuard { internal class PendingSpawn { public object Handler; public MethodInfo Method; public ReceivedMessage Message; public byte Owner; public int EntityID = -1; public bool Particle; } internal class FxEntry { public Poolee Poolee; public GameObject Go; public byte Owner; public float Time; } internal static class FusionCompat { private const BindingFlags PubStatic = BindingFlags.Static | BindingFlags.Public; private const BindingFlags PubInst = BindingFlags.Instance | BindingFlags.Public; private static PropertyInfo _playerIdPlat; private static PropertyInfo _playerInfoPlat; private static MethodInfo _fetchPerm; private static MethodInfo _setPerm; private static MethodInfo _pardon; private static bool _init; private static MethodInfo _deny; private static MethodInfo _disconnectUser; internal static bool StringIds { get; private set; } internal static string Mode => StringIds ? "Fusion EOS (Epic/Quest)" : "Official Fusion (SteamVR)"; internal static bool PermsOk { get { Init(); return _fetchPerm != null; } } internal static void Init() { if (!_init) { _init = true; _playerIdPlat = typeof(PlayerID).GetProperty("PlatformID", BindingFlags.Instance | BindingFlags.Public); _playerInfoPlat = typeof(PlayerInfo).GetProperty("PlatformID", BindingFlags.Instance | BindingFlags.Public); StringIds = _playerIdPlat != null && _playerIdPlat.PropertyType == typeof(string); Type typeFromHandle = typeof(FusionPermissions); _fetchPerm = typeFromHandle.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo m) => m.Name == "FetchPermissionLevel" && m.GetParameters().Length == 3); _setPerm = typeFromHandle.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo m) => m.Name == "TrySetPermission" && m.GetParameters().Length == 3); _pardon = typeof(NetworkHelper).GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo m) => m.Name == "PardonUser" && m.GetParameters().Length == 1); } } internal static string Plat(PlayerID player) { if (player == null) { return string.Empty; } Init(); return Normalize(_playerIdPlat?.GetValue(player)); } internal static string BanPlat(PlayerInfo info) { if (info == null) { return string.Empty; } Init(); return Normalize(_playerInfoPlat?.GetValue(info)); } internal static bool Has(string plat) { return !string.IsNullOrEmpty(plat); } private static string Normalize(object value) { if (value == null) { return string.Empty; } if (value is ulong num) { return (num == 0L) ? string.Empty : num.ToString(); } return value.ToString() ?? string.Empty; } private static bool TryArg(string plat, Type target, out object arg) { arg = null; if (!Has(plat)) { return false; } if (target == typeof(string)) { arg = plat; return true; } if (target == typeof(ulong) && ulong.TryParse(plat, out var result)) { arg = result; return true; } return false; } internal static PermissionLevel FetchPermission(string plat) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) Init(); if (_fetchPerm == null || !TryArg(plat, _fetchPerm.GetParameters()[0].ParameterType, out var arg)) { return (PermissionLevel)0; } object[] array = new object[3] { arg, null, null }; _fetchPerm.Invoke(null, array); return (PermissionLevel)((array[1] is PermissionLevel val) ? ((int)val) : 0); } internal static void SetPermission(string plat, string username, PermissionLevel level) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) Init(); if (!(_setPerm == null) && TryArg(plat, _setPerm.GetParameters()[0].ParameterType, out var arg)) { _setPerm.Invoke(null, new object[3] { arg, username, level }); } } internal static void Deny(string plat, string reason) { try { if (_deny == null) { _deny = typeof(ConnectionSender).GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo m) => m.Name == "SendConnectionDeny" && m.GetParameters().Length == 2); } if (!(_deny == null) && TryArg(plat, _deny.GetParameters()[0].ParameterType, out var arg)) { _deny.Invoke(null, new object[2] { arg, reason }); } } catch { } } internal static void Pardon(string plat) { Init(); if (!(_pardon == null) && TryArg(plat, _pardon.GetParameters()[0].ParameterType, out var arg)) { _pardon.Invoke(null, new object[1] { arg }); } } internal static void CloseConnection(string plat) { try { if (_disconnectUser == null) { _disconnectUser = typeof(NetworkConnectionManager).GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo m) => m.Name == "DisconnectUser" && m.GetParameters().Length == 1); } if (!(_disconnectUser == null) && TryArg(plat, _disconnectUser.GetParameters()[0].ParameterType, out var arg)) { _disconnectUser.Invoke(null, new object[1] { arg }); } } catch { } } } internal static class PlatformDetect { private const BindingFlags All = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private static bool _init; private static bool _ok; private static PropertyInfo _connectProp; private static FieldInfo _runtimeField; private static FieldInfo _connIface; private static FieldInfo _localUser; private static MethodInfo _fromString; private static MethodInfo _copyInfo; private static MethodInfo _query; private static ConstructorInfo _utfCtor; private static Type _copyOptT; private static Type _queryOptT; private static Type _puidT; private static Delegate _callback; private static readonly Dictionary<string, string> cache = new Dictionary<string, string>(); private static readonly Dictionary<string, float> asked = new Dictionary<string, float>(); private static void Init() { if (_init) { return; } _init = true; try { Assembly assembly = typeof(PlayerID).Assembly; Type type = assembly.GetType("LabFusion.Network.EOSRuntime"); Type type2 = assembly.GetType("LabFusion.Network.EpicGamesNetworkLayer"); if (type2 != null) { _runtimeField = type2.GetField("Runtime", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } Type type3 = assembly.GetType("LabFusion.Network.EOSConnect"); _puidT = assembly.GetType("Epic.OnlineServices.ProductUserId"); Type type4 = assembly.GetType("Epic.OnlineServices.Utf8String"); Type type5 = assembly.GetType("Epic.OnlineServices.Connect.ConnectInterface"); _copyOptT = assembly.GetType("Epic.OnlineServices.Connect.CopyProductUserInfoOptions"); _queryOptT = assembly.GetType("Epic.OnlineServices.Connect.QueryProductUserIdMappingsOptions"); Type type6 = assembly.GetType("Epic.OnlineServices.Connect.OnQueryProductUserIdMappingsCallback"); if (!(type == null) && !(type3 == null) && !(_puidT == null) && !(type4 == null) && !(type5 == null) && !(_copyOptT == null) && !(_queryOptT == null) && !(type6 == null)) { _connectProp = type.GetProperty("Connect", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); _connIface = type3.GetField("ConnectInterface", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); _localUser = type3.GetField("LocalUserId", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); _fromString = _puidT.GetMethod("FromString", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { type4 }, null); _utfCtor = type4.GetConstructor(new Type[1] { typeof(string) }); _copyInfo = type5.GetMethod("CopyProductUserInfo", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); _query = type5.GetMethod("QueryProductUserIdMappings", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); Type parameterType = type6.GetMethod("Invoke").GetParameters()[0].ParameterType; ParameterExpression parameterExpression = Expression.Parameter(parameterType, "data"); _callback = Expression.Lambda(type6, Expression.Empty(), parameterExpression).Compile(); _ok = _connectProp != null && _runtimeField != null && _connIface != null && _localUser != null && _fromString != null && _utfCtor != null && _copyInfo != null && _query != null; } } catch (Exception ex) { _ok = false; MelonLogger.Warning("[Platform] init : " + ex.Message); } } internal static void Clear() { asked.Clear(); } internal static string Get(string plat) { if (!FusionCompat.Has(plat)) { return "?"; } if (!FusionCompat.StringIds) { return "PC"; } if (cache.TryGetValue(plat, out var value)) { return value; } Init(); if (!_ok) { return "?"; } try { object layer = NetworkLayerManager.Layer; if (layer == null || !_runtimeField.DeclaringType.IsInstanceOfType(layer)) { return "?"; } object value2 = _runtimeField.GetValue(layer); object obj = ((value2 != null) ? _connectProp.GetValue(value2) : null); if (obj == null) { return "?"; } object value3 = _connIface.GetValue(obj); object value4 = _localUser.GetValue(obj); object obj2 = _fromString.Invoke(null, new object[1] { _utfCtor.Invoke(new object[1] { plat }) }); if (value3 == null || obj2 == null) { return "?"; } object obj3 = Activator.CreateInstance(_copyOptT); _copyOptT.GetProperty("TargetUserId").SetValue(obj3, obj2); object[] array = new object[2] { obj3, null }; object obj4 = _copyInfo.Invoke(value3, array); if (obj4 != null && obj4.ToString() == "Success" && array[1] != null) { object obj5 = array[1]; string text = obj5.GetType().GetProperty("AccountIdType")?.GetValue(obj5)?.ToString() ?? ""; string text2 = text switch { "Epic" => "PC (Epic)", "Oculus" => "QUEST", "Steam" => "PC", _ => text.ToUpperInvariant(), }; if (!string.IsNullOrEmpty(text2)) { cache[plat] = text2; return text2; } } float realtimeSinceStartup = Time.realtimeSinceStartup; if (value4 != null && (!asked.TryGetValue(plat, out var value5) || realtimeSinceStartup - value5 > 20f)) { asked[plat] = realtimeSinceStartup; object obj6 = Activator.CreateInstance(_queryOptT); _queryOptT.GetProperty("LocalUserId").SetValue(obj6, value4); Array array2 = Array.CreateInstance(_puidT, 1); array2.SetValue(obj2, 0); _queryOptT.GetProperty("ProductUserIds").SetValue(obj6, array2); _query.Invoke(value3, new object[3] { obj6, null, _callback }); } } catch (Exception ex) { MelonLogger.Warning("[Platform] " + (ex.InnerException?.Message ?? ex.Message)); } return "?"; } } internal class SecAlert { public string Kind; public byte Small; public string PlatformID; public string Name; public string Reason; public int Count; public float Last; public byte? Target; public string TargetName; public bool Ban; public bool Kicked; public float KickedAt; public bool Allowed; } internal class PlayerHold { public byte SmallID; public string PlatformID; public string Name; public int Total; public int Particles; public int Dropped; public bool ByParticles; public bool Quarantine; public int ScoreAtStart; public readonly Dictionary<string, int> Counts = new Dictionary<string, int>(); public readonly Dictionary<string, string> Titles = new Dictionary<string, string>(); public readonly List<PendingSpawn> Queue = new List<PendingSpawn>(); public readonly List<PendingSpawn> FxQueue = new List<PendingSpawn>(); } public class Core : MelonMod { private delegate void PlatSetter(ref ReadableMessage message, string plat); private class GuardBan { public string Plat; public string Name; public string Reason; public string Date; } private class GodTrack { public float Start = -1f; public int Hits; public float MinRatio = 1f; public float LastH; public float LastM; public float LastDrop = -1f; public readonly List<float> RegenHits = new List<float>(); public int BadHealth; public int AvatarId; } private class MsgCounter { public float Since; public int Count; public int Over; public long Bytes; public int OverBytes; } private sealed class LobbyPlayerRow { public string Name; public string User; public string Id; public string Fg; public string Watch; public bool HasFg; } private sealed class LobbyRow { public string Key; public string Name; public string Host; public string Code; public string Level; public string Mode; public string Privacy; public string FgHostVer; public string FgHostPlat; public int Count; public int Max; public int FgCount; public bool FgHost; public bool Open; public List<LobbyPlayerRow> Players = new List<LobbyPlayerRow>(); public Action Join; } private struct RecentSpawn { public ushort Id; public byte Owner; public float Time; } private class NetStat { public int Msgs; public int Spawns; public int Despawns; public int Owners; public int Damage; public int Kicks; public long Bytes; public readonly Dictionary<string, int> Types = new Dictionary<string, int>(); } private class GunTrack { public int LastAmmo = -1; public float LastShot; public int NoDrop; public readonly Queue<float> Times = new Queue<float>(); public Gun Gun; public float GunAt; public readonly List<KeyValuePair<float, Vector3>> Aim = new List<KeyValuePair<float, Vector3>>(); } private class LastShotInfo { public float Time; public ushort GunId; public Gun Gun; } private class RecentShot { public float Time; public Vector3 Muzzle; public Vector3 Forward; public float Spread; public float TurnSpeed; } private class GrabOnMe { public byte Sender; public Handedness Hand; public float Since; public float BadSince = -1f; } private class DmgSample { public byte Shooter; public float K; public string Gun; } private class FreezeState { public Vector3 Pos; public float LastTp; public string Name; } private class AimEval { public float Time; public bool Sus; public float Angle; } private class AimShot { public float Time; public byte Target = byte.MaxValue; public float Dist; public bool Snap; public float Peak; public bool Hit; public bool Head; public bool Moving; } private class BlockedWord { public string Word; public bool On = true; public bool Everywhere; } private class ApprovalHold { public byte SmallID; public string PlatformID; public string Name; public float Since; public readonly List<PendingSpawn> Queue = new List<PendingSpawn>(); public readonly Dictionary<string, int> Counts = new Dictionary<string, int>(); } private enum ItemKind { Toggle, Slider, Cycle, Page, Action, Info, Header } private class MenuItem { public string Label; public ItemKind Kind; public Func<bool> GetBool; public Action<bool> SetBool; public Func<float> GetFloat; public Action<float> SetFloat; public float Min; public float Max; public float Step; public string Suffix = ""; public Func<string> GetText; public Action Click; public MenuPage Target; public bool HasTint; public Color Tint; public string Key; public string ConfirmKey; } private class MenuPage { public string Title; public MenuPage Parent; public int Scroll; public bool NoSave; public object Tag; public Func<int> Badge; public string Desc; public List<MenuItem> Items = new List<MenuItem>(); } private class UiButton { public Renderer Rend; public Vector2 Center; public Vector2 Half; public Color Base; public Action Press; public string Key; } private class TpBack { public Vector3 Pos; public Vector3 SentTo; public string Plat; } private class StateSlot { public MenuItem It; public MelonPreferences_Entry<bool> B; public MelonPreferences_Entry<float> F; public MelonPreferences_Entry<string> S; } internal static Core Instance; private static int _isQuest = -1; internal static bool Replaying; private static MethodInfo handleMethod; private static MethodInfo requestMethod; private bool protection = true; private bool antiSpawn = false; private bool allowPerms = true; private int preset = 1; private float threshold = 15f; private float window = 3f; private float loadSpeed = 4f; private float maxQueue = 1500f; private bool trustHost = true; private bool autoOpen = true; private bool autoClose = true; private bool notifications = true; private bool hostFilter = true; private bool clientFilter = true; private bool warnHold = true; private bool warnBlocked = true; private bool logAll = false; private bool blockItems = true; private bool askExplosives = true; private bool fxFilter = true; private float fxThreshold = 10f; private float fxWindow = 3f; private float maxActiveFx = 40f; private bool blockAllFx = false; private bool limitSpawnFx = true; private float spawnFxPerSec = 10f; private bool antiCheatDamage = true; private bool autoKick = true; private float kickStrikes = 3f; private float meleeRange = 3f; private bool antiKickServer = true; private bool antiFakeKick = true; private bool kickNotifs = true; private bool secPopup = true; private bool godDetect = true; private bool confirmOpKicks = false; private bool antiFakePerms = true; private bool antiHijack = true; private bool antiForeignDespawn = true; private bool limitAvatarSpam = true; private bool antiHealthHack = true; private float godHits = 10f; private bool antiBadPose = true; private bool antiFlood = true; private float floodLimit = 3000f; private float floodKB = 512f; private bool antiGamemodeTriggers = true; private bool antiFakeTp = true; private bool limitTeleports = true; private int triggersBlocked; private int tpBlocked; private int ghostDropped; private bool operatorMode = true; private bool autoBanCrashSpam = true; private bool hostCrashDespawn = true; private bool kickNukeSpam = true; private float nukeKickAt = 2f; private float explosiveKickAt = 6f; private int spawnKicks; private float crashSpamSecs = 5f; private bool shieldMode = false; private int shieldDropped; private int autoBans; private bool antiGodGuns = true; private bool antiSilentAim = true; private bool detectAimLock = true; private bool antiInfiniteAmmo = true; private bool antiWallbang = true; private bool antiNoShotDamage = true; private bool antiRemoteGrab = true; private bool antiFling = true; private float flingSpeed = 60f; private int combatBlocked; private int grabsBlocked; private int flingsStopped; private int ammoAlerts; private bool warnBannedJoin = true; private bool watchScanLobbies = true; private bool detectDmgMult = true; private bool antiKillAir = true; private int multAlerts; private int godScanHits; private const int MaxMessageBytes = 262144; private const int MaxMetadataChars = 1024; private bool antiRemoteFire = true; private bool antiSlowMo = true; private bool antiLinks = true; private float avatarMax = 6f; private static readonly string[] PresetNames = new string[5] { "Low", "Normal", "High", "Max", "Custom" }; private static readonly string[] SpawnPermNames = new string[3] { "Normal", "Trusted", "Blocked" }; private static readonly string[] PermNames = new string[4] { "Guest", "Default", "Operator", "Owner" }; private static readonly float[] PresetThreshold = new float[4] { 40f, 15f, 8f, 4f }; private static readonly float[] PresetWindow = new float[4] { 3f, 3f, 3f, 2f }; private bool applyingPreset = false; private const int BindCount = 5; private int menuBind = 1; private int menuHand = 0; private int menuAccent = 0; private float menuSize = 1f; private float textSize = 1f; private bool haptics = true; private int touchSafety = 0; private static readonly string[] TouchNames = new string[2] { "Normal", "Strict" }; private MelonPreferences_Entry<bool> tutorialPref; private GameObject hintRoot; private TextMesh hintLine2; private string hintBind; private readonly List<Material> hintMats = new List<Material>(); private bool hintNotified; private const string TsNamespace = "FusionGuardTeam"; private bool checkUpdates = true; private volatile bool updBusy; private bool updAvailable; private bool updNotifyPending; private string updLatest; private string updStatus = "Not checked yet"; private MenuPage updPage; private static readonly string[] AccentNames = new string[6] { "Cyan", "Purple", "Green", "Orange", "Pink", "Rainbow" }; private static readonly Color[] AccentColors = (Color[])(object)new Color[5] { new Color(0.2f, 0.85f, 1f, 1f), new Color(0.66f, 0.45f, 1f, 1f), new Color(0.25f, 0.9f, 0.5f, 1f), new Color(1f, 0.6f, 0.2f, 1f), new Color(1f, 0.4f, 0.75f, 1f) }; private float aimHeadshots = 5f; private float aimDistance = 15f; private float silentShots = 4f; private float fireRateMargin = 50f; private float killAirPct = 50f; private float graceUntil; private const float GraceSeconds = 12f; private readonly Dictionary<byte, Queue<float>> recent = new Dictionary<byte, Queue<float>>(); private readonly Dictionary<byte, PlayerHold> holds = new Dictionary<byte, PlayerHold>(); private readonly Dictionary<string, string> blocked = new Dictionary<string, string>(); private readonly Dictionary<string, string> trusted = new Dictionary<string, string>(); private readonly Dictionary<string, string> fxBlocked = new Dictionary<string, string>(); private readonly Dictionary<byte, Queue<float>> recentFx = new Dictionary<byte, Queue<float>>(); private readonly Dictionary<byte, Queue<float>> recentAmmo = new Dictionary<byte, Queue<float>>(); private int fxDropped; private readonly Dictionary<string, bool> fxCache = new Dictionary<string, bool>(); private readonly Dictionary<string, bool> fxGuess = new Dictionary<string, bool>(); private readonly Dictionary<int, FxEntry> activeFx = new Dictionary<int, FxEntry>(); private readonly Queue<float> spawnFxTimes = new Queue<float>(); private int fxCapped; private readonly List<SecAlert> alerts = new List<SecAlert>(); private readonly Dictionary<byte, float> lastHeld = new Dictionary<byte, float>(); private readonly Dictionary<byte, List<float>> strikes = new Dictionary<byte, List<float>>(); private readonly Dictionary<string, string> damageAllow = new Dictionary<string, string>(); private readonly Dictionary<string, float> lastSecNotify = new Dictionary<string, float>(); private int dmgBlocked; private int kicksBlocked; private float heldTimer; private SecAlert autoOpenAlert; private readonly Dictionary<byte, GodTrack> godTrack = new Dictionary<byte, GodTrack>(); private readonly Dictionary<byte, Queue<float>> dmgRate = new Dictionary<byte, Queue<float>>(); private float godTimer; private float permTimer; private readonly Dictionary<byte, float> poseQuarantine = new Dictionary<byte, float>(); private readonly Dictionary<byte, float> downUntil = new Dictionary<byte, float>(); private readonly Dictionary<byte, List<float>> badPoseStrikes = new Dictionary<byte, List<float>>(); private readonly Dictionary<byte, List<float>> bigMsgStrikes = new Dictionary<byte, List<float>>(); private readonly Dictionary<byte, List<float>> gunStrikes = new Dictionary<byte, List<float>>(); private readonly Dictionary<byte, List<float>> slowMoStrikes = new Dictionary<byte, List<float>>(); private readonly Dictionary<byte, MsgCounter> msgCount = new Dictionary<byte, MsgCounter>(); private readonly Dictionary<string, int> cheatScore = new Dictionary<string, int>(); private int badPoses; private int floodDropped; private int remoteFireBlocked; private readonly Dictionary<byte, List<float>> hijackStrikes = new Dictionary<byte, List<float>>(); private readonly Dictionary<byte, List<float>> despawnStrikes = new Dictionary<byte, List<float>>(); private readonly Dictionary<byte, Queue<float>> avatarSwaps = new Dictionary<byte, Queue<float>>(); private int netBlocked; private int foreignDespawns; private readonly Dictionary<byte, float> lastDeath = new Dictionary<byte, float>(); private readonly Dictionary<byte, float> godFlagged = new Dictionary<byte, float>(); private readonly Dictionary<byte, float> hpFlagged = new Dictionary<byte, float>(); private int godAlerts; private const float HoldGrace = 6f; private int spawnFxSkipped; private float fxTimer; private static readonly string[] GunFxWords = new string[7] { "muzzle", "tracer", "tracers", "casing", "casings", "shellcasing", "brass" }; private static readonly string[] FxWords = new string[19] { "vfx", "fx", "particle", "particles", "smoke", "explosion", "explosions", "spark", "sparks", "effect", "effects", "firework", "fireworks", "confetti", "fog", "nuke", "blood", "splash", "flash" }; private readonly Queue<PendingSpawn> replayQueue = new Queue<PendingSpawn>(); private int blockedDropped; private bool holdsDirty; private float holdsRefreshTimer; private bool menuAutoOpened; private bool pendingAutoOpen; private PlayerHold autoOpenTarget; private readonly Dictionary<byte, List<ushort>> spawnedBy = new Dictionary<byte, List<ushort>>(); private readonly Dictionary<byte, int> spawnCount = new Dictionary<byte, int>(); private readonly List<string> spawnLog = new List<string>(); private readonly Dictionary<byte, float> lastWarn = new Dictionary<byte, float>(); private bool adminDirty = true; private float adminTimer; private string boneAdminSig = ""; private readonly List<GameObject> hiddenProps = new List<GameObject>(); private string confirmKey; private float confirmUntil; private string lastActiveScene; private static FieldInfo _discPlatF; private static FieldInfo _discReasonF; [ThreadStatic] private static string _eosPeer; [ThreadStatic] private static bool _eosFresh; [ThreadStatic] private static bool _eosNetDisconnect; [ThreadStatic] private static bool _eosServerHandled; [ThreadStatic] private static bool _eosNativeCheck; private static bool eosPatched; private static bool eosNativeOn; private bool antiSpoof = true; private int spoofBlocked; private readonly Dictionary<string, List<float>> spoofStrikes = new Dictionary<string, List<float>>(); private static FieldInfo _backupIdField; private readonly Dictionary<string, float> blockedPeers = new Dictionary<string, float>(); private readonly Dictionary<string, float> joinGrace = new Dictionary<string, float>(); private readonly Dictionary<string, float> peerCloseAt = new Dictionary<string, float>(); private readonly Dictionary<string, float> ghostLogAt = new Dictionary<string, float>(); private readonly Dictionary<string, int> ghostCount = new Dictionary<string, int>(); private static bool eosIdsMatch; private static FieldInfo _rcvP2P; private static FieldInfo _p2pPool; private static MethodInfo _poolReturn; private static bool _poolInit; private static FieldInfo _p2pLocalId; private static long _selfPackets; private static bool _selfLogged; private static PlatSetter _setPlat; private bool lockdown = false; private bool quarantineOn = true; private float quarantineSecs = 45f; private bool autoSanctions = true; private float sanctionBlockAt = 2f; private float sanctionKickAt = 3f; private float sanctionBanAt = 5f; private bool antiRejoin = true; private bool epicAccountCheck = true; private bool securityLogFile = true; private bool strongHaptics = true; private readonly Dictionary<byte, float> firstSeen = new Dictionary<byte, float>(); private float serverSeenAt = -1f; private readonly Dictionary<string, List<float>> kickHistory = new Dictionary<string, List<float>>(); private readonly Dictionary<string, float> tempBans = new Dictionary<string, float>(); private readonly Dictionary<string, List<float>> joinAttempts = new Dictionary<string, List<float>>(); private readonly Dictionary<string, int> sanctionDone = new Dictionary<string, int>(); private readonly HashSet<string> epicKicked = new HashSet<string>(); private readonly Dictionary<string, float> banKickAt = new Dictionary<string, float>(); private readonly Dictionary<string, int> voiceMute = new Dictionary<string, int>(); private int joinsDenied; private bool hapticPending; private float lastDenyNotify; private static readonly HashSet<string> SevereKinds = new HashSet<string> { "kickcheat", "spoof", "badpose", "flood", "hijack", "fakekick", "fakeperm", "remotefire", "damage", "faketp" }; private static readonly HashSet<string> ScoreKinds = new HashSet<string> { "kickcheat", "spoof", "fakekick", "fakeperm", "flood", "badpose", "remotefire", "nukespam" }; private readonly Dictionary<string, GuardBan> guardBans = new Dictionary<string, GuardBan>(); private string trustedSig = ""; private readonly Dictionary<byte, string> slotOwner = new Dictionary<byte, string>(); private static PropertyInfo _recvPlatProp; private bool muteAllNonStaff; private readonly Dictionary<byte, KeyValuePair<float, bool>> staffCache = new Dictionary<byte, KeyValuePair<float, bool>>(); private readonly Dictionary<string, float> lastNetCheat = new Dictionary<string, float>(); private readonly Dictionary<byte, float> cullSeen = new Dictionary<byte, float>(); private const float CullGrace = 3f; private readonly Dictionary<byte, float> disarmAt = new Dictionary<byte, float>(); private static bool shotWatchPatched; private int disarms; private const float PoseLimit = 100000f; private static FieldInfo _bodiesField; private static PropertyInfo _bodiesProp; private static bool _bodiesInit; private static FieldInfo _gunIdF; private static FieldInfo _gunF; private static FieldInfo _entF; private static FieldInfo _idF; private static bool _gunInit; private const string GuardKey = "FusionGuard"; private float guardTimer; private int guardTries; private readonly HashSet<byte> guardSeen = new HashSet<byte>(); internal const bool AdminBuild = false; private const string LobbyGuardKey = "FusionGuard"; private bool shareLobbyFg = true; private bool lobbyFgPatched; private string lobbyFgSig; private float nextLobbyFgWrite; private readonly List<LobbyRow> lobbyRows = new List<LobbyRow>(); private MenuPage lobbyPage; private bool lobbyBusy; private float lobbyReqAt; private float lobbyLoadedAt = -1f; private string lobbyStatus = "Open this page to load the lobby list"; private const string MegaKey = "FusionGuard.Mega"; private bool megaphone; private readonly Dictionary<byte, KeyValuePair<float, bool>> megaCache = new Dictionary<byte, KeyValuePair<float, bool>>(); private readonly HashSet<int> megaApplied = new HashSet<int>(); private static readonly Vector3 VanishSpot = new Vector3(0f, -4000f, 0f); private bool vanish; private bool vanishPatched; private readonly Dictionary<string, List<float>> crashSeconds = new Dictionary<string, List<float>>(); private readonly Dictionary<string, float> crashKickAt = new Dictionary<string, float>(); private readonly Dictionary<string, List<float>> nukeTries = new Dictionary<string, List<float>>(); private readonly Dictionary<string, List<float>> explosiveTries = new Dictionary<string, List<float>>(); private readonly Dictionary<string, float> spawnKickAt = new Dictionary<string, float>(); private readonly Dictionary<byte, float> shieldDrop = new Dictionary<byte, float>(); private readonly List<RecentSpawn> recentSpawns = new List<RecentSpawn>(); private bool netDebug = true; private float netSummarySecs = 10f; private readonly Dictionary<byte, NetStat> netStats = new Dictionary<byte, NetStat>(); private readonly Dictionary<byte, string> netRoster = new Dictionary<byte, string>(); private readonly Dictionary<string, float> netLineAt = new Dictionary<string, float>(); private readonly Dictionary<string, string> netMetaLast = new Dictionary<string, string>(); private float netSummaryTimer; private float netStatusTimer; private float netRosterTimer; [ThreadStatic] private static bool _fgDropped; private const byte NetNoSender = byte.MaxValue; private static readonly FieldInfo _discPlatF2 = typeof(DisconnectMessageData).GetField("PlatformID", BindingFlags.Instance | BindingFlags.Public); private static readonly FieldInfo _discReasonF2 = typeof(DisconnectMessageData).GetField("Reason", BindingFlags.Instance | BindingFlags.Public); private readonly Dictionary<byte, List<RecentShot>> recentShots = new Dictionary<byte, List<RecentShot>>(); private readonly Dictionary<ushort, GunTrack> gunTracks = new Dictionary<ushort, GunTrack>(); private readonly Dictionary<byte, LastShotInfo> lastShotBy = new Dictionary<byte, LastShotInfo>(); private readonly HashSet<byte> infAmmoPopped = new HashSet<byte>(); private readonly Dictionary<string, float> combatNotifyAt = new Dictionary<string, float>(); private readonly Dictionary<string, List<float>> combatStrikes = new Dictionary<string, List<float>>(); [ThreadStatic] private static bool _dmgCertain; private static FieldInfo _ammoF; private static bool _ammoInit; private static FieldInfo _gunIdxF; private static FieldInfo _gunIdxInner; private static bool _gunIdxInit; private static FieldInfo _magGunF; private static FieldInfo _magEjGunF; private static readonly Dictionary<int, bool> solidLayerCache = new Dictionary<int, bool>(); private static readonly string[] SoftLayerWords = new string[18] { "ignore", "nocollide", "trigger", "player", "ui", "water", "block", "clip", "nav", "invisible", "socket", "deciverse", "feet", "hand", "interactable", "ragdoll", "effect", "fx" }; private static readonly Handedness HandLeft = (Handedness)1; private readonly List<GrabOnMe> grabsOnMe = new List<GrabOnMe>(); private float flingWatchUntil; private float flingNotifyAt; private Rigidbody[] myRbs; private float myRbsAt; private readonly Dictionary<string, float> bannedJoinAt = new Dictionary<string, float>(); private const string DefaultWatchlist = "nyro,nyro.dll"; private const int WatchlistVersion = 2; private MelonPreferences_Entry<string> watchPref; private MelonPreferences_Entry<int> watchVer; private readonly Dictionary<byte, string> watchSeen = new Dictionary<byte, string>(); private readonly Dictionary<string, float> watchLobbyAt = new Dictionary<string, float>(); private readonly HashSet<string> knownAmmo = new HashSet<string>(); private readonly List<DmgSample>[] dmgSamples = new List<DmgSample>[2] { new List<DmgSample>(), new List<DmgSample>() }; private readonly Dictionary<byte, List<float>> shooterRatios = new Dictionary<byte, List<float>>(); private readonly Dictionary<byte, float> multFlagged = new Dictionary<byte, float>(); private readonly Dictionary<byte, FreezeState> frozen = new Dictionary<byte, FreezeState>(); [ThreadStatic] private static bool _freezeTp; private readonly Dictionary<byte, List<AimEval>> aimEvals = new Dictionary<byte, List<AimEval>>(); private int aimAlerts; private readonly Dictionary<byte, List<AimShot>> aimShots = new Dictionary<byte, List<AimShot>>(); private readonly Dictionary<byte, List<KeyValuePair<float, Vector3>>> holdAim = new Dictionary<byte, List<KeyValuePair<float, Vector3>>>(); private readonly Dictionary<byte, KeyValuePair<float, Vector3>> pelvisLast = new Dictionary<byte, KeyValuePair<float, Vector3>>(); private readonly Dictionary<byte, float> pelvisSpeed = new Dictionary<byte, float>(); private int aimLockAlerts; private readonly Dictionary<byte, List<float>> triggerTimes = new Dictionary<byte, List<float>>(); private readonly Dictionary<byte, List<float>> triggerStrikes = new Dictionary<byte, List<float>>(); private readonly Dictionary<byte, List<float>> tpTimes = new Dictionary<byte, List<float>>(); private readonly Dictionary<byte, List<float>> tpStrikes = new Dictionary<byte, List<float>>(); private readonly Dictionary<byte, List<float>> fakeTpStrikes = new Dictionary<byte, List<float>>(); private static readonly Regex LinkRegex = new Regex("(https?://|www\\.|discord\\.gg|discord\\.com/invite|\\b[a-z0-9-]{2,}\\.(com|net|org|gg|fun|xyz|io|ru|tk|ly|me|tv|site|online|shop)\\b)", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static bool vfxBroken; private static readonly string[] AmmoWords = new string[12] { "magazine", "magazines", "mag", "mags", "ammo", "clip", "clips", "shell", "shells", "cartridge", "battery", "cell" }; private readonly Dictionary<string, bool> ammoCache = new Dictionary<string, bool>(); private static readonly string[] DefaultBlockedItems = new string[8] { "!nuke", "missile", "explosion", "explosive", "bomb", "c4", "!void spawn", "!void orb" }; private static readonly string[] AllowedItemWords = new string[3] { "rpg", "launcher", "bazooka" }; private const int BlockedItemsVersion = 3; private readonly List<BlockedWord> blockedItems = new List<BlockedWord>(); private MelonPreferences_Entry<string> blockedItemsPref; private MelonPreferences_Entry<int> blockedItemsVer; private readonly Dictionary<string, string> crateText = new Dictionary<string, string>(); private readonly Dictionary<string, BlockedWord> itemMatch = new Dictionary<string, BlockedWord>(); private int itemsBlocked; private MenuPage itemsPage; private static readonly string[] ExplosiveWords = new string[17] { "explosive", "explosion", "grenade", "bomb", "c4", "missile", "rocket", "nuke", "mine", "landmine", "dynamite", "tnt", "claymore", "detonator", "frag", "molotov", "warhead" }; private readonly Dictionary<byte, ApprovalHold> approvals = new Dictionary<byte, ApprovalHold>(); private readonly Dictionary<string, string> explosiveTrusted = new Dictionary<string, string>(); private readonly Dictionary<string, string> explosiveBlocked = new Dictionary<string, string>(); private readonly Dictionary<string, bool> explosiveCache = new Dictionary<string, bool>(); private ApprovalHold autoOpenApproval; private int explosivesRefused; private const int MaxApprovalQueue = 30; private const float ApprovalTimeout = 90f; private static int mainThreadId = -1; private static readonly ConcurrentQueue<Action> mainQueue = new ConcurrentQueue<Action>(); private float nextMenuErr; private bool menuOpen = false; private bool lastCombo = false; private float menuAnim = 0f; private GameObject menuRoot; private GameObject pointerBall; private Renderer pointerRend; private MenuPage homePage; private MenuPage currentPage; private MenuPage pendingPage; private MenuPage playersPage; private MenuPage filterPage; private MenuPage fxPage; private MenuPage securityPage; private MenuPage netPage; private MenuPage toolsPage; private MenuPage settingsPage; private MenuPage watchPage; private readonly List<UiButton> uiButtons = new List<UiButton>(); private readonly List<Material> menuMats = new List<Material>(); private readonly List<Renderer> accentRends = new List<Renderer>(); private readonly List<TextMesh> accentTexts = new List<TextMesh>(); private Animator fingerAnim; private float nextFingerSearch; private Font menuFont; private Material textMat; private bool fontSearched = false; private bool pressLock = false; private UiButton armedBtn; private UiButton approachBtn; private float armedSince; private float approachTime; private float settleUntil; private const int HiddenLayer = 0; private static readonly Color CBg = new Color(0.05f, 0.055f, 0.07f, 1f); private static readonly Color CTop = new Color(0.075f, 0.082f, 0.104f, 1f); private static readonly Color CSide = new Color(0.068f, 0.075f, 0.096f, 1f); private static readonly Color CCard = new Color(0.108f, 0.118f, 0.15f, 1f); private static readonly Color CInfo = new Color(0.08f, 0.088f, 0.112f, 1f); private static readonly Color CChip = new Color(0.155f, 0.168f, 0.212f, 1f); private static readonly Color CTrack = new Color(0.215f, 0.228f, 0.275f, 1f); private static readonly Color COn = new Color(0.2f, 0.8f, 0.45f, 1f); private static readonly Color COff = new Color(0.3f, 0.32f, 0.38f, 1f); private static readonly Color CText = new Color(0.95f, 0.96f, 1f, 1f); private static readonly Color CTextDim = new Color(0.76f, 0.79f, 0.87f, 1f); private static readonly Color CSub = new Color(0.55f, 0.6f, 0.7f, 1f); private static readonly Color CGood = new Color(0.11f, 0.42f, 0.25f, 1f); private static readonly Color CDanger = new Color(0.5f, 0.12f, 0.15f, 1f); private static readonly Color CArmed = new Color(0.9f, 0.15f, 0.12f, 1f); private static readonly Color CWarn = new Color(1f, 0.78f, 0.3f, 1f); private static readonly Color CAlert = new Color(1f, 0.45f, 0.45f, 1f); private static readonly Color CHeader = CTop; private static readonly Color CRow = CCard; private static readonly Color CRowSoft = CInfo; private static readonly Color CTile = CCard; private static readonly Color CNav = CChip; private static readonly Color TLoad = new Color(0.13f, 0.5f, 0.3f, 1f); private static readonly Color TTrust = new Color(0.12f, 0.36f, 0.55f, 1f); private static readonly Color TRefuse = new Color(0.45f, 0.1f, 0.12f, 1f); private static readonly Color TBlock = new Color(0.3f, 0.05f, 0.06f, 1f); private static readonly Color TFrozen = new Color(0.1f, 0.32f, 0.72f, 1f); private static readonly Color KAlerts = new Color(1f, 0.56f, 0.26f, 1f); private static readonly Color KPlayers = new Color(0.38f, 0.66f, 1f, 1f); private static readonly Color KServer = new Color(0.68f, 0.52f, 1f, 1f); private static readonly Color KSpawns = new Color(1f, 0.8f, 0.3f, 1f); private static readonly Color KParticles = new Color(1f, 0.46f, 0.76f, 1f); private static readonly Color KCheat = new Color(1f, 0.36f, 0.4f, 1f); private static readonly Color KNetwork = new Color(0.3f, 0.86f, 0.76f, 1f); private static readonly Color KSettings = new Color(0.66f, 0.7f, 0.78f, 1f); private const float PW = 0.37f; private const float PH = 0.36f; private const float MW = 0.37f; private const float MH = 0.36f; private const float SideW = 0.082f; private const float CL = -0.087f; private const float CR = 0.175f; private const float CW = 0.262f; private const float CX = 0.044f; private const float RW = 0.262f; private const float RowH = 0.031f; private const float RowStep = 0.038f; private const int RowsPerPage = 6; private const float HitInset = 0.002f; private MenuPage serverPage; private readonly Dictionary<byte, TpBack> tpBack = new Dictionary<byte, TpBack>(); private MenuPage resumePage; private bool tutorialSessionDone; private float nextHintErr; private MenuPage lastDrawnPage; private bool lastArmedState; private Color drawCat; private static Shader menuShader; private static bool shaderSearched; private static readonly string[] ShaderNames = new string[5] { "Hidden/Internal-Colored", "Universal Render Pipeline/Unlit", "Unlit/Color", "Sprites/Default", "UI/Default" }; private Page bonePending; private Page bonePlayers; private Page boneTools; private MelonPreferences_Category stateCat; private readonly List<StateSlot> stateSlots = new List<StateSlot>(); private bool loadingState = false; private bool saveQueued; private float saveTimer; internal static bool IsQuest { get { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 if (_isQuest < 0) { try { _isQuest = (((int)Application.platform == 11) ? 1 : 0); } catch { _isQuest = ((Environment.OSVersion.Platform == PlatformID.Unix) ? 1 : 0); } } return true; } } internal static bool RealAndroid { get { _ = IsQuest; return _isQuest == 1; } } private static bool GuardOn => Instance != null && Instance.protection; private bool TutorialDone { get { try { return tutorialPref != null && tutorialPref.Value; } catch { return true; } } } private static string TsPackage => IsQuest ? "FusionGuard_Quest" : "FusionGuard"; private string BansPath => Path.Combine(GuardDir(), "bans.txt"); private string ImportPath => Path.Combine(GuardDir(), "import_bans.txt"); private string TrustedPath => Path.Combine(GuardDir(), "trusted.txt"); private bool ShieldActive => shieldMode && NetworkInfo.HasServer && !NetworkInfo.IsHost; private static bool OnMainThread => Thread.CurrentThread.ManagedThreadId == mainThreadId; private bool IsGunFx(string barcode) { string text = CrateWords(barcode); string[] gunFxWords = GunFxWords; foreach (string text2 in gunFxWords) { if (text.Contains(" " + text2 + " ")) { return true; } } return false; } public override void OnInitializeMelon() { Instance = this; mainThreadId = Thread.CurrentThread.ManagedThreadId; bool flag = true; try { if (MelonBase.RegisteredMelons.Any((MelonBase m) => m != null && (object)m != this && m.Info != null && m.Info.Name == "FusionGuard Admin")) { ((MelonBase)this).LoggerInstance.Error("FusionGuard Admin is also installed: this FusionGuard disables itself. Keep only one of the DLLs."); Instance = null; try { ((MelonBase)this).Unregister("FusionGuard Admin already installed", false); return; } catch { return; } } } catch { } try { if (MelonBase.RegisteredMelons.Any((MelonBase m) => m != null && m.Info != null && m.Info.Name == "FusionGuard")) { ((MelonBase)this).LoggerInstance.Error("FusionGuard (PC) is also installed: FusionGuard Quest disables itself. Keep only one of the two DLLs."); Instance = null; try { ((MelonBase)this).Unregister("FusionGuard (PC) already installed", false); return; } catch { return; } } } catch { } FusionCompat.Init(); if (!RealAndroid) { ((MelonBase)this).LoggerInstance.Warning("This build is made for Quest standalone. On PC, use FusionGuard (PC)."); } ((MelonBase)this).LoggerInstance.Msg("Fusion version detected: " + FusionCompat.Mode); ((MelonBase)this).LoggerInstance.Msg("Platform: " + (IsQuest ? "Quest standalone (Android / LemonLoader)" : "PC")); if (IsQuest) { maxActiveFx = 25f; spawnFxPerSec = 6f; } PatchFusion(); BuildPages(); LoadState(); LoadTrusted(); SetupBoneMenu(); try { MelonPreferences_Category val = MelonPreferences.CreateCategory("FusionGuard"); tutorialPref = val.CreateEntry<bool>("TutorialDone", false, (string)null, "true once the hand menu has been opened (hides the \"how to open\" hint)", false, false, (ValueValidator)null, (string)null); } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Warning("[Tutorial] " + ex.Message); } if (!IsQuest && checkUpdates) { CheckForUpdates(manual: false); } ((MelonBase)this).LoggerInstance.Msg("FusionGuard Quest 8.4.9 loaded. Hand menu: " + BindName() + " on the " + ((menuHand == 0) ? "left" : "right") + " hand"); } public override void OnSceneWasInitialized(int buildIndex, string sceneName) { //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) menuRoot = null; pointerBall = null; menuOpen = false; menuAnim = 0f; uiButtons.Clear(); menuMats.Clear(); DestroyHint(); hintRoot = null; fingerAnim = null; armedBtn = null; approachBtn = null; lastDrawnPage = null; accentRends.Clear(); accentTexts.Clear(); graceUntil = Time.realtimeSinceStartup + 12f; string text = sceneName ?? ""; try { Scene activeScene = SceneManager.GetActiveScene(); text = ((Scene)(ref activeScene)).name ?? text; } catch { } if (text != lastActiveScene) { lastActiveScene = text; try { ClearPending(); } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Warning("[Map] " + ex.Message); } } } public override void OnApplicationQuit() { try { SaveTrustedIfChanged(); } catch { } SaveState(); } private void PatchFusion() { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Expected O, but got Unknown //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Expected O, but got Unknown try { handleMethod = typeof(SpawnResponseMessage).GetMethod("OnHandleMessage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (handleMethod == null) { ((MelonBase)this).LoggerInstance.Error("SpawnResponseMessage.OnHandleMessage not found (different Fusion version?)"); return; } ((MelonBase)this).HarmonyInstance.Patch((MethodBase)handleMethod, new HarmonyMethod(typeof(Core).GetMethod("SpawnPrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).LoggerInstance.Msg("[Guard] patch spawn Fusion OK"); requestMethod = typeof(SpawnRequestMessage).GetMethod("OnHandleMessage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (requestMethod != null) { ((MelonBase)this).HarmonyInstance.Patch((MethodBase)requestMethod, new HarmonyMethod(typeof(Core).GetMethod("ServerSpawnPrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).LoggerInstance.Msg("[Guard] anti-spawn host OK"); } else { ((MelonBase)this).LoggerInstance.Warning("[Guard] SpawnRequestMessage.OnHandleMessage not found, host anti-spawn disabled"); } MethodInfo method = typeof(SpawnResponseMessage).GetMethod("OnSpawnFinished", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { ((MelonBase)this).HarmonyInstance.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(typeof(Core).GetMethod("SpawnFinishedPostfix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).LoggerInstance.Msg("[Guard] particle tracking OK"); } else { ((MelonBase)this).LoggerInstance.Warning("[Guard] SpawnResponseMessage.OnSpawnFinished not found, active particle limit disabled"); } } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Error("[Guard] Fusion patch failed: " + ex); } try { MethodInfo method2 = typeof(SpawnEffects).GetMethod("CallSpawnEffect", BindingFlags.Static | BindingFlags.Public); if (method2 != null) { ((MelonBase)this).HarmonyInstance.Patch((MethodBase)method2, new HarmonyMethod(typeof(Core).GetMethod("SpawnEffectPrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).LoggerInstance.Msg("[Guard] spawn effect limit OK"); } } catch (Exception ex2) { ((MelonBase)this).LoggerInstance.Error("[Guard] Fusion patch failed: " + ex2); } PatchSecurity(); } private void PatchSecurity() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Expected O, but got Unknown //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Expected O, but got Unknown //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Expected O, but got Unknown //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Expected O, but got Unknown //IL_03a6: Unknown result type (might be due to invalid IL or missing references) //IL_03b4: Expected O, but got Unknown //IL_03e7: Unknown result type (might be due to invalid IL or missing references) //IL_03f5: Expected O, but got Unknown //IL_0461: Unknown result type (might be due to invalid IL or missing references) //IL_0466: Unknown result type (might be due to invalid IL or missing references) //IL_047a: Expected O, but got Unknown //IL_04b3: Unknown result type (might be due to invalid IL or missing references) //IL_04c1: Expected O, but got Unknown //IL_04f4: Unknown result type (might be due to invalid IL or missing references) //IL_0502: Expected O, but got Unknown //IL_056a: Unknown result type (might be due to invalid IL or missing references) //IL_056f: Unknown result type (might be due to invalid IL or missing references) //IL_0578: Expected O, but got Unknown //IL_0741: Unknown result type (might be due to invalid IL or missing references) //IL_074e: Expected O, but got Unknown //IL_0782: Unknown result type (might be due to invalid IL or missing references) //IL_078f: Expected O, but got Unknown //IL_08a3: Unknown result type (might be due to invalid IL or missing references) //IL_08b1: Expected O, but got Unknown //IL_091d: Unknown result type (might be due to invalid IL or missing references) //IL_092b: Expected O, but got Unknown //IL_099b: Unknown result type (might be due to invalid IL or missing references) //IL_09a9: Expected O, but got Unknown //IL_0a19: Unknown result type (might be due to invalid IL or missing references) //IL_0a27: Expected O, but got Unknown //IL_060b: Unknown result type (might be due to invalid IL or missing references) //IL_0618: Expected O, but got Unknown //IL_06b3: Unknown result type (might be due to invalid IL or missing references) //IL_06c0: Expected O, but got Unknown //IL_080e: Unknown result type (might be due to invalid IL or missing references) //IL_081c: Expected O, but got Unknown //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Expected O, but got Unknown //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Expected O, but got Unknown try { MethodInfo method = typeof(PlayerRepDamageMessage).GetMethod("OnHandleMessage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); ((MelonBase)this).HarmonyInstance.Patch((MethodBase)method, new HarmonyMethod(typeof(Core).GetMethod("DamagePrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).LoggerInstance.Msg("[Security] cheat damage guard OK"); } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Warning("[Security] damage patch failed: " + ex.Message); } try { MethodInfo method2 = typeof(MessageHandler).GetMethod("OnPreRelayMessage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); ((MelonBase)this).HarmonyInstance.Patch((MethodBase)method2, new HarmonyMethod(typeof(Core).GetMethod("RelayPrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).LoggerInstance.Msg("[Security] host damage guard (relay) OK"); } catch (Exception ex2) { ((MelonBase)this).LoggerInstance.Warning("[Security] relay patch failed: " + ex2.Message); } try { MethodInfo method3 = typeof(DisconnectMessage).GetMethod("OnHandleMessage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); ((MelonBase)this).HarmonyInstance.Patch((MethodBase)method3, new HarmonyMethod(typeof(Core).GetMethod("DisconnectPrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).LoggerInstance.Msg("[Security] fake kick guard OK"); } catch (Exception ex3) { ((MelonBase)this).LoggerInstance.Warning("[Security] disconnect patch failed: " + ex3.Message); } try { MethodInfo methodInfo = typeof(PlayerSender).GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo x) => x.Name == "SendPlayerDamage" && x.GetParameters().Length == 3); if (methodInfo != null) { ((MelonBase)this).HarmonyInstance.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(Core).GetMethod("SendDamagePrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo method4 = typeof(PlayerRepActionMessage).GetMethod("OnHandleMessage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); ((MelonBase)this).HarmonyInstance.Patch((MethodBase)method4, new HarmonyMethod(typeof(Core).GetMethod("ActionPrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).LoggerInstance.Msg("[Security] god mode detector OK"); } catch (Exception ex4) { ((MelonBase)this).LoggerInstance.Warning("[Security] god mode patch failed: " + ex4.Message); } try { ((MelonBase)this).HarmonyInstance.Patch((MethodBase)typeof(EntityOwnershipRequestMessage).GetMethod("OnHandleMessage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), new HarmonyMethod(typeof(Core).GetMethod("OwnershipPrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).HarmonyInstance.Patch((MethodBase)typeof(DespawnRequestMessage).GetMethod("OnHandleMessage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), new HarmonyMethod(typeof(Core).GetMethod("DespawnRequestPrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).HarmonyInstance.Patch((MethodBase)typeof(PlayerRepAvatarMessage).GetMethod("OnHandleMessage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), new HarmonyMethod(typeof(Core).GetMethod("AvatarPrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).LoggerInstance.Msg("[Security] hijack / despawn / avatar spam guard OK"); } catch (Exception ex5) { ((MelonBase)this).LoggerInstance.Warning("[Security] entity patch failed: " + ex5.Message); } PatchEos(); PatchServer6(); PatchPoses(); try { ((MelonBase)this).HarmonyInstance.Patch((MethodBase)typeof(GunShotMessage).GetMethod("OnHandleMessage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), new HarmonyMethod(typeof(Core).GetMethod("GunShotPrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).HarmonyInstance.Patch((MethodBase)typeof(SlowMoButtonMessage).GetMethod("OnHandleMessage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), new HarmonyMethod(typeof(Core).GetMethod("SlowMoPrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).LoggerInstance.Msg("[Security] remote fire / forced slow-mo guard OK"); } catch (Exception ex6) { ((MelonBase)this).LoggerInstance.Warning("[Security] gun / slow-mo patch failed: " + ex6.Message); } try { ((MelonBase)this).HarmonyInstance.Patch((MethodBase)typeof(GunShotMessage).GetMethod("OnHandleMessage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), new HarmonyMethod(typeof(Core).GetMethod("ShotWatchPrefix", BindingFlags.Static | BindingFlags.NonPublic)) { priority = 200 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); shotWatchPatched = true; ((MelonBase)this).HarmonyInstance.Patch((MethodBase)typeof(MagazineInsertMessage).GetMethod("OnHandleMessage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), new HarmonyMethod(typeof(Core).GetMethod("MagInsertPrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).HarmonyInstance.Patch((MethodBase)typeof(MagazineEjectMessage).GetMethod("OnHandleMessage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), new HarmonyMethod(typeof(Core).GetMethod("MagEjectPrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).LoggerInstance.Msg("[Security] Combat Guard OK (warnings: modded guns, infinite ammo)"); } catch (Exception ex7) { ((MelonBase)this).LoggerInstance.Warning("[Security] Combat Guard patch failed: " + ex7.Message); } try { MethodInfo method5 = typeof(MessageHandler).GetMethod("StartHandlingMessage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); HarmonyMethod val = new HarmonyMethod(typeof(Core).GetMethod("NetStatPrefix", BindingFlags.Static | BindingFlags.NonPublic)) { priority = 0 }; ((MelonBase)this).HarmonyInstance.Patch((MethodBase)method5, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).LoggerInstance.Msg("[Security] network log [NET] OK"); } catch (Exception ex8) { ((MelonBase)this).LoggerInstance.Warning("[Security] network log patch failed: " + ex8.Message); } try { MethodInfo method6 = typeof(RigPose).GetMethod("ReadSkeleton", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method6 != null) { ((MelonBase)this).HarmonyInstance.Patch((MethodBase)method6, (HarmonyMethod)null, new HarmonyMethod(typeof(Core).GetMethod("VanishPosePostfix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); vanishPatched = true; ((MelonBase)this).LoggerInstance.Msg("[Security] vanish OK"); } else { ((MelonBase)this).LoggerInstance.Warning("[Security] RigPose.ReadSkeleton not found: vanish disabled"); } } catch (Exception ex9) { ((MelonBase)this).LoggerInstance.Warning("[Security] vanish patch failed: " + ex9.Message); } try { MethodInfo method7 = typeof(RigVoiceSource).GetMethod("UpdateVoiceSource", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method7 != null) { ((MelonBase)this).HarmonyInstance.Patch((MethodBase)method7, (HarmonyMethod)null, new HarmonyMethod(typeof(Core).GetMethod("VoiceRangePostfix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).LoggerInstance.Msg("[Security] megaphone OK"); } else { ((MelonBase)this).LoggerInstance.Warning("[Security] RigVoiceSource.UpdateVoiceSource not found: megaphone disabled"); } } catch (Exception ex10) { ((MelonBase)this).LoggerInstance.Warning("[Security] megaphone patch failed: " + ex10.Message); } try { ((MelonBase)this).HarmonyInstance.Patch((MethodBase)typeof(LobbyMetadataSerializer).GetMethod("ReadInfo", BindingFlags.Static | BindingFlags.Public), (HarmonyMethod)null, new HarmonyMethod(typeof(Core).GetMethod("LobbyInfoPostfix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).HarmonyInstance.Patch((MethodBase)typeof(PlayerSender).GetMethod("SendPlayerTeleport", BindingFlags.Static | BindingFlags.Public), (HarmonyMethod)null, new HarmonyMethod(typeof(Core).GetMethod("TeleportPostfix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).LoggerInstance.Msg("[Security] watchlist lobbies + freeze OK"); } catch (Exception ex11) { ((MelonBase)this).LoggerInstance.Warning("[Security] watchlist / freeze patch failed: " + ex11.Message); } try { MethodInfo method8 = typeof(LobbyMetadataInfo).GetMethod("Write", BindingFlags.Instance | BindingFlags.Public); if (method8 != null) { ((MelonBase)this).HarmonyInstance.Patch((MethodBase)method8, new HarmonyMethod(typeof(Core).GetMethod("LobbyWritePrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); lobbyFgPatched = true; ((MelonBase)this).LoggerInstance.Msg("[Security] FusionGuard info in the lobby list OK"); } else { ((MelonBase)this).LoggerInstance.Warning("[Security] LobbyMetadataInfo.Write not found: FG info in the lobby list disabled"); } } catch (Exception ex12) { ((MelonBase)this).LoggerInstance.Warning("[Security] lobby FG info patch failed: " + ex12.Message); } try { ((MelonBase)this).HarmonyInstance.Patch((MethodBase)typeof(GamemodeTriggerResponseMessage).GetMethod("OnHandleMessage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), new HarmonyMethod(typeof(Core).GetMethod("TriggerPrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).LoggerInstance.Msg("[Security] fake gamemode event guard OK"); } catch (Exception ex13) { ((MelonBase)this).LoggerInstance.Warning("[Security] gamemode patch failed: " + ex13.Message); } try { ((MelonBase)this).HarmonyInstance.Patch((MethodBase)typeof(PlayerRepTeleportMessage).GetMethod("OnHandleMessage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), new HarmonyMethod(typeof(Core).GetMethod("TeleportMsgPrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).LoggerInstance.Msg("[Security] fake teleport guard OK"); } catch (Exception ex14) { ((MelonBase)this).LoggerInstance.Warning("[Security] teleport patch failed: " + ex14.Message); } try { MethodInfo method9 = typeof(PlayerMetadataRequestMessage).GetMethod("OnHandleMessage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); ((MelonBase)this).HarmonyInstance.Patch((MethodBase)method9, new HarmonyMethod(typeof(Core).GetMethod("MetadataPrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).LoggerInstance.Msg("[Security] fake rank guard OK"); } catch (Exception ex15) { ((MelonBase)this).LoggerInstance.Warning("[Security] metadata patch failed: " + ex15.Message); } try { MethodInfo method10 = typeof(PermissionCommandRequestMessage).GetMethod("OnHandleMessage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); ((MelonBase)this).HarmonyInstance.Patch((MethodBase)method10, new HarmonyMethod(typeof(Core).GetMethod("PermCommandPrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).LoggerInstance.Msg("[Security] anti-kick host OK"); } catch (Exception ex16) { ((MelonBase)this).LoggerInstance.Warning("[Security] kick patch failed: " + ex16.Message); } } private static bool DamagePrefix(ReceivedMessage received) { //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) if (!GuardOn) { return true; } Core instance = Instance; if (instance == null || !((ReceivedMessage)(ref received)).Sender.HasValue) { return true; } try { byte value = ((ReceivedMessage)(ref received)).Sender.Value; if (value == PlayerIDManager.LocalSmallID) { return true; } if (NetworkInfo.IsHost && instance.IsFrozen(value)) { return false; } if (!instance.antiCheatDamage) { return true; } PlayerRepDamageData data = ((ReceivedMessage)(ref received)).ReadData<PlayerRepDamageData>(); if ((Object)(object)Player.Head == (Object)null) { return true; } Vector3 position = Player.Head.position; if (!instance.IsCheatDamage(value, data, position, PlayerIDManager.LocalSmallID, out var reason)) { return true; } instance.OnCheatDamage(value, PlayerIDManager.LocalSmallID, reason); return false; } catch (Exception ex) { ((MelonBase)instance).LoggerInstance.Warning("[Security] DamagePrefix : " + ex.Message); return true; } } private static bool RelayPrefix(MessageHandler __instance, ReceivedMessage received, ref bool __result) { //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) if (!GuardOn) { return true; } Core instance = Instance; if (instance == null || !((ReceivedMessage)(ref received)).Sender.HasValue || !NetworkInfo.IsHost) { return true; } byte value = ((ReceivedMessage)(ref received)).Sender.Value; if (instance.IsFrozen(value) && (__instance is PlayerRepDamageMessage || __instance is PlayerRepGrabMessage || __instance is SlowMoButtonMessage)) { __result = false; return false; } if (__instance is PlayerRepTeleportMessage && instance.antiFakeTp && value != PlayerIDManager.LocalSmallID) { instance.OnFakeTeleport(value); __result = false; return false; } try { if (!instance.CountMessage(value, received)) { __result = false; return false; } } catch { } if ((__instance is PlayerPoseUpdateMessage || __instance is EntityPoseUpdateMessage) && instance.poseQuarantine.TryGetValue(value, out var value2) && Time.realtimeSinceStartup < value2) { __result = false; return false; } if (__instance is PlayerVoiceChatMessage && instance.VoiceMutedForAll(value)) { __result = false; return false; } if (__instance is SlowMoButtonMessage && instance.antiSlowMo && !SlowMoAllowed(value)) { instance.OnBadSlowMo(value); __result = false; return false; } if (__instance is GamemodeTriggerResponseMessage) { string text = null; try { text = instance.BadTrigger(value, received); } catch { } if (text != null) { instance.OnBadTrigger(value, text); __result = false; return false; } } bool flag = __instance is PlayerRepDamageMessage; bool flag2 = !flag && __instance is PlayerRepAvatarMessage; if (!flag && !flag2 && !(__instance is PlayerRepActionMessage)) { return true; } try { byte b = value; if (flag2) { if (!instance.AvatarSpam(b)) { return true; } __result = false; return false; } if (!flag) { instance.OnPlayerAction(b, ((ReceivedMessage)(ref received)).ReadData<PlayerRepActionData>()); return true; } MessageRoute route = ((ReceivedMessage)(ref received)).Route; byte? target = ((MessageRoute)(ref route)).Target; if (!target.HasValue || target.Value == PlayerIDManager.LocalSmallID) { return true; } if (b == PlayerIDManager.LocalSmallID) { return true; } PlayerRepDamageData data = ((ReceivedMessage)(ref received)).ReadData<PlayerRepDamageData>(); if (instance.antiCheatDamage && instance.TryGetHead(target.Value, out var pos) && instance.IsCheatDamage(b, data, pos, target.Value, out var reason)) { instance.OnCheatDamage(b, target.Value, reason); __result = false; return false; } instance.RecordDamage(target.Value, data); return true; } catch (Exception ex) { ((MelonBase)instance).LoggerInstance.Warning("[Security] RelayPrefix : " + ex.Message); return true; } } private static void SendDamagePrefix(byte target, Attack attack) { if (!GuardOn) { return; } Core instance = Instance; if (instance == null || !instance.godDetect || attack == null) { return; } try { instance.RecordDamage(target, attack.damage); } catch { } } private static void ActionPrefix(ReceivedMessage received) { if (!GuardOn) { return; } Core instance = Instance; if (instance == null || !((ReceivedMessage)(ref received)).Sender.HasValue) { return; } try { instance.OnPlayerAction(((ReceivedMessage)(ref received)).Sender.Value, ((ReceivedMessage)(ref received)).ReadData<PlayerRepActionData>()); } catch { } } private static bool DisconnectPrefix(ReceivedMessage received) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) if (!GuardOn) { return true; } Core instance = Instance; if (instance == null) { return true; } if (!instance.antiFakeKick) { if (!NetworkInfo.IsHost) { instance.NotifyKickSeen(received); } return true; } if (NetworkInfo.IsHost) { if (!_eosNetDisconnect || ((ReceivedMessage)(ref received)).IsServerHandled) { return true; } _eosNetDisconnect = false; instance.kicksBlocked++; instance.AddLog("Fake kick sent to the host (" + (((ReceivedMessage)(ref received)).Sender.HasValue ? GetName(PlayerIDManager.GetPlayerID(((ReceivedMessage)(ref received)).Sender.Value), ((ReceivedMessage)(ref received)).Sender.Value) : "hidden sender") + "): blocked"); instance.SecNotify("hostkick", "/!\\ Someone tried to kick the host (fake message): blocked"); return false; } if (!((ReceivedMessage)(ref received)).Sender.HasValue) { instance.NotifyKickSeen(received); return true; } try { byte value = ((ReceivedMessage)(ref received)).Sender.Value; PlayerID playerID = PlayerIDManager.GetPlayerID(value); if (playerID != null && playerID.IsHost) { instance.NotifyKickSeen(received); return true; } instance.kicksBlocked++; instance.CrashHit(value, "fake kick"); string name = GetName(playerID, value); instance.AddLog(name + " sent a fake kick (blocked)"); instance.SecNotify("fake" + value, "/!\\ " + name + " tried to kick you (fake kick blocked)"); instance.RaiseAlert("fakekick", value, "Sent a fake kick (blocked)", null, ban: false); return false; } catch { return true; } } private void NotifyKickSeen(ReceivedMessage received) { if (!kickNotifs) { return; } try { DisconnectMessageData val = ((ReceivedMessage)(ref received)).ReadData<DisconnectMessageData>(); if (val == null) { return; } if (_discPlatF == null) { _discPlatF = typeof(DisconnectMessageData).GetField("PlatformID", BindingFlags.Instance | BindingFlags.Public); } if (_discReasonF == null) { _discReasonF = typeof(DisconnectMessageData).GetField("Reason", BindingFlags.Instance | BindingFlags.Public); } string text = _discPlatF?.GetValue(val)?.ToString(); string text2 = (_discReasonF?.GetValue(val) as string) ?? ""; if (string.IsNullOrEmpty(text) || text == "0") { return; } PlayerID val2 = PlayerByPlat(text); if (val2 != null && !val2.IsMe) { string text3 = text2.ToLowerInvariant(); bool flag = text3.Contains("ban"); if (flag || text3.Contains("kick")) { string name = GetName(val2, val2.SmallID); AddLog(name + (flag ? " was banned" : " was kicked") + " by the host (" + text2 + ")"); Notify(name + (flag ? " was banned from the server" : " was kicked from the server"), 3f); } } } catch { } } private static PermissionLevel LevelOf(PlayerID pid) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (pid == null) { return (PermissionLevel)0; } if (pid.IsHost) { return (PermissionLevel)2; } try { return FusionCompat.FetchPermission(FusionCompat.Plat(pid)); } catch { return (PermissionLevel)0; } } private static bool PermCommandPrefix(ReceivedMessage received) { //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Invalid comparison between Unknown and I4 //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Invalid comparison between Unknown and I4 //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Invalid comparison between Unknown and I4 //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) if (!GuardOn) { return true; } Core instance = Instance; if (instance == null || (!instance.antiKickServer && !instance.limitTeleports) || !NetworkInfo.IsHost || !((ReceivedMessage)(ref received)).Sender.HasValue) { return true; } try { PermissionCommandRequestData val = ((ReceivedMessage)(ref received)).ReadData<PermissionCommandRequestData>(); if (val == null) { return true; } byte value = ((ReceivedMessage)(ref received)).Sender.Value; if (value == PlayerIDManager.LocalSmallID) { return true; } if ((int)val.Type == 4) { string text = FusionCompat.Plat(PlayerIDManager.GetPlayerID(value)); if (!instance.limitTeleports || (FusionCompat.Has(text) && instance.trusted.ContainsKey(text)) || !instance.TeleportSpam(value)) { return true; } instance.tpBlocked++; instance.CrashHit(value, "TP spam"); if (instance.Strike(instance.tpStrikes, value, 3, 20f)) { instance.NetCheat(value, "tpspam", "TP spam on other players: blocked", "TP spam on players: blocked", "Teleport spam (TP others to him)"); } return false; } bool flag = (int)val.Type == 2; if (!flag && (int)val.Type != 1) { return true; } if (!instance.antiKickServer || !FusionCompat.PermsOk) { return true; } PlayerID playerID = PlayerIDManager.GetPlayerID(value); PlayerID val2 = (val.OtherPlayer.HasValue ? PlayerIDManager.GetPlayerID(val.OtherPlayer.Value) : null); string name = GetName(playerID, value); string text2 = (val.OtherPlayer.HasValue ? GetName(val2, val.OtherPlayer.Value) : "?"); string text3 = (flag ? "ban" : "kick"); PermissionLevel val3 = LevelOf(playerID); PermissionLevel val4 = (PermissionLevel)1; try { val4 = (flag ? LobbyInfoManager.LobbyInfo.Banning : LobbyInfoManager.LobbyInfo.Kicking); } catch { } PermissionLevel val5 = LevelOf(val2); string text4 = null; if (val2 == null) { text4 = "target not found"; } else if (val2.IsHost || val2.IsMe) { text4 = "target is the HOST"; } else if (val3 < val4) { text4 = "no permission (" + PermNames[PermIndex(val3)] + " < " + PermNames[PermIndex(val4)] + ")"; } else if (val5 >= val3) { text4 = "target has same or higher rank (" + PermNames[PermIndex(val5)] + ")"; } if (text4 == null && !instance.confirmOpKicks) { instance.AddLog(name + " (" + PermNames[PermIndex(val3)] + ") did " + text3 + " " + text2); instance.Notify(name + " used " + text3 + " on " + text2, 2.5f); return true; } instance.kicksBlocked++; if (text4 != null) { instance.CrashHit(value, "kick without perms"); } string reason = ((text4 == null) ? ("Wants to " + text3 + " " + text2 + " (has perms, needs your OK)") : ("Tried to " + text3 + " " + text2 + " : " + text4)); instance.AddLog(name + " : " + text3 + " " + text2 + " blocked" + ((text4 != null) ? (" (" + text4 + ")") : " (waiting for your OK)")); instance.SecNotify("kick" + value, "/!\\ " + name + " tried to " + text3 + " " + text2 + ((text4 != null) ? " without the right" : "") + ": blocked"); SecAlert secAlert = instance.RaiseAlert((text4 == null) ? "kick" : "kickcheat", value, reason, val.OtherPlayer, flag); secAlert.Allowed = text4 == null; return false; } catch (Exception ex) { ((MelonBase)instance).LoggerInstance.Warning("[Security] PermCommandPrefix : " + ex.Message); return true; } } private void BlockPeer(string plat, float secs) { if (FusionCompat.Has(plat)) { float num = Time.realtimeSinceStartup + secs; if (!blockedPeers.TryGetValue(plat, out var value) || value < num) { blockedPeers[plat] = num; } } } private bool PeerBlocked(string plat) { if (!FusionCompat.Has(plat)) { return false; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (guardBans.ContainsKey(plat)) { return true; } if (tempBans.TryGetValue(plat, out var value) && realtimeSinceStartup < value) { return true; } float value2; return blockedPeers.TryGetValue(plat, out value2) && realtimeSinceStartup < value2; } private void DropPeerPacket(string plat, string why) { ghostDropped++; float realtimeSinceStartup = Time.realtimeSinceStartup; if (!peerCloseAt.TryGetValue(plat, out var value) || realtimeSinceStartup - value > 2f) { peerCloseAt[plat] = realtimeSinceStartup; FusionCompat.CloseConnection(plat); } ghostCount.TryGetValue(plat, out var value2); value2 = (ghostCount[plat] = value2 + 1); if (value2 >= 10 && (!ghostLogAt.TryGetValue(plat, out var value3) || realtimeSinceStartup - value3 > 30f)) { ghostLogAt[plat] = realtimeSinceStartup; ghostCount[plat] = 0; AddLog("Packets from a player not in the server (" + why + "): dropped + connection closed"); SecLog("GHOST [" + plat + "] : " + why); } } private static PlayerID PlayerByPlat(string plat) { if (string.IsNullOrEmpty(plat)) { return null; } foreach (PlayerID item in PlayerIDManager.PlayerIDs.ToList()) { if (item != null && FusionCompat.Plat(item) == plat) { return item; } } return null; } private static string MyPlat() { foreach (PlayerID item in PlayerIDManager.PlayerIDs.ToList()) { if (item != null && item.IsMe) { return FusionCompat.Plat(item); } } return null; } private static string HostPlat() { foreach (PlayerID item in PlayerIDManager.PlayerIDs.ToList()) { if (item != null && item.IsHost) { return FusionCompat.Plat(item); } } return null; } private void OnSpoof(string peer, string what) { spoofBlocked++; PlayerID val = PlayerByPlat(peer); if (val != null) { CrashHit(val.SmallID, "spoofing"); } string text = peer ?? "?"; if (!spoofStrikes.TryGetValue(text, out var value)) { value = new List<float>(); spoofStrikes[text] = value; } float now = Time.realtimeSinceStartup; value.Add(now); value.RemoveAll((float x) => now - x > 10f); if (value.Count == 2) { if (val != null) { NetCheat(val.SmallID, "spoof", what + ": blocked", what + " (Epic exploit): blocked", what); return; } AddLog("Forged packet from an unknown sender (" + text + "): " + what + ": blocked"); } } private static bool EosProcessPrefix(object __instance, object[] __args) { if (!GuardOn) { return true; } bool flag = EosProcessCheck(__instance, __args); if (!flag) { ReturnEosBuffer(__instance, __args); } return flag; } private static void ReturnEosBuffer(object receiver, object[] args) { try { if (receiver != null && args != null && args.Length != 0 && args[0] is byte[] array) { if (!_poolInit) { _poolInit = true; _rcvP2P = receiver.GetType().GetField("P2P", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _p2pPool = _rcvP2P?.FieldType.GetField("BufferPool", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _poolReturn = _p2pPool?.FieldType.GetMethod("Return", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(byte[]) }, null); } object obj = _rcvP2P?.GetValue(receiver); object obj2 = ((obj == null) ? null : _p2pPool?.GetValue(obj)); if (obj2 != null) { _poolReturn?.Invoke(obj2, new object[1] { array }); } } } catch { } } private static string LocalEosId(object receiver) { try { if (receiver == null) { return null; } if (_rcvP2P == null) { _rcvP2P = receiver.GetType().GetField("P2P", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } object obj = _rcvP2P?.GetValue(receiver); if (obj == null) { return null; } if (_p2pLocalId == null) { _p2pLocalId = obj.GetType().GetField("LocalUserId", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } return _p2pLocalId?.GetValue(obj)?.ToString(); } catch { return null; } } private static bool EosProcessCheck(object receiver, object[] __args) { _eosPeer = null; _eosNetDisconnect = false; _eosNativeCheck = false; Core instance = Instance; try { _eosPeer = __args[2]?.ToString(); object obj = __args[3]; bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } _eosServerHandled = (byte)((uint)num & (flag ? 1u : 0u)) != 0; _eosFresh = true; if (instance == null || !NetworkInfo.HasServer) { return true; } string text = LocalEosId(receiver); if (string.IsNullOrEmpty(text)) { text = MyPlat(); } if (!string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(_eosPeer) && _eosPeer == text) { _eosPeer = null; _eosFresh = false; _selfPackets++; if (!_selfLogged && NetworkInfo.IsHost) { _selfLogged = true; ((MelonBase)instance).LoggerInstance.Msg("[Epic] host: your own Epic packets (the copies Fusion handles for you) are let through: OK"); } return true; } bool flag2 = instance.antiSpoof || instance.antiFakeKick || instance.antiKickServer; if (NetworkInfo.IsHost) { if (instance.antiSpoof && instance.PeerBlocked(_eosPeer)) { instance.DropPeerPacket(_eosPeer, "kicked / banned"); return false; } if (flag2 && !_eosServerHandled) { instance.OnSpoof(_eosPeer, "Sent a fake 'server' message to the host"); return false; } } else if (flag2) { if (_eosServerHandled) { instance.OnSpoof(_eosPeer, "Sent a fake 'server' packet to you"); return false; } string text2 = HostPlat(); if (!string.IsNullOrEmpty(text2) && !string.IsNullOrEmpty(_eosPeer) && _eosPeer != text2) { instance.OnSpoof(_eosPeer, "Sent you a packet directly (not through the host)"); return false; } } } catch { } return true; } private static void EosProcessPostfix() { _eosPeer = null; _eosFresh = false; _eosNetDisconnect = false; _eosNativeCheck = false; } private static void BuildPlatSetter() { try { Type typeFromHandle = typeof(ReadableMessage); MethodInfo methodInfo = typeFromHandle.GetProperty("PlatformID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetSetMethod(nonPublic: true); if (!(methodInfo == null) && methodInfo.GetParameters().Length == 1 && !(methodInfo.GetParameters()[0].ParameterType != typeof(string))) { DynamicMethod dynamicMethod = new DynamicMethod("FG_FillRealSenderId", typeof(void), new Type[2] { typeFromHandle.MakeByRefType(), typeof(string) }, typeof(Core).Module, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldarg_1); iLGenerator.Emit(OpCodes.Call, methodInfo); iLGenerator.Emit(OpCodes.Ret); _setPlat = (PlatSetter)dynamicMethod.CreateDelegate(typeof(PlatSetter)); } } catch (Exception ex) { _setPlat = null; Core instance = Instance; if (instance != null) { ((MelonBase)instance).LoggerInstance.Warning("[Security] setter PlatformID : " + ex.Message); } } } private static void ReadMessagePrefix(ref ReadableMessage __0) { if (!GuardOn) { return; } _eosNativeCheck = false; Core instance = Instance; if (instance == null || !instance.antiSpoof || _setPlat == null || !_eosFresh || string.IsNullOrEmpty(_eosPeer) || !NetworkInfo.IsHost) { return; } try { if (((ReadableMessage)(ref __0)).IsServerHandled && PlayerByPlat(_eosPeer) != null) { _setPlat(ref __0, _eosPeer); _eosNativeCheck = true; } } catch { } } private static void ReadMessagePostfix() { _eosNativeCheck = false; } private static void NativeDisconnectPrefix(object __0) { if (!GuardOn || !_eosNativeCheck) { return; } Core instance = Instance; if (instance == null) { return; } try { string text = __0?.ToString(); if (!string.IsNullOrEmpty(text) && !(text != _eosPeer)) { _eosNativeCheck = false; instance.spoofBlocked++; instance.BlockPeer(text, 60f); PlayerID val = PlayerByPlat(text); string text2 = ((val != null) ? GetName(val, val.SmallID) : text); instance.AddLog(text2 + " pretended to be another player: disconnected by Fusion (check re-enabled)"); instance.SecNotify("spoofnative" + text, "/!\\ " + text2 + " tried to pretend to be another player: disconnected"); instance.SecLog("SPOOF (native) [" + text + "] → disconnected"); if (val != null) { instance.RaiseAlert("spoof", val.SmallID, "Pretended to be another player (disconnected)", null, ban: false); } } } catch { } } private static bool EosIncomingPrefix(object[] __args) { if (!GuardOn) { return true; } Core instance = Instance; if (instance == null || !instance.antiSpoof || __args == null || __args.Length == 0) { return true; } try { object obj = __args[0]; string text = obj?.GetType().GetProperty("RemoteUserId")?.GetValue(obj)?.ToString(); if (string.IsNullOrEmpty(text) || !instance.PeerBlocked(text)) { return true; } instance.ghostDropped++; if (instance.guardBans.TryGetValue(text, out var value)) { instance.WarnBannedJoin(text, value.Name, "P2P refused"); } if (!instance.ghostLogAt.TryGetValue(text, out var value2) || Time.realtimeSinceStartup - value2 > 30f) { instance.ghostLogAt[text] = Time.realtimeSinceStartup; instance.AddLog("P2P connection refused (banned / recently kicked) [" + text + "]"); } return false; } catch { return true; } } private static bool StartHandlingPrefix(MessageHandler __instance, ReceivedMessage received) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (!GuardOn) { _fgDropped = false; return true; } bool flag = StartHandlingCheck(__instance, received); _fgDropped = !flag; return flag; } private static bool StartHandlingCheck(MessageHandler __instance, ReceivedMessage received) { Core instance = Instance; _eosNativeCheck = false; string eosPeer = _eosPeer; if (eosPeer == null || !_eosFresh) { _eosNetDisconnect = false; return true; } _eosFresh = false; _eosNetDisconnect = __instance is DisconnectMessage; if (instance == null || !instance.antiSpoof || !NetworkInfo.IsHost || !((ReceivedMessage)(ref received)).IsServerHandled) { return true; } try { if (__instance is ConnectionRequestMessage) { instance.joinGrace[eosPeer] = Time.realtimeSinceStartup; if (_backupIdField == null) { _backupIdField = typeof(ConnectionRequestData).GetField("BackupPlatformID", BindingFlags.Instance | BindingFlags.Public); } ConnectionRequestData obj = ((ReceivedMessage)(ref received)).ReadData<ConnectionRequestData>(); string text = _backupIdField?.GetValue(obj)?.ToString(); if (!string.IsNullOrEmpty(text) && text != eosPeer) { instance.spoofBlocked++; instance.AddLog("Connection refused: a player pretended to be " + text + " (real ID " + eosPeer + ")"); instance.Notify("/!\\ Someone tried to join with another player's ID (perm theft / ban evasion): blocked", 4f); return false; } return true; } PlayerID val = PlayerByPlat(eosPeer); if (val != null) { eosIdsMatch = true;