Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Trippy v1.0.0
Trippy.dll
Decompiled 8 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Trippy")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+3408f12aa5db26b88198b5a801f5d0a0a1e671c5")] [assembly: AssemblyProduct("Trippy")] [assembly: AssemblyTitle("Trippy")] [assembly: AssemblyVersion("1.0.0.0")] [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 Trippy { internal static class InputGuard { private static readonly Type? ChatManagerType = AccessTools.TypeByName("ChatManager"); private static readonly Func<object?, object?>? GetInstance = MemberGetter(ChatManagerType, "instance"); private static readonly Func<object?, object?>? GetChatActive = MemberGetter(ChatManagerType, "chatActive"); private static readonly Func<object?, object?>? GetChatState = MemberGetter(ChatManagerType, "chatState"); public static bool Available { get { if (GetInstance != null) { if (GetChatActive == null) { return GetChatState != null; } return true; } return false; } } public static bool IsTyping() { if (!Available) { return false; } try { object obj = GetInstance(null); if (obj == null) { return false; } if (GetChatActive != null) { object obj2 = GetChatActive(obj); bool flag = default(bool); int num; if (obj2 is bool) { flag = (bool)obj2; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } object obj3 = GetChatState(obj); return obj3 != null && Convert.ToInt32(obj3) != 0; } catch (Exception) { return false; } } private static Func<object?, object?>? MemberGetter(Type? type, string name) { if (type == null) { return null; } FieldInfo field = AccessTools.Field(type, name); if (field != null) { return (object? instance) => field.GetValue(instance); } MethodInfo getter = AccessTools.Property(type, name)?.GetGetMethod(nonPublic: true); if (getter != null) { return (object? instance) => getter.Invoke(instance, null); } return null; } } internal sealed class KeyCombo { private readonly Key _key; private readonly Key[][] _modifiers; private static readonly Dictionary<string, Key[]> ModifierAliases = new Dictionary<string, Key[]>(StringComparer.OrdinalIgnoreCase) { ["ctrl"] = (Key[])(object)new Key[2] { (Key)55, (Key)56 }, ["control"] = (Key[])(object)new Key[2] { (Key)55, (Key)56 }, ["shift"] = (Key[])(object)new Key[2] { (Key)51, (Key)52 }, ["alt"] = (Key[])(object)new Key[2] { (Key)53, (Key)54 } }; private KeyCombo(Key key, Key[][] modifiers) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) _key = key; _modifiers = modifiers; } public static bool TryParse(string? value, out KeyCombo combo, out string error) { //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected I4, but got Unknown combo = null; error = ""; string[] array = (from p in (value ?? "").Split(new char[1] { '+' }, StringSplitOptions.RemoveEmptyEntries) select p.Trim() into p where p.Length > 0 select p).ToArray(); if (array.Length == 0) { error = "no key name given"; return false; } List<Key[]> list = new List<Key[]>(); for (int num = 0; num < array.Length - 1; num++) { if (ModifierAliases.TryGetValue(array[num], out Key[] value2)) { list.Add(value2); continue; } if (Enum.TryParse<Key>(array[num], ignoreCase: true, out Key result) && (int)result != 0) { list.Add((Key[])(object)new Key[1] { (Key)(int)result }); continue; } error = "'" + array[num] + "' is not a modifier (Ctrl/Shift/Alt) or a UnityEngine.InputSystem.Key name"; return false; } string text = array[^1]; if (!Enum.TryParse<Key>(text, ignoreCase: true, out Key result2) || (int)result2 == 0) { error = "'" + text + "' is not a UnityEngine.InputSystem.Key name"; return false; } combo = new KeyCombo(result2, list.ToArray()); return true; } public bool WasPressedThisFrame(Keyboard keyboard) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!((ButtonControl)keyboard[_key]).wasPressedThisFrame) { return false; } Key[][] modifiers = _modifiers; for (int i = 0; i < modifiers.Length; i++) { if (!modifiers[i].Any((Key k) => ((ButtonControl)keyboard[k]).isPressed)) { return false; } } return true; } public override string ToString() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) return string.Join("+", _modifiers.Select((Key[] m) => ((object)Unsafe.As<Key, Key>(ref m[0])/*cast due to .constrained prefix*/).ToString()).Append(((object)_key/*cast due to .constrained prefix*/).ToString())); } } internal static class PlayerReflection { private static readonly FieldInfo? TumbleField = AccessTools.Field(typeof(PlayerAvatar), "tumble"); private static readonly FieldInfo? IsTumblingField = AccessTools.Field(typeof(PlayerAvatar), "isTumbling"); private static readonly FieldInfo? DeadSetField = AccessTools.Field(typeof(PlayerAvatar), "deadSet"); public static bool Ready { get { if (TumbleField != null && IsTumblingField != null) { return DeadSetField != null; } return false; } } public static PlayerTumble? GetTumble(PlayerAvatar avatar) { object? obj = TumbleField?.GetValue(avatar); return (PlayerTumble?)((obj is PlayerTumble) ? obj : null); } public static bool IsTumbling(PlayerAvatar avatar) { if (IsTumblingField != null) { return (bool)IsTumblingField.GetValue(avatar); } return false; } public static bool IsDead(PlayerAvatar avatar) { if (DeadSetField != null) { return (bool)DeadSetField.GetValue(avatar); } return false; } } [BepInPlugin("Trippy", "Trippy", "1.0.0")] public class Plugin : BaseUnityPlugin { private const string DefaultTripKey = "G"; internal static ManualLogSource Log; internal static ConfigEntry<string> TripKeyName; internal static ConfigEntry<float> Range; internal static ConfigEntry<float> Cooldown; internal static ConfigEntry<bool> IncludeSelf; internal static ConfigEntry<bool> IgnoreWhileTyping; private KeyCombo _tripKey; private float _cooldownTimer; private void Awake() { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; TripKeyName = ((BaseUnityPlugin)this).Config.Bind<string>("General", "TripKey", "G", "Key that trips nearby players. Any UnityEngine.InputSystem.Key name (e.g. G, Semicolon, F9), optionally with modifiers (e.g. Ctrl+G, LeftAlt+Shift+T). Applies as soon as it's changed - no restart needed."); Range = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Range", 6f, new ConfigDescription("How far from you (in meters) other players get tripped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 25f), Array.Empty<object>())); Cooldown = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Cooldown", 1.5f, new ConfigDescription("Minimum seconds between trips, so holding/mashing the key doesn't spam RPCs.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>())); IncludeSelf = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "IncludeSelf", false, "If true, you also trip yourself along with anyone nearby."); IgnoreWhileTyping = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "IgnoreWhileTyping", true, "If true, the trip key does nothing while the in-game chat box is open, so typing a message can't trip the lobby."); ApplyTripKey(); TripKeyName.SettingChanged += delegate { ApplyTripKey(); }; if (IgnoreWhileTyping.Value && !InputGuard.Available) { Log.LogWarning((object)"Couldn't find the game's ChatManager, so IgnoreWhileTyping can't do anything - the trip key will also fire while typing in chat. Bind TripKey to a function key or a modifier combo if that's a problem."); } if (!PlayerReflection.Ready) { Log.LogWarning((object)"PlayerAvatar's tumble/isTumbling/deadSet fields weren't found; a game update likely renamed them. Trippy will stay loaded but do nothing."); } Log.LogInfo((object)string.Format("{0} {1} loaded. Press {2} to trip nearby players.", "Trippy", "1.0.0", _tripKey)); } private void ApplyTripKey() { if (KeyCombo.TryParse(TripKeyName.Value, out KeyCombo combo, out string error)) { _tripKey = combo; } else if (_tripKey == null) { KeyCombo.TryParse("G", out _tripKey, out string _); Log.LogWarning((object)$"Invalid TripKey '{TripKeyName.Value}' ({error}); using {_tripKey} instead."); } else { Log.LogWarning((object)$"Invalid TripKey '{TripKeyName.Value}' ({error}); keeping {_tripKey}."); } } private void Update() { if (_cooldownTimer > 0f) { _cooldownTimer -= Time.deltaTime; return; } Keyboard current = Keyboard.current; if (current != null && _tripKey != null && _tripKey.WasPressedThisFrame(current) && (!IgnoreWhileTyping.Value || !InputGuard.IsTyping())) { int num = TripAction.TripNearby(Range.Value, IncludeSelf.Value); _cooldownTimer = Cooldown.Value; if (num > 0) { Log.LogInfo((object)$"Tripped {num} nearby player(s)."); } } } } internal static class TripAction { public static int TripNearby(float range, bool includeSelf) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (!PlayerReflection.Ready) { return 0; } PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); if ((Object)(object)val == (Object)null) { return 0; } List<PlayerAvatar> list = SemiFunc.PlayerGetAllPlayerAvatarWithinRange(range, ((Component)val).transform.position, false, default(LayerMask)); int num = 0; foreach (PlayerAvatar item in list) { if (!((Object)(object)item == (Object)null) && (!((Object)(object)item == (Object)(object)val) || includeSelf) && !PlayerReflection.IsDead(item) && !PlayerReflection.IsTumbling(item)) { PlayerTumble tumble = PlayerReflection.GetTumble(item); if (!((Object)(object)tumble == (Object)null)) { tumble.TumbleRequest(true, false); num++; } } } return num; } } public static class MyPluginInfo { public const string PLUGIN_GUID = "Trippy"; public const string PLUGIN_NAME = "Trippy"; public const string PLUGIN_VERSION = "1.0.0"; } }