Please disclose if your mod was created primarily 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 ValheimEssentials v1.0.0
plugins/ValheimEssentials/ValheimEssentials.dll
Decompiled 2 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("ValheimEssentials")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+f84a7f7d29d31f2889ca36c8ca597670851b1e2e")] [assembly: AssemblyProduct("ValheimEssentials")] [assembly: AssemblyTitle("ValheimEssentials")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ValheimEssentials { public static class BackManager { public enum PositionType { Teleport, Death } private static readonly Dictionary<string, Vector3> LastPositions = new Dictionary<string, Vector3>(); private static readonly Dictionary<string, PositionType> LastTypes = new Dictionary<string, PositionType>(); public static void SavePosition(Player player, PositionType type = PositionType.Teleport) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) string key = player.GetPlayerID().ToString(); LastPositions[key] = ((Component)player).transform.position; LastTypes[key] = type; } public static Vector3? GetLastPosition(Player player) { PositionType type; return GetLastPosition(player, out type); } public static Vector3? GetLastPosition(Player player, out PositionType type) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) type = PositionType.Teleport; string key = player.GetPlayerID().ToString(); if (LastPositions.TryGetValue(key, out var value)) { LastTypes.TryGetValue(key, out type); return value; } return null; } public static void Clear() { LastPositions.Clear(); LastTypes.Clear(); } } [HarmonyPatch(typeof(Chat), "InputText")] public static class CommandRouter { private static bool Prefix(Chat __instance) { string text = ((TMP_InputField)((Terminal)__instance).m_input).text; if (string.IsNullOrEmpty(text)) { return true; } string value = Plugin.CommandPrefix.Value; if (!text.StartsWith(value, StringComparison.OrdinalIgnoreCase)) { return true; } string text2 = text.Substring(value.Length); if (string.IsNullOrEmpty(text2)) { return true; } string[] array = text2.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); string cmd = array[0].ToLowerInvariant(); string[] array2; if (array.Length > 1) { array2 = new string[array.Length - 1]; Array.Copy(array, 1, array2, 0, array.Length - 1); } else { array2 = Array.Empty<string>(); } Dispatch(cmd, array2); return false; } private static void Dispatch(string cmd, string[] args) { //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_03d2: Unknown result type (might be due to invalid IL or missing references) switch (cmd) { case "sethome": { Player localPlayer4 = Player.m_localPlayer; if (!((Object)(object)localPlayer4 == (Object)null)) { if (args.Length == 0) { FeedbackHelper.SendError("Você precisa dar um nome! Ex: /sethome base"); break; } if (HomeManager.SetHome(localPlayer4, args[0], ((Component)localPlayer4).transform.position)) { FeedbackHelper.Send("Home '<color=yellow>" + args[0] + "</color>' salvo!"); break; } int value = Plugin.MaxHomes.Value; FeedbackHelper.SendError($"Limite de homes atingido! ({value}/{value}). Delete um com /delhome <nome>"); } break; } case "home": { Player localPlayer7 = Player.m_localPlayer; if ((Object)(object)localPlayer7 == (Object)null) { break; } if (args.Length == 0) { FeedbackHelper.SendError("Você precisa dar um nome! Ex: /home base"); break; } Vector3? home = HomeManager.GetHome(localPlayer7, args[0]); if (!home.HasValue) { FeedbackHelper.SendError("Home '<color=yellow>" + args[0] + "</color>' não encontrado. Use /homes pra ver seus homes."); break; } TeleportHelper.Teleport(localPlayer7, home.Value); FeedbackHelper.Send("Teleportado para '<color=yellow>" + args[0] + "</color>'!"); break; } case "delhome": { Player localPlayer2 = Player.m_localPlayer; if (!((Object)(object)localPlayer2 == (Object)null)) { if (args.Length == 0) { FeedbackHelper.SendError("Você precisa dar um nome! Ex: /delhome base"); } else if (HomeManager.RemoveHome(localPlayer2, args[0])) { FeedbackHelper.Send("Home '<color=yellow>" + args[0] + "</color>' deletado!"); } else { FeedbackHelper.SendError("Home '<color=yellow>" + args[0] + "</color>' não encontrado. Use /homes pra ver seus homes."); } } break; } case "homes": { Player localPlayer8 = Player.m_localPlayer; if (!((Object)(object)localPlayer8 == (Object)null)) { List<string> homeNames = HomeManager.GetHomeNames(localPlayer8); int value2 = Plugin.MaxHomes.Value; if (homeNames.Count == 0) { FeedbackHelper.Send("Você não tem homes salvos. Use /sethome <nome> pra criar um!"); break; } homeNames.Sort(StringComparer.OrdinalIgnoreCase); string arg = string.Join(", ", homeNames); FeedbackHelper.Send($"Homes ({homeNames.Count}/{value2}): {arg}"); } break; } case "back": { Player localPlayer6 = Player.m_localPlayer; if ((Object)(object)localPlayer6 == (Object)null) { break; } BackManager.PositionType type; Vector3? lastPosition = BackManager.GetLastPosition(localPlayer6, out type); if (!lastPosition.HasValue) { FeedbackHelper.SendError("Nenhuma posição anterior salva. Use um teleporte primeiro!"); break; } TeleportHelper.Teleport(localPlayer6, lastPosition.Value); if (type == BackManager.PositionType.Death) { FeedbackHelper.Send("Teleportado para o local da sua morte!"); } else { FeedbackHelper.Send("Teleportado para a posicao anterior!"); } break; } case "tpa": { Player localPlayer5 = Player.m_localPlayer; if ((Object)(object)localPlayer5 == (Object)null) { break; } if (args.Length == 0) { FeedbackHelper.SendError("Uso: /tpa <jogador>"); break; } string text = string.Join(" ", args); if (text.Equals(localPlayer5.GetPlayerName(), StringComparison.OrdinalIgnoreCase)) { FeedbackHelper.SendError("Voce nao pode se teleportar para si mesmo!"); } else { RpcChannels.SendTpaRequest(localPlayer5, text); } break; } case "tpaccept": { Player localPlayer3 = Player.m_localPlayer; if (!((Object)(object)localPlayer3 == (Object)null)) { RpcChannels.SendTpaAccept(); } break; } case "rtp": { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { float minRange = Plugin.RtpMinRange.Value; float maxRange = Plugin.RtpMaxRange.Value; RtpManager.StartSearch(localPlayer, minRange, maxRange); } break; } default: FeedbackHelper.Send("Comando desconhecido: <color=yellow>/" + cmd + "</color>. Use /ajuda para ver os comandos."); break; } } } [HarmonyPatch(typeof(ZNet), "Awake")] public static class ZNet_Start_Patch { private static void Postfix() { HomeManager.Reset(); RpcChannels.Register(); Plugin.Log.LogInfo((object)"[ValheimEssentials] RPCs registrados. Homes serao carregados no primeiro uso."); } } [HarmonyPatch(typeof(Player), "CreateTombStone")] public static class Player_CreateTombStone_Patch { private static void Prefix(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { BackManager.SavePosition(__instance, BackManager.PositionType.Death); FeedbackHelper.Send("Posição de morte salva. Use /back para voltar!"); } } } public static class FeedbackHelper { private const string Prefix = "<color=orange>[Essentials]</color>"; public static void Send(string message) { if (!((Object)(object)Chat.instance == (Object)null)) { ((Terminal)Chat.instance).AddString("<color=orange>[Essentials]</color> " + message); } } public static void SendError(string message) { if (!((Object)(object)Chat.instance == (Object)null)) { ((Terminal)Chat.instance).AddString("<color=orange>[Essentials]</color> <color=red>" + message + "</color>"); } } } public static class HomeManager { private static readonly Dictionary<string, Dictionary<string, Vector3>> PlayerHomes = new Dictionary<string, Dictionary<string, Vector3>>(); private static string _currentFile; private static bool _loaded = false; private static string GetSavePath() { string text = "default"; try { if ((Object)(object)ZNet.instance != (Object)null) { string worldName = ZNet.instance.GetWorldName(); if (!string.IsNullOrEmpty(worldName) && worldName != "") { text = worldName; } } } catch { } string text2 = Path.Combine(Paths.ConfigPath, "ValheimEssentials"); Directory.CreateDirectory(text2); return Path.Combine(text2, "homes_" + text + ".txt"); } private static void EnsureLoaded() { if (!_loaded) { Load(); } } public static void Reset() { _loaded = false; PlayerHomes.Clear(); } public static void Load() { //IL_0122: Unknown result type (might be due to invalid IL or missing references) PlayerHomes.Clear(); _currentFile = GetSavePath(); _loaded = true; Plugin.Log.LogInfo((object)("[ValheimEssentials] Tentando carregar homes de: " + _currentFile)); if (!File.Exists(_currentFile)) { Plugin.Log.LogInfo((object)("[ValheimEssentials] Arquivo de homes nao encontrado: " + _currentFile)); return; } string[] array = File.ReadAllLines(_currentFile); foreach (string text in array) { string[] array2 = text.Split(new char[1] { '|' }); if (array2.Length != 5) { continue; } string key = array2[0]; string key2 = array2[1]; if (float.TryParse(array2[2], out var result) && float.TryParse(array2[3], out var result2) && float.TryParse(array2[4], out var result3)) { if (!PlayerHomes.ContainsKey(key)) { PlayerHomes[key] = new Dictionary<string, Vector3>(StringComparer.OrdinalIgnoreCase); } PlayerHomes[key][key2] = new Vector3(result, result2, result3); } } Plugin.Log.LogInfo((object)$"Homes carregadas de {_currentFile}: {PlayerHomes.Values.Sum((Dictionary<string, Vector3> h) => h.Count)} total"); } public static void Save() { //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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) _currentFile = GetSavePath(); List<string> list = new List<string>(); foreach (KeyValuePair<string, Dictionary<string, Vector3>> playerHome in PlayerHomes) { string key = playerHome.Key; foreach (KeyValuePair<string, Vector3> item in playerHome.Value) { Vector3 value = item.Value; list.Add($"{key}|{item.Key}|{value.x}|{value.y}|{value.z}"); } } string text = _currentFile + ".tmp"; File.WriteAllLines(text, list); if (File.Exists(_currentFile)) { File.Replace(text, _currentFile, null); } else { File.Move(text, _currentFile); } } public static string GetPlayerId(Player player) { return player.GetPlayerID().ToString(); } public static bool SetHome(Player player, string homeName, Vector3 position) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) EnsureLoaded(); string playerId = GetPlayerId(player); if (!PlayerHomes.ContainsKey(playerId)) { PlayerHomes[playerId] = new Dictionary<string, Vector3>(StringComparer.OrdinalIgnoreCase); } Dictionary<string, Vector3> dictionary = PlayerHomes[playerId]; if (dictionary.ContainsKey(homeName)) { dictionary[homeName] = position; Save(); return true; } if (dictionary.Count >= Plugin.MaxHomes.Value) { return false; } dictionary[homeName] = position; Save(); return true; } public static bool RemoveHome(Player player, string homeName) { EnsureLoaded(); string playerId = GetPlayerId(player); if (!PlayerHomes.ContainsKey(playerId)) { return false; } bool flag = PlayerHomes[playerId].Remove(homeName); if (flag) { Save(); } return flag; } public static Vector3? GetHome(Player player, string homeName) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) EnsureLoaded(); string playerId = GetPlayerId(player); if (!PlayerHomes.ContainsKey(playerId)) { return null; } if (PlayerHomes[playerId].TryGetValue(homeName, out var value)) { return value; } return null; } public static List<string> GetHomeNames(Player player) { EnsureLoaded(); string playerId = GetPlayerId(player); if (!PlayerHomes.ContainsKey(playerId)) { return new List<string>(); } return PlayerHomes[playerId].Keys.ToList(); } } [BepInPlugin("com.jojo.valheimessentials", "ValheimEssentials", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.jojo.valheimessentials"; public const string PluginName = "ValheimEssentials"; public const string PluginVersion = "1.0.0"; internal static ManualLogSource Log; internal static Plugin Instance; private Harmony _harmony; public static ConfigEntry<int> RtpMinRange; public static ConfigEntry<int> RtpMaxRange; public static ConfigEntry<int> RtpCooldownSeconds; public static ConfigEntry<int> HomeCooldownSeconds; public static ConfigEntry<int> BackCooldownSeconds; public static ConfigEntry<int> MaxHomes; public static ConfigEntry<string> CommandPrefix; private void Awake() { Instance = this; Log = ((BaseUnityPlugin)this).Logger; CommandPrefix = ((BaseUnityPlugin)this).Config.Bind<string>("General", "CommandPrefix", "/", "Prefixo dos comandos no chat"); RtpMinRange = ((BaseUnityPlugin)this).Config.Bind<int>("RTP", "MinRange", 1000, "Distância mínima do teleporte aleatório"); RtpMaxRange = ((BaseUnityPlugin)this).Config.Bind<int>("RTP", "MaxRange", 8000, "Distância máxima do teleporte aleatório"); RtpCooldownSeconds = ((BaseUnityPlugin)this).Config.Bind<int>("RTP", "CooldownSeconds", 0, "Cooldown do /rtp em segundos (0 = desativado)"); HomeCooldownSeconds = ((BaseUnityPlugin)this).Config.Bind<int>("Home", "CooldownSeconds", 0, "Cooldown do /home em segundos (0 = desativado)"); MaxHomes = ((BaseUnityPlugin)this).Config.Bind<int>("Home", "MaxHomes", 5, "Número máximo de homes por jogador"); BackCooldownSeconds = ((BaseUnityPlugin)this).Config.Bind<int>("Back", "CooldownSeconds", 0, "Cooldown do /back em segundos (0 = desativado)"); _harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "com.jojo.valheimessentials"); if (typeof(Chat).GetMethod("InputText", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) == null) { Log.LogError((object)"[ValheimEssentials] ERRO CRITICO: Chat.InputText nao encontrado! O mod pode nao funcionar apos uma atualizacao do Valheim."); } Log.LogInfo((object)"ValheimEssentials v1.0.0 carregado!"); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } public static class RpcChannels { public struct PlayerMatch { public long PeerUid; public string PlayerName; } public static void Register() { ZRoutedRpc.instance.Register<ZPackage>("VE_TpaRequest", (Action<long, ZPackage>)RPC_Server_TpaRequest); ZRoutedRpc.instance.Register<ZPackage>("VE_TpaNotify", (Action<long, ZPackage>)RPC_Client_TpaNotify); ZRoutedRpc.instance.Register<ZPackage>("VE_TpaAccept", (Action<long, ZPackage>)RPC_Server_TpaAccept); ZRoutedRpc.instance.Register<ZPackage>("VE_TpaExecute", (Action<long, ZPackage>)RPC_Client_TpaExecute); ZRoutedRpc.instance.Register<ZPackage>("VE_TpaExpireRequester", (Action<long, ZPackage>)RPC_Client_TpaExpireRequester); ZRoutedRpc.instance.Register<ZPackage>("VE_TpaExpireTarget", (Action<long, ZPackage>)RPC_Client_TpaExpireTarget); Plugin.Log.LogInfo((object)"[ValheimEssentials] RPCs de TPA registrados."); } public static void SendTpaRequest(Player player, string targetQuery) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(player.GetPlayerName()); val.Write(targetQuery); long serverPeerUid = GetServerPeerUid(); ZRoutedRpc.instance.InvokeRoutedRPC(serverPeerUid, "VE_TpaRequest", new object[1] { val }); } public static void SendTpaAccept() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown ZPackage val = new ZPackage(); long serverPeerUid = GetServerPeerUid(); ZRoutedRpc.instance.InvokeRoutedRPC(serverPeerUid, "VE_TpaAccept", new object[1] { val }); } private static long GetServerPeerUid() { if (ZNet.instance.IsServer()) { return ZNet.GetUID(); } ZNetPeer serverPeer = ZNet.instance.GetServerPeer(); if (serverPeer != null) { return serverPeer.m_uid; } Plugin.Log.LogWarning((object)"[ValheimEssentials] GetServerPeerUid: server peer nao encontrado, usando GetUID()"); return ZNet.GetUID(); } private static void RPC_Server_TpaRequest(long sender, ZPackage pkg) { //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Expected O, but got Unknown //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Expected O, but got Unknown string text = pkg.ReadString(); string query = pkg.ReadString(); List<PlayerMatch> list = FindByNameQuery(query); if (list.Count == 0) { SendNotifyError(sender, "Jogador nao encontrado ou offline"); return; } if (list.Count > 1) { string text2 = string.Join(", ", list.Select((PlayerMatch p) => p.PlayerName)); SendNotifyError(sender, "Multiplos jogadores encontrados: " + text2 + ". Seja mais especifico!"); return; } PlayerMatch playerMatch = list[0]; if (playerMatch.PeerUid == sender) { SendNotifyError(sender, "Voce nao pode se teleportar para si mesmo!"); return; } if (TpaManager.HasPendingFromRequester(sender)) { SendNotifyError(sender, "Voce ja tem um pedido pendente!"); return; } TpaManager.PendingRequest pendingRequest = default(TpaManager.PendingRequest); pendingRequest.RequesterPeerUid = sender; pendingRequest.RequesterName = text; pendingRequest.TargetPeerUid = playerMatch.PeerUid; pendingRequest.TargetName = playerMatch.PlayerName; pendingRequest.ExpiresAt = DateTime.UtcNow.AddSeconds(60.0); TpaManager.PendingRequest req = pendingRequest; TpaManager.TryAddRequest(sender, req); ZPackage val = new ZPackage(); val.Write((byte)2); val.Write(text); ZRoutedRpc.instance.InvokeRoutedRPC(playerMatch.PeerUid, "VE_TpaNotify", new object[1] { val }); ZPackage val2 = new ZPackage(); val2.Write((byte)1); val2.Write(playerMatch.PlayerName); ZRoutedRpc.instance.InvokeRoutedRPC(sender, "VE_TpaNotify", new object[1] { val2 }); ((MonoBehaviour)Plugin.Instance).StartCoroutine(TpaManager.ExpireAfterDelay(sender, 60f)); } private static void RPC_Server_TpaAccept(long sender, ZPackage pkg) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Expected O, but got Unknown if (!TpaManager.TryConsumeByTarget(sender, out var req)) { SendNotifyError(sender, "Nenhum pedido de TP pendente para voce!"); return; } ZNetPeer peer = ZNet.instance.GetPeer(req.RequesterPeerUid); if (peer == null) { SendNotifyError(sender, "O jogador que fez o pedido se desconectou."); return; } ZNetPeer peer2 = ZNet.instance.GetPeer(sender); if (peer2 == null) { SendNotifyError(req.RequesterPeerUid, "Erro ao obter posicao. Tente novamente."); return; } ZDO zDO = ZDOMan.instance.GetZDO(peer2.m_characterID); if (zDO == null) { SendNotifyError(req.RequesterPeerUid, "Erro ao obter posicao. Tente novamente."); return; } Vector3 position = zDO.GetPosition(); ZPackage val = new ZPackage(); val.Write(position); val.Write(req.TargetName); ZRoutedRpc.instance.InvokeRoutedRPC(req.RequesterPeerUid, "VE_TpaExecute", new object[1] { val }); ZPackage val2 = new ZPackage(); val2.Write((byte)3); val2.Write(req.RequesterName); ZRoutedRpc.instance.InvokeRoutedRPC(sender, "VE_TpaNotify", new object[1] { val2 }); } private static void RPC_Client_TpaNotify(long sender, ZPackage pkg) { byte b = pkg.ReadByte(); string text = pkg.ReadString(); switch (b) { case 0: FeedbackHelper.SendError(text); break; case 1: FeedbackHelper.Send("Pedido de TP enviado para <color=yellow>" + text + "</color>!"); break; case 2: FeedbackHelper.Send("<color=yellow>" + text + "</color> quer se teleportar para voce! Use /tpaccept"); break; case 3: FeedbackHelper.Send("<color=yellow>" + text + "</color> foi teleportado para voce!"); break; default: Plugin.Log.LogWarning((object)$"[ValheimEssentials] VE_TpaNotify: tipo desconhecido {b}"); break; } } private static void RPC_Client_TpaExecute(long sender, ZPackage pkg) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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) Vector3 destination = pkg.ReadVector3(); string text = pkg.ReadString(); Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { TeleportHelper.Teleport(localPlayer, destination); FeedbackHelper.Send("Teleportado para <color=yellow>" + text + "</color>!"); } } private static void RPC_Client_TpaExpireRequester(long sender, ZPackage pkg) { string text = pkg.ReadString(); FeedbackHelper.Send("Pedido de TP para <color=yellow>" + text + "</color> expirou"); } private static void RPC_Client_TpaExpireTarget(long sender, ZPackage pkg) { string text = pkg.ReadString(); FeedbackHelper.Send("Pedido de TP de <color=yellow>" + text + "</color> expirou"); } private static List<PlayerMatch> FindByNameQuery(string query) { string value = query.ToLowerInvariant(); List<PlayerMatch> list = new List<PlayerMatch>(); List<ZNetPeer> peers = ZNet.instance.GetPeers(); foreach (ZNetPeer item in peers) { if (item.m_playerName != null && item.m_playerName.ToLowerInvariant().Contains(value)) { list.Add(new PlayerMatch { PeerUid = item.m_uid, PlayerName = item.m_playerName }); } } if (ZNet.instance.IsServer() && (Object)(object)Player.m_localPlayer != (Object)null) { string playerName = Player.m_localPlayer.GetPlayerName(); if (playerName != null && playerName.ToLowerInvariant().Contains(value)) { list.Add(new PlayerMatch { PeerUid = ZNet.GetUID(), PlayerName = playerName }); } } return list; } private static void SendNotifyError(long peerUid, string errorMessage) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write((byte)0); val.Write(errorMessage); ZRoutedRpc.instance.InvokeRoutedRPC(peerUid, "VE_TpaNotify", new object[1] { val }); } } public static class RtpManager { private static bool _searching; public static void StartSearch(Player player, float minRange, float maxRange) { if (_searching) { FeedbackHelper.SendError("Já estamos buscando uma posição segura, espere!"); return; } _searching = true; FeedbackHelper.Send("Buscando uma posição segura, espere..."); ((MonoBehaviour)Plugin.Instance).StartCoroutine(SearchCoroutine(player, minRange, maxRange)); } private static IEnumerator SearchCoroutine(Player player, float minRange, float maxRange) { int totalAttempts = 0; int attemptsPerFrame = 100; int maxTotalAttempts = 10000; while (totalAttempts < maxTotalAttempts) { if ((Object)(object)player == (Object)null) { _searching = false; yield break; } for (int i = 0; i < attemptsPerFrame; i++) { totalAttempts++; Vector3 candidate = RandomRingPoint(((Component)player).transform.position, minRange, maxRange); if (IsSafePosition(candidate.x, candidate.z, out var groundY)) { _searching = false; Vector3 safePos = new Vector3(candidate.x, groundY + 1f, candidate.z); TeleportHelper.Teleport(player, safePos); FeedbackHelper.Send("Teleportado para uma posição aleatória!"); yield break; } } if (totalAttempts % 2000 == 0) { FeedbackHelper.Send($"Ainda buscando... ({totalAttempts} tentativas)"); } yield return null; } _searching = false; FeedbackHelper.SendError("Não foi possível encontrar uma posição segura. Tente novamente!"); } private static Vector3 RandomRingPoint(Vector3 center, float minR, float maxR) { //IL_001f: 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) //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_004f: Unknown result type (might be due to invalid IL or missing references) float num = Random.Range(0f, 360f) * ((float)Math.PI / 180f); float num2 = Random.Range(minR, maxR); float num3 = center.x + Mathf.Cos(num) * num2; float num4 = center.z + Mathf.Sin(num) * num2; return new Vector3(num3, 0f, num4); } private static bool IsSafePosition(float x, float z, out float groundY) { //IL_002c: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Invalid comparison between Unknown and I4 groundY = 0f; if (WorldGenerator.instance == null) { return false; } Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(x, 0f, z); Biome biome = WorldGenerator.instance.GetBiome(val); if ((int)biome == 256) { return false; } groundY = WorldGenerator.instance.GetHeight(x, z); if (groundY < 30f) { return false; } float num = Mathf.Sqrt(x * x + z * z); if (num > 10000f) { return false; } return true; } } public static class TeleportHelper { public static void Teleport(Player player, Vector3 destination) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) BackManager.SavePosition(player); ((Character)player).TeleportTo(destination, ((Component)player).transform.rotation, true); Plugin.Log.LogInfo((object)$"[TeleportHelper] {player.GetPlayerName()} teleportado para {destination}"); } } public static class TpaManager { public struct PendingRequest { public long RequesterPeerUid; public string RequesterName; public long TargetPeerUid; public string TargetName; public DateTime ExpiresAt; } private static readonly Dictionary<long, PendingRequest> _pending = new Dictionary<long, PendingRequest>(); public static bool TryAddRequest(long requesterKey, PendingRequest req) { if (_pending.ContainsKey(requesterKey)) { return false; } _pending[requesterKey] = req; return true; } public static bool HasPendingFromRequester(long requesterKey) { return _pending.ContainsKey(requesterKey); } public static bool TryConsumeByTarget(long targetPeerUid, out PendingRequest req) { foreach (KeyValuePair<long, PendingRequest> item in _pending) { if (item.Value.TargetPeerUid == targetPeerUid) { req = item.Value; _pending.Remove(item.Key); return true; } } req = default(PendingRequest); return false; } public static bool TryGetPending(long requesterKey, out PendingRequest req) { return _pending.TryGetValue(requesterKey, out req); } public static void Remove(long requesterKey) { _pending.Remove(requesterKey); } public static void Clear() { _pending.Clear(); } public static IEnumerator ExpireAfterDelay(long requesterKey, float delaySeconds) { yield return (object)new WaitForSeconds(delaySeconds); if (_pending.TryGetValue(requesterKey, out var req)) { _pending.Remove(requesterKey); ZPackage pkgR = new ZPackage(); pkgR.Write(req.TargetName); ZRoutedRpc.instance.InvokeRoutedRPC(req.RequesterPeerUid, "VE_TpaExpireRequester", new object[1] { pkgR }); ZPackage pkgT = new ZPackage(); pkgT.Write(req.RequesterName); ZRoutedRpc.instance.InvokeRoutedRPC(req.TargetPeerUid, "VE_TpaExpireTarget", new object[1] { pkgT }); } } } }