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.4.0
BepInEx/plugins/RepoAntiItemTeleport.dll
Decompiled 3 weeks 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.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Photon.Pun; using Photon.Realtime; using Steamworks; using Steamworks.Data; 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("1.4.0.0")] [assembly: AssemblyInformationalVersion("1.4.0")] [assembly: AssemblyProduct("Anti Item Teleport")] [assembly: AssemblyTitle("RepoAntiItemTeleport")] [assembly: AssemblyVersion("1.4.0.0")] namespace AntiItemTeleport { [BepInPlugin("com.sunwu.anti_Item_teleport", "Anti Item Teleport", "1.4.0")] public sealed class Plugin : BaseUnityPlugin { internal const string Guid = "com.sunwu.anti_Item_teleport"; internal const string Name = "Anti Item Teleport"; internal const string Version = "1.4.0"; internal static ManualLogSource Log; internal static ConfigEntry<bool> AutoKick; internal static ConfigEntry<bool> ItemProtection; internal static ConfigEntry<bool> CartProtection; private void Awake() { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; AutoKick = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Auto Kick", true, "Kick players caught teleporting objects. Host only.\n아이템 텔레포트 악용이 감지된 플레이어를 추방합니다. 방장에서만 동작합니다."); ItemProtection = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Item Protection", true, "When a player leaves or quits with items in their inventory, drop those items in the truck. Host only.\n플레이어가 인벤토리에 아이템을 넣은 채 나가거나 게임을 종료하면, 그 아이템을 트럭에 떨어뜨립니다. 방장에서만 동작합니다."); CartProtection = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Cart Protection", true, "Carts that would be destroyed by an extraction point or by falling out of the map are returned to the truck instead. Host only.\n추출구나 맵 밖 추락 등으로 부서질 카트를 부수지 않고 트럭으로 되돌립니다. 방장에서만 동작합니다."); PatchInstaller.InstallAll(new Harmony("com.sunwu.anti_Item_teleport")); SceneManager.sceneLoaded += delegate { PatchInstaller.TryInstallNetworkPatches(); }; } private void Update() { PatchInstaller.TryInstallNetworkPatches(); ModEvents.TickHostCheck(); } } } namespace AntiItemTeleport.Patches { internal static class CartRescue { internal static bool Prefix(PhysGrabObjectImpactDetector __instance) { if (!__instance.isCart || !Plugin.CartProtection.Value || !RunGate.CanMoveObjects || SemiFunc.RunIsShop()) { return true; } PhysGrabObject component = ((Component)__instance).GetComponent<PhysGrabObject>(); if ((Object)(object)component == (Object)null || component.dead || !Truck.MoveTo(component)) { return true; } ModEvents.Share("rescue-cart", "[Rescued] " + GuardLog.NameOf((Object)(object)component) + " -> truck"); return false; } } internal static class LeaverItemDrop { private static readonly FieldRef<ItemEquippable, int> SpotIndex = AccessTools.FieldRefAccess<ItemEquippable, int>("inventorySpotIndex"); private static readonly FieldRef<ItemEquippable, bool> ForceUnequipping = AccessTools.FieldRefAccess<ItemEquippable, bool>("isForceUnequipping"); internal static void Prefix(Player otherPlayer) { try { Drop(otherPlayer); } catch (Exception ex) { GuardLog.Warn("item-drop-error", "Item protection failed: " + ex.Message); } } private static void Drop(Player leaver) { if (leaver == null || !Plugin.ItemProtection.Value || !RunGate.CanMoveObjects || SemiFunc.RunIsShop() || SemiFunc.RunIsArena() || (Object)(object)TruckSafetySpawnPoint.instance == (Object)null) { return; } PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); if ((Object)(object)val == (Object)null) { return; } int viewID = PhotonView.Get((Component)(object)val).ViewID; List<string> list = new List<string>(); string text = null; ItemEquippable[] array = Object.FindObjectsOfType<ItemEquippable>(); foreach (ItemEquippable val2 in array) { PlayerAvatar val3 = (val2.IsEquipped() ? val2.GetOwnerPlayerAvatar() : null); if (!((Object)(object)val3 == (Object)null) && PhotonView.Get((Component)(object)val3).OwnerActorNr == leaver.ActorNumber) { int num = SpotIndex.Invoke(val2); ((MonoBehaviourPun)val2).photonView.RPC("RPC_UpdateItemState", (RpcTarget)0, new object[3] { 3, -1, viewID }); ForceUnequipping.Invoke(val2) = true; PhysGrabObject component = ((Component)val2).GetComponent<PhysGrabObject>(); component.OverrideDeactivateReset(); Truck.MoveTo(component, 0.3f * (float)list.Count); if (num >= 0) { StatsManager.instance.PlayerInventoryUpdate(SemiFunc.PlayerGetSteamID(val3), "", num, true); } list.Add(GuardLog.NameOf((Object)(object)component)); if (text == null) { text = SemiFunc.PlayerGetName(val3); } } } if (list.Count > 0) { ModEvents.Share($"rescue-items:{leaver.ActorNumber}", "[Rescued] " + string.Join(", ", list) + " -> truck (" + text + " left)"); } } } internal static class RpcDispatchGuard { private static readonly object KeyViewId = (byte)0; private static readonly object KeyMethodName = (byte)3; private static readonly object KeyRpcIndex = (byte)5; internal static bool ShouldDrop(Hashtable rpcData, Player sender) { if (rpcData == null || sender == PhotonNetwork.LocalPlayer || !RunGate.HostInGame) { return false; } string text; try { text = MethodName(rpcData); } catch (Exception ex) { GuardLog.Warn("dispatch-error", "Unreadable RPC: " + ex.Message); return false; } if (text != "SetPositionRPC") { return false; } PhotonView val = ((rpcData[KeyViewId] is int num) ? PhotonView.Find(num) : null); if ((Object)(object)val != (Object)null) { Detection.Handle(((Component)val).gameObject, sender); } return true; } private static string MethodName(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 (num < 0 || num >= rpcList.Count) { return null; } return rpcList[num]; } } internal static class SetPositionRpcGuard { internal static bool Prefix(PhysGrabObject __instance) { if (!RunGate.HostInGame || TeleportOrigin.InLocalCall) { return true; } if (RpcOrigin.Available && !RpcOrigin.InDispatch) { return true; } Detection.Handle(((Component)__instance).gameObject, RpcOrigin.CurrentSender); return false; } } internal static class VoidRescue { private const float VanillaVoidY = -50f; internal static void Prefix(PhysGrabObject __instance) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (!(((Component)__instance).transform.position.y >= -50f) && RunGate.CanMoveObjects && !__instance.dead && __instance.spawned && !((Object)(object)((Component)__instance).GetComponent<ValuableObject>() == (Object)null) && Truck.MoveTo(__instance)) { ModEvents.Share("rescue", "[Rescued] " + GuardLog.NameOf((Object)(object)__instance) + " -> truck"); } } } } namespace AntiItemTeleport.Core { internal static class Detection { private static readonly HashSet<int> Kicked = new HashSet<int>(); private static FieldRef<SteamManager, Lobby> _currentLobby; internal static void Handle(GameObject target, Player sender) { try { if (!((Object)(object)target == (Object)null) && !IsRedundantMove(target)) { string kicked = (Kick(sender) ? " (kicked)" : ""); Player obj = sender; ModEvents.Share($"tp:{((obj != null) ? new int?(obj.ActorNumber) : ((int?)null))}", () => "[Teleport] " + Describe(sender) + " -> " + Category(target) + ": " + GuardLog.NameOf((Object)(object)target) + kicked); } } catch (Exception ex) { GuardLog.Warn("detect-error", "Detection failed: " + ex.Message); } } private static bool IsRedundantMove(GameObject target) { EnemyParent componentInParent = target.GetComponentInParent<EnemyParent>(); if ((!((Object)(object)componentInParent != (Object)null) || !((Object)(object)((Component)componentInParent).GetComponentInChildren<EnemySlowMouth>(true) != (Object)null)) && (!((Object)(object)target.GetComponentInParent<ItemMine>() != (Object)null) || !SemiFunc.RunIsShop())) { return (Object)(object)target.GetComponentInParent<PlayerTumble>() != (Object)null; } return true; } private static string Category(GameObject target) { if ((Object)(object)target.GetComponent<CosmeticWorldObject>() != (Object)null) { return "Cosmetic box"; } if ((Object)(object)target.GetComponent<ValuableObject>() != (Object)null) { return "Valuable"; } if ((Object)(object)target.GetComponent<ItemAttributes>() != (Object)null) { return "Item"; } if ((Object)(object)target.GetComponentInParent<EnemyParent>() != (Object)null) { return "Monster"; } if ((Object)(object)target.GetComponentInParent<PlayerDeathHead>() != (Object)null) { return "Death head"; } if ((Object)(object)target.GetComponent<PhysGrabCart>() != (Object)null) { return "Cart"; } return "Object"; } internal static string Describe(Player player) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) if (player == null) { return "unknown"; } PlayerAvatar val = SemiFunc.PlayerAvatarGetFromPhotonPlayer(player); string text = (((Object)(object)val != (Object)null) ? SemiFunc.PlayerGetSteamID(val) : null); Friend? val2 = LobbyMember(player.UserId); if (!val2.HasValue) { string obj = (((Object)(object)val != (Object)null) ? SemiFunc.PlayerGetName(val) : player.NickName); string text2 = ((!string.IsNullOrEmpty(player.UserId)) ? player.UserId : (text ?? "?")); return obj + " (" + text2 + ", unverified)"; } Friend value = val2.Value; string text3 = value.Id.Value.ToString(); value = val2.Value; string text4 = ((Friend)(ref value)).Name + " (" + text3 + ")"; if (text == null || !(text != text3)) { return text4; } return text4 + " [claims " + text + "]"; } private static Friend? LobbyMember(string userId) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(userId) || (Object)(object)SteamManager.instance == (Object)null) { return null; } try { if (_currentLobby == null) { _currentLobby = AccessTools.FieldRefAccess<SteamManager, Lobby>("currentLobby"); } foreach (Friend member in ((Lobby)(ref _currentLobby.Invoke(SteamManager.instance))).Members) { if (member.Id.Value.ToString() == userId) { return member; } } } catch { } return null; } internal static void PublishUserId(EnterRoomParams enterRoomParams) { if (enterRoomParams?.RoomOptions != null) { enterRoomParams.RoomOptions.PublishUserId = true; } } private static bool Kick(Player sender) { if (sender == null || !Plugin.AutoKick.Value) { return false; } if (Kicked.Contains(sender.ActorNumber)) { return true; } PlayerAvatar val = SemiFunc.PlayerAvatarGetFromPhotonPlayer(sender); if ((Object)(object)val == (Object)null || (Object)(object)NetworkManager.instance == (Object)null) { return false; } NetworkManager.instance.KickPlayer(val); Kicked.Add(sender.ActorNumber); return true; } } internal static class GuardLog { private static readonly Dictionary<string, float> NextEmit = new Dictionary<string, float>(); private static readonly Dictionary<string, int> Suppressed = new Dictionary<string, int>(); internal static bool Warn(string key, string message) { return Warn(key, () => message) != null; } internal static string Warn(string key, Func<string> build) { float unscaledTime = Time.unscaledTime; Suppressed.TryGetValue(key, out var value); if (NextEmit.TryGetValue(key, out var value2) && unscaledTime < value2) { Suppressed[key] = value + 1; return null; } NextEmit[key] = unscaledTime + 1f; Suppressed[key] = 0; string text = build(); Plugin.Log.LogWarning((object)((value > 0) ? $"{text} (+{value})" : text)); return text; } internal static string NameOf(Object obj) { return obj.name.Replace("(Clone)", "").Trim(); } } internal static class ModEvents { private const byte Code = 171; private const byte Report = 0; private const byte Ping = 1; private const byte Pong = 2; private static bool _listening; private static string _checkedRoom; private static float _pingSentAt = -1f; internal static void Listen() { try { PhotonNetwork.NetworkingClient.EventReceived += OnEvent; _listening = true; } catch (Exception ex) { Plugin.Log.LogError((object)("Patch failed: mod events (" + ex.Message + ")")); } } internal static void Share(string key, string line) { Share(key, () => line); } internal static void Share(string key, Func<string> build) { //IL_001e: 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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown string text = GuardLog.Warn(key, build); if (text != null) { Send(new object[2] { (byte)0, text }, new RaiseEventOptions { Receivers = (ReceiverGroup)0 }); } } internal static void TickHostCheck() { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown if (_listening) { if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient || PhotonNetwork.CurrentRoom == null) { _checkedRoom = null; _pingSentAt = -1f; } else if (PhotonNetwork.CurrentRoom.Name != _checkedRoom) { _checkedRoom = PhotonNetwork.CurrentRoom.Name; _pingSentAt = Time.unscaledTime; Send(new object[2] { (byte)1, "1.4.0" }, new RaiseEventOptions { Receivers = (ReceiverGroup)2 }); } else if (_pingSentAt >= 0f && Time.unscaledTime - _pingSentAt > 5f) { _pingSentAt = -1f; Plugin.Log.LogWarning((object)"Host does not have Anti Item Teleport."); } } } private static void Send(object[] content, RaiseEventOptions options) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) try { if (PhotonNetwork.InRoom) { PhotonNetwork.RaiseEvent((byte)171, (object)content, options, SendOptions.SendReliable); } } catch (Exception ex) { GuardLog.Warn("event-send", "Mod event not sent: " + ex.Message); } } private static void OnEvent(EventData e) { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown if (e.Code == 171 && e.CustomData is object[] array && array.Length >= 2 && array[0] is byte b) { Player masterClient = PhotonNetwork.MasterClient; bool flag = masterClient != null && e.Sender == masterClient.ActorNumber; if (b == 0 && flag && array[1] is string text) { GuardLog.Warn("host:" + text.Split(' ')[0], "[Host] " + text); } else if (b == 1 && PhotonNetwork.IsMasterClient) { object[] content = new object[2] { (byte)2, "1.4.0" }; RaiseEventOptions val = new RaiseEventOptions(); val.TargetActors = new int[1] { e.Sender }; Send(content, val); } else if (b == 2 && flag && _pingSentAt >= 0f) { _pingSentAt = -1f; Plugin.Log.LogInfo((object)string.Format("Host has {0} {1}.", "Anti Item Teleport", array[1])); } } } } internal static class PatchInstaller { private static Harmony _harmony; private static bool _networkPatched; internal static void InstallAll(Harmony harmony) { _harmony = harmony; if (Apply("PhysGrabObject.Teleport", AccessTools.Method(typeof(PhysGrabObject), "Teleport", new Type[2] { typeof(Vector3), typeof(Quaternion) }, (Type[])null), Hook(typeof(TeleportOrigin), "Enter"), Hook(typeof(TeleportOrigin), "Leave"))) { Apply("PhysGrabObject.SetPositionRPC", AccessTools.Method(typeof(PhysGrabObject), "SetPositionRPC", (Type[])null, (Type[])null), Hook(typeof(SetPositionRpcGuard), "Prefix")); } Apply("PhysGrabObject.Update", AccessTools.Method(typeof(PhysGrabObject), "Update", (Type[])null, (Type[])null), Hook(typeof(VoidRescue), "Prefix")); Apply("PhysGrabObjectImpactDetector.DestroyObject", AccessTools.Method(typeof(PhysGrabObjectImpactDetector), "DestroyObject", (Type[])null, (Type[])null), Hook(typeof(CartRescue), "Prefix")); } internal static void TryInstallNetworkPatches() { if (!_networkPatched && _harmony != null && !((Object)(object)GameObject.Find("PhotonMono") == (Object)null)) { _networkPatched = true; ModEvents.Listen(); string[] array = new string[2] { "OpCreateRoom", "OpJoinOrCreateRoom" }; foreach (string text in array) { Apply("LoadBalancingClient." + text, AccessTools.Method(typeof(LoadBalancingClient), text, (Type[])null, (Type[])null), Hook(typeof(Detection), "PublishUserId")); } Apply("NetworkManager.OnPlayerLeftRoom", AccessTools.Method(typeof(NetworkManager), "OnPlayerLeftRoom", (Type[])null, (Type[])null), Hook(typeof(LeaverItemDrop), "Prefix")); RpcOrigin.Available = Apply("PhotonNetwork.ExecuteRpc", AccessTools.Method(typeof(PhotonNetwork), "ExecuteRpc", (Type[])null, (Type[])null), Hook(typeof(RpcOrigin), "Enter"), Hook(typeof(RpcOrigin), "Leave")); Plugin.Log.LogInfo((object)(RpcOrigin.Available ? "Anti Item Teleport 1.4.0 active." : "Anti Item Teleport 1.4.0 active (fallback layer only).")); } } private static HarmonyMethod Hook(Type type, string method) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown return new HarmonyMethod(type, method, (Type[])null); } private static bool Apply(string label, MethodBase target, HarmonyMethod prefix, HarmonyMethod finalizer = null) { try { if (target == null) { throw new MissingMethodException("not found"); } _harmony.Patch(target, prefix, (HarmonyMethod)null, (HarmonyMethod)null, finalizer, (HarmonyMethod)null); return true; } catch (Exception ex) { Plugin.Log.LogError((object)("Patch failed: " + label + " (" + ex.Message + ")")); return false; } } } internal static class RpcOrigin { internal static bool Available; private static readonly List<Player> Senders = new List<Player>(); internal static bool InDispatch => Senders.Count > 0; internal static Player CurrentSender { get { if (Senders.Count <= 0) { return null; } return Senders[Senders.Count - 1]; } } internal static bool Enter(Hashtable rpcData, Player sender) { if (Senders.Count > 64) { Senders.Clear(); } Senders.Add(sender); return !RpcDispatchGuard.ShouldDrop(rpcData, sender); } internal static void Leave() { if (Senders.Count > 0) { Senders.RemoveAt(Senders.Count - 1); } } } internal static class RunGate { private static int _frame = -1; private static bool _hostInGame; private static bool _levelReady; internal static bool HostInGame { get { Refresh(); return _hostInGame; } } internal static bool CanMoveObjects { get { Refresh(); if (_hostInGame) { return _levelReady; } return false; } } private static void Refresh() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Invalid comparison between Unknown and I4 if (_frame == Time.frameCount) { return; } _frame = Time.frameCount; try { _hostInGame = (Object)(object)RunManager.instance != (Object)null && !SemiFunc.MenuLevel() && SemiFunc.IsMasterClientOrSingleplayer(); _levelReady = (Object)(object)LevelGenerator.Instance != (Object)null && LevelGenerator.Instance.Generated && (Object)(object)GameDirector.instance != (Object)null && (int)GameDirector.instance.currentState == 2; } catch { _hostInGame = (_levelReady = false); } } } internal static class TeleportOrigin { private static int _depth; internal static bool InLocalCall => _depth > 0; internal static void Enter() { if (++_depth > 64) { _depth = 0; } } internal static void Leave() { if (_depth > 0) { _depth--; } } } internal static class Truck { internal static bool MoveTo(PhysGrabObject obj, float height = 0f) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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) TruckSafetySpawnPoint instance = TruckSafetySpawnPoint.instance; if ((Object)(object)instance == (Object)null) { return false; } if ((Object)(object)obj.rb != (Object)null) { obj.rb.velocity = Vector3.zero; obj.rb.angularVelocity = Vector3.zero; } obj.Teleport(((Component)instance).transform.position + Vector3.up * height, ((Component)instance).transform.rotation); return true; } } }