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 AntiItemTeleport v1.1.0
BepInEx/plugins/RepoAntiItemTeleport.dll
Decompiled 7 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using AntiItemTeleport.Core; using AntiItemTeleport.Patches; using BepInEx; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.SceneManagement; [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("RepoAntiItemTeleport")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("2.6.0.0")] [assembly: AssemblyInformationalVersion("2.6.0")] [assembly: AssemblyProduct("Anti Item Teleport")] [assembly: AssemblyTitle("RepoAntiItemTeleport")] [assembly: AssemblyVersion("2.6.0.0")] namespace AntiItemTeleport { [BepInPlugin("com.sunwu.anti_Item_teleport", "Anti Item Teleport", "1.0.0")] public sealed class Plugin : BaseUnityPlugin { internal static ManualLogSource Log; private void Awake() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; PatchInstaller.InstallAll(new Harmony("com.sunwu.anti_Item_teleport")); SceneManager.sceneLoaded += delegate { PatchInstaller.TryInstallDispatchGuard(); }; Log.LogInfo((object)"Anti Item Teleport 1.0.0 ready - clients cannot change object positions (enforced on the host only)."); } private void Update() { PatchInstaller.TryInstallDispatchGuard(); } } internal static class PluginInfo { internal const string Guid = "com.sunwu.anti_Item_teleport"; internal const string Name = "Anti Item Teleport"; internal const string Version = "1.0.0"; } } namespace AntiItemTeleport.Patches { internal static class GumballRosterFix { private static bool _resolved; private static bool _ready; private static FieldRef<GumballValuable, List<GameObject>> _hypnosisLines; private static FieldRef<GumballValuable, List<bool>> _playerInSight; private static FieldRef<GumballValuable, List<bool>> _previouslySeen; internal static bool Resolve() { if (_resolved) { return _ready; } _resolved = true; try { _hypnosisLines = AccessTools.FieldRefAccess<GumballValuable, List<GameObject>>("hypnosisLines"); _playerInSight = AccessTools.FieldRefAccess<GumballValuable, List<bool>>("playerInSight"); _previouslySeen = AccessTools.FieldRefAccess<GumballValuable, List<bool>>("previouslySeenList"); _ready = true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("GumballValuable internal fields not found, disabling the gumball fix: " + ex.Message)); } return _ready; } internal static bool Prefix(GumballValuable __instance) { if ((Object)(object)__instance == (Object)null) { return true; } try { List<PlayerAvatar> list = SemiFunc.PlayerGetList(); List<GameObject> list2 = _hypnosisLines.Invoke(__instance); if (list == null || list2 == null) { return true; } int count = list.Count; if (count <= list2.Count) { return true; } Grow(_playerInSight.Invoke(__instance), count); Grow(_previouslySeen.Invoke(__instance), count); while (list2.Count < count) { GameObject val = CreateHypnosisLine(__instance, list[list2.Count]); if ((Object)(object)val == (Object)null) { GuardLog.Warn("gumball", $"[Gumball] Could not create a hypnosis line (need {count}, have {list2.Count})." + " Skipping the roster update."); return false; } list2.Add(val); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Gumball list repair failed, skipping this frame: " + ex.Message)); return false; } return true; } private static void Grow(List<bool> list, int need) { if (list != null) { while (list.Count < need) { list.Add(item: false); } } } private static GameObject CreateHypnosisLine(GumballValuable gumball, PlayerAvatar player) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)gumball.hypnosisLine == (Object)null || (Object)(object)player == (Object)null || (Object)(object)player.localCamera == (Object)null) { return null; } Transform overrideTransform = player.localCamera.GetOverrideTransform(); if ((Object)(object)overrideTransform == (Object)null) { return null; } GameObject val = Object.Instantiate<GameObject>(gumball.hypnosisLine, ((Component)gumball).transform.position, Quaternion.identity); if ((Object)(object)val == (Object)null) { return null; } val.transform.SetParent(overrideTransform); val.transform.localPosition = Vector3.zero; val.transform.localRotation = Quaternion.identity; EyeLines component = val.GetComponent<EyeLines>(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val); return null; } component.InitializeLine(player); val.transform.SetParent(gumball.HypnosisLinesParenTransform); val.SetActive(false); return val; } } internal static class RpcDispatchGuard { private const string TargetMethod = "SetPositionRPC"; private static readonly object KeyViewId = (byte)0; private static readonly object KeyMethodName = (byte)3; private static readonly object KeyParameters = (byte)4; private static readonly object KeyRpcIndex = (byte)5; internal static bool ShouldDrop(Hashtable rpcData, Player sender) { if (rpcData == null) { return false; } if (sender != null && sender == PhotonNetwork.LocalPlayer) { return false; } if (!RunGate.HostInGame) { return false; } try { if (ResolveMethodName(rpcData) != "SetPositionRPC") { return false; } PhotonView val = FindView(rpcData); string text = (((Object)(object)val != (Object)null) ? $"{((Object)val).name} (View {val.ViewID})" : "(unknown)"); GuardLog.Warn("drop", "[Blocked] Dropped a client object position request | target: " + text + " | position: " + DescribePosition(rpcData) + " | from: " + RpcOrigin.DescribeSender(sender)); if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).GetComponent<ValuableObject>() != (Object)null) { CheatReport.Broadcast(sender, ((Object)val).name); } return true; } catch (Exception ex) { GuardLog.Warn("dispatch-error", "Error while screening an inbound RPC, letting it through: " + ex.Message); return false; } } private static string ResolveMethodName(Hashtable rpcData) { if (!((Dictionary<object, object>)(object)rpcData).ContainsKey(KeyRpcIndex)) { return rpcData[KeyMethodName] as string; } int num = (short)rpcData[KeyRpcIndex]; List<string> rpcList = PhotonNetwork.PhotonServerSettings.RpcList; if (rpcList == null || num < 0 || num >= rpcList.Count) { return null; } return rpcList[num]; } private static PhotonView FindView(Hashtable rpcData) { object obj = (((Dictionary<object, object>)(object)rpcData).ContainsKey(KeyViewId) ? rpcData[KeyViewId] : null); int num = ((obj is int) ? ((int)obj) : 0); if (num == 0) { return null; } try { return PhotonView.Find(num); } catch { return null; } } private static string DescribePosition(Hashtable rpcData) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) object[] array = (((Dictionary<object, object>)(object)rpcData).ContainsKey(KeyParameters) ? (rpcData[KeyParameters] as object[]) : null); if (array == null || array.Length < 1 || !(array[0] is Vector3)) { return "(unknown)"; } return ((object)(Vector3)array[0]/*cast due to .constrained prefix*/).ToString(); } } internal static class SetPositionRpcGuard { internal static bool Prefix(PhysGrabObject __instance, Vector3 __0) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) if (!RunGate.HostInGame) { return true; } if (TeleportOrigin.InLocalCall) { return true; } if (RpcOrigin.Available && !RpcOrigin.InDispatch) { return true; } string text = (((Object)(object)__instance != (Object)null) ? ((Object)__instance).name : "(unknown)"); GuardLog.Warn("deny", "[Blocked] Refused a client object position request | target: " + text + $" | position: {__0}" + " | from: " + RpcOrigin.DescribeSender()); return false; } } internal static class VoidRescue { private const float VanillaVoidY = -50f; private const float PerObjectCooldown = 2f; private static readonly Dictionary<int, float> LastRescue = new Dictionary<int, float>(); private static float _nextPrune; private static bool _valuableRefResolved; private static FieldRef<PhysGrabObject, bool> _isValuable; internal static void Prefix(PhysGrabObject __instance) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if (!RunGate.CanMoveObjects || (Object)(object)__instance == (Object)null || __instance.dead || !__instance.spawned) { return; } Vector3 position = ((Component)__instance).transform.position; if (position.y >= -50f || !IsValuable(__instance)) { return; } TruckSafetySpawnPoint instance = TruckSafetySpawnPoint.instance; if (!((Object)(object)instance == (Object)null) && PassesCooldown(((Object)__instance).GetInstanceID())) { if ((Object)(object)__instance.rb != (Object)null) { __instance.rb.velocity = Vector3.zero; __instance.rb.angularVelocity = Vector3.zero; } __instance.Teleport(((Component)instance).transform.position, ((Component)instance).transform.rotation); GuardLog.Warn("rescue", "[Rescued] Returned a valuable that fell out of the world to the truck safety spawn" + $" - {((Object)__instance).name} (Y {position.y:F1})"); } } private static bool IsValuable(PhysGrabObject target) { if (!_valuableRefResolved) { _valuableRefResolved = true; try { _isValuable = AccessTools.FieldRefAccess<PhysGrabObject, bool>("isValuable"); } catch (Exception ex) { Plugin.Log.LogWarning((object)("PhysGrabObject.isValuable not accessible, falling back to GetComponent: " + ex.Message)); } } if (_isValuable == null) { return (Object)(object)((Component)target).GetComponent<ValuableObject>() != (Object)null; } return _isValuable.Invoke(target); } private static bool PassesCooldown(int id) { float unscaledTime = Time.unscaledTime; if (LastRescue.TryGetValue(id, out var value) && unscaledTime - value < 2f) { return false; } LastRescue[id] = unscaledTime; if (unscaledTime >= _nextPrune || LastRescue.Count >= 1024) { _nextPrune = unscaledTime + 30f; List<int> list = new List<int>(); foreach (KeyValuePair<int, float> item in LastRescue) { if (unscaledTime - item.Value > 30f) { list.Add(item.Key); } } for (int i = 0; i < list.Count; i++) { LastRescue.Remove(list[i]); } } return true; } } } namespace AntiItemTeleport.Core { internal static class CheatReport { private const byte EventCode = 171; private static bool _listening; internal static void StartListening() { if (_listening) { return; } try { PhotonNetwork.NetworkingClient.EventReceived += OnEvent; _listening = true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not subscribe to host block reports: " + ex.Message)); } } internal static void Broadcast(Player culprit, string targetName) { //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) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) if (culprit == null) { return; } try { if (PhotonNetwork.InRoom) { object[] array = new object[3] { culprit.ActorNumber, RpcOrigin.DescribeSender(culprit), targetName }; RaiseEventOptions val = new RaiseEventOptions { Receivers = (ReceiverGroup)0 }; PhotonNetwork.RaiseEvent((byte)171, (object)array, val, SendOptions.SendReliable); } } catch (Exception ex) { GuardLog.Warn("report-send", "Could not broadcast the block report: " + ex.Message); } } private static void OnEvent(EventData photonEvent) { if (photonEvent.Code != 171) { return; } Player masterClient = PhotonNetwork.MasterClient; if (masterClient != null && photonEvent.Sender == masterClient.ActorNumber && photonEvent.CustomData is object[] array && array.Length >= 3) { string text = array[1] as string; string text2 = array[2] as string; if (!string.IsNullOrEmpty(text)) { GuardLog.Warn("report", "[Host report] The host blocked a valuable position request | from: " + text + " | target: " + text2); } } } } internal static class GuardLog { private struct Bucket { public float NextEmit; public int Suppressed; } private const float Window = 1f; private static readonly Dictionary<string, Bucket> Buckets = new Dictionary<string, Bucket>(); internal static void Warn(string key, string message) { float unscaledTime = Time.unscaledTime; if (!Buckets.TryGetValue(key, out var value)) { value = default(Bucket); } if (unscaledTime < value.NextEmit) { value.Suppressed++; Buckets[key] = value; return; } if (value.Suppressed > 0) { message += $" ({value.Suppressed} more of the same suppressed in the last second)"; } value.Suppressed = 0; value.NextEmit = unscaledTime + 1f; Buckets[key] = value; Plugin.Log.LogWarning((object)message); } } internal static class PatchInstaller { private static Harmony _harmony; private static bool _dispatchGuardDone; internal static void InstallAll(Harmony harmony) { _harmony = harmony; if (Apply(harmony, "Call origin marker (PhysGrabObject.Teleport)", AccessTools.Method(typeof(PhysGrabObject), "Teleport", new Type[2] { typeof(Vector3), typeof(Quaternion) }, (Type[])null), Method(typeof(TeleportOrigin), "Enter"), Method(typeof(TeleportOrigin), "Leave"))) { Apply(harmony, "Second layer (PhysGrabObject.SetPositionRPC)", AccessTools.Method(typeof(PhysGrabObject), "SetPositionRPC", (Type[])null, (Type[])null), Method(typeof(SetPositionRpcGuard), "Prefix")); } else { Plugin.Log.LogError((object)"PhysGrabObject.Teleport not found. Cannot tell legitimate moves from cheats, so the second layer is not installed."); } Apply(harmony, "Fallen valuable rescue (PhysGrabObject.Update)", AccessTools.Method(typeof(PhysGrabObject), "Update", (Type[])null, (Type[])null), Method(typeof(VoidRescue), "Prefix")); if (GumballRosterFix.Resolve()) { Apply(harmony, "Gumball roster fix (GumballValuable.CheckForLeftPlayers)", AccessTools.Method(typeof(GumballValuable), "CheckForLeftPlayers", (Type[])null, (Type[])null), Method(typeof(GumballRosterFix), "Prefix")); } } internal static void TryInstallDispatchGuard() { if (!_dispatchGuardDone && _harmony != null && !((Object)(object)GameObject.Find("PhotonMono") == (Object)null)) { _dispatchGuardDone = true; CheatReport.StartListening(); try { RpcOrigin.Available = Apply(_harmony, "First layer (PhotonNetwork.ExecuteRpc)", AccessTools.Method(typeof(PhotonNetwork), "ExecuteRpc", (Type[])null, (Type[])null), Method(typeof(RpcOrigin), "Enter"), Method(typeof(RpcOrigin), "Leave")); } catch (Exception ex) { RpcOrigin.Available = false; Plugin.Log.LogError((object)("Failed to install the first layer: " + ex.Message)); } if (!RpcOrigin.Available) { Plugin.Log.LogError((object)"Running on the second layer (direct SetPositionRPC check) only."); } } } private static bool Apply(Harmony harmony, string label, MethodBase target, HarmonyMethod prefix = null, HarmonyMethod finalizer = null) { if (target == null) { Plugin.Log.LogWarning((object)("Target not found, skipping - " + label)); return false; } try { harmony.Patch(target, prefix, (HarmonyMethod)null, (HarmonyMethod)null, finalizer, (HarmonyMethod)null); Plugin.Log.LogInfo((object)("Installed - " + label)); return true; } catch (Exception ex) { Plugin.Log.LogError((object)("Failed to install - " + label + ": " + ex.Message)); return false; } } private static HarmonyMethod Method(Type type, string name) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(type, name, (Type[])null, (Type[])null); if (methodInfo == null) { throw new InvalidOperationException("Patch method not found: " + type.Name + "." + name); } return new HarmonyMethod(methodInfo); } } internal static class RpcOrigin { private const int SanityLimit = 64; internal static bool Available; private static readonly List<Player> Stack = new List<Player>(8); private static bool _warned; internal static bool InDispatch => Stack.Count > 0; internal static Player CurrentSender { get { if (Stack.Count <= 0) { return null; } return Stack[Stack.Count - 1]; } } internal static bool Enter(Hashtable rpcData, Player sender) { Stack.Add(sender); if (Stack.Count > 64) { Stack.Clear(); if (!_warned) { _warned = true; Plugin.Log.LogWarning((object)"Inbound RPC sender stack grew abnormally deep and was reset."); } return true; } return !RpcDispatchGuard.ShouldDrop(rpcData, sender); } internal static void Leave() { int num = Stack.Count - 1; if (num >= 0) { Stack.RemoveAt(num); } } internal static string DescribeSender() { return DescribeSender(CurrentSender); } internal static string DescribeSender(Player sender) { if (sender == null) { return "unknown client"; } try { PlayerAvatar val = SemiFunc.PlayerAvatarGetFromPhotonPlayer(sender); if ((Object)(object)val != (Object)null) { return $"{SemiFunc.PlayerGetName(val)} (SteamID {SemiFunc.PlayerGetSteamID(val)}, Actor {sender.ActorNumber})"; } } catch { } return $"{sender.NickName} (Actor {sender.ActorNumber})"; } } internal static class RunGate { private static int _frame = -1; private static bool _inGame; private static bool _host; private static bool _levelReady; internal static bool HostInGame { get { Refresh(); if (_inGame) { return _host; } return false; } } internal static bool CanMoveObjects { get { Refresh(); if (_inGame && _host) { return _levelReady; } return false; } } private static void Refresh() { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Invalid comparison between Unknown and I4 int frameCount = Time.frameCount; if (frameCount == _frame) { return; } _frame = frameCount; _inGame = false; _host = false; _levelReady = false; try { if ((Object)(object)RunManager.instance == (Object)null || SemiFunc.MenuLevel()) { return; } _inGame = true; _host = SemiFunc.IsMasterClientOrSingleplayer(); _levelReady = (Object)(object)LevelGenerator.Instance != (Object)null && LevelGenerator.Instance.Generated && (Object)(object)GameDirector.instance != (Object)null && (int)GameDirector.instance.currentState == 2; } catch (Exception) { _inGame = false; _host = false; _levelReady = false; } PatchInstaller.TryInstallDispatchGuard(); } } internal static class TeleportOrigin { private const int SanityLimit = 64; private static int _depth; private static bool _warned; internal static bool InLocalCall => _depth > 0; internal static void Enter() { _depth++; if (_depth > 64) { _depth = 0; if (!_warned) { _warned = true; Plugin.Log.LogWarning((object)"Teleport call depth grew abnormally large and was reset."); } } } internal static void Leave() { if (_depth > 0) { _depth--; } } } }