diff --git a/DevourClient/ClientMain.cs b/DevourClient/ClientMain.cs index 01c320e..9bccfcd 100644 --- a/DevourClient/ClientMain.cs +++ b/DevourClient/ClientMain.cs @@ -4,10 +4,13 @@ using System.Threading.Tasks; using Il2CppPhoton.Bolt; using UnityEngine; using Il2Cpp; +using System; +using System.Collections; +using System.Collections.Generic; namespace DevourClient { - public class ClientMain : MonoBehaviour + public class ClientMain : MonoBehaviour, IDisposable { public ClientMain(IntPtr ptr) : base(ptr) @@ -25,7 +28,7 @@ namespace DevourClient Players = 6 } - static Rect windowRect = new Rect(Settings.Settings.x + 10, Settings.Settings.y + 10, 700, 700); + static Rect windowRect = new Rect(Settings.Settings.x + 10, Settings.Settings.y + 10, 800, 750); static CurrentTab current_tab = CurrentTab.Visuals; static bool flashlight_toggle = false; @@ -34,13 +37,12 @@ namespace DevourClient static bool azazel_esp_colorpick = false; static bool spoofLevel = false; static float spoofLevelValue = 0; - static bool change_server_name = false; - static bool change_steam_name = false; + + // UI variables static bool fly = false; static float fly_speed = 5; static bool fastMove = false; static float _PlayerSpeedMultiplier = 1; - public static float lobbySize = 4; public static bool _IsAutoRespawn = false; public static bool unlimitedUV = false; public static bool exp_modifier = false; @@ -53,7 +55,6 @@ namespace DevourClient static bool azazel_esp = false; static bool azazel_skel_esp = false; static bool azazel_snapline = false; - static bool spam_message = false; static bool item_esp = false; static bool goat_rat_esp = false; static bool demon_esp = false; @@ -64,46 +65,40 @@ namespace DevourClient static bool should_show_start_message = true; static Texture2D crosshairTexture = default!; - private static string spamMessageText = "Deez Nutz"; - private static string steamNameText = "patate"; - private static string serverNameText = "patate on top !"; - private static float spamMessageInterval = 5f; // Default send interval in seconds - private static float spamMessageTimer = 0f; // Timer + private static int frameCount = 0; + private static int lastMemoryLog = 0; + private const int GC_GEN0_INTERVAL = 300; + private const int GC_FULL_INTERVAL = 3600; + private const int MEMORY_LOG_INTERVAL = 1800; public void Start() { MelonLogger.Msg("For the Queen !"); - Hacks.Misc.ShowMessageBox("For the Queen !"); MelonLogger.Warning("Made with <3 by patate and Jadis."); - Hacks.Misc.ShowMessageBox("Made with <3 by patate and Jadis."); MelonLogger.Warning("Github : https://github.com/ALittlePatate/DevourClient"); - Hacks.Misc.ShowMessageBox("Github : https://github.com/ALittlePatate/DevourClient"); MelonLogger.Warning("Note : if you payed for this you most likely got scammed."); - Hacks.Misc.ShowMessageBox("Note : if you payed for this you most likely got scammed."); + + long startMemory = GC.GetTotalMemory(false); + MelonLogger.Msg($"[Memory Monitor] Startup managed memory: {startMemory / 1024 / 1024} MB"); crosshairTexture = Helpers.GUIHelper.GetCircularTexture(5, 5); - // Start all coroutines using new coroutine management mechanism Helpers.Entities.StartAllCoroutines(); - } - public void OnDestroy() - { - // Stop all coroutines when component is destroyed - Helpers.Entities.StopAllCoroutines(); - - // Clean up other resources - if (crosshairTexture != null) - { - UnityEngine.Object.Destroy(crosshairTexture); - crosshairTexture = null; - } - } - - public void OnApplicationQuit() - { - // Stop all coroutines when application quits - Helpers.Entities.StopAllCoroutines(); + Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetLocalPlayer())); + Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetGoatsAndRats())); + Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetSurvivalInteractables())); + Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetKeys())); + Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetDemons())); + Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetSpiders())); + Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetGhosts())); + Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetBoars())); + Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetCorpses())); + Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetCrows())); + Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetLumps())); + Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetAzazels())); + Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetAllPlayers())); + Helpers.Entities.RegisterCoroutine(MelonCoroutines.Start(Helpers.Entities.GetMonkeys())); } public void Update() @@ -159,31 +154,13 @@ namespace DevourClient } else { + if (crosshair && in_game_cache) { in_game_cache = false; } } - if (spam_message) - { - spamMessageTimer += Time.deltaTime; - if (spamMessageTimer >= spamMessageInterval) - { - Hacks.Misc.MessageSpam(spamMessageText); - spamMessageTimer = 0f; // Reset timer - } - } - else - { - spamMessageTimer = 0f; // Reset timer when disabled - } - - if (spoofLevel) - { - Hacks.Misc.SetRank((int)spoofLevelValue); - } - if (Input.GetKeyDown(Settings.Settings.flyKey)) { fly = !fly; @@ -237,7 +214,30 @@ namespace DevourClient { Helpers.Entities.LocalPlayer_.p_GameObject.GetComponent().TimeScale = _PlayerSpeedMultiplier; } - catch { return; } + catch { return; } + } + + + frameCount++; + + if (frameCount % GC_GEN0_INTERVAL == 0) + { + GC.Collect(0, GCCollectionMode.Optimized); + } + + if (frameCount % GC_FULL_INTERVAL == 0) + { + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); + frameCount = 0; + } + + if (frameCount - lastMemoryLog >= MEMORY_LOG_INTERVAL) + { + long memoryUsed = GC.GetTotalMemory(false); + MelonLogger.Msg($"[Memory Monitor] Current managed memory: {memoryUsed / 1024 / 1024} MB | Frame: {frameCount}"); + lastMemoryLog = frameCount; } } @@ -249,72 +249,37 @@ namespace DevourClient should_show_start_message = false; } - // Update error message display time - if (Settings.Settings.showErrorMessage) + // 保存原始GUI状态 + Color originalBackgroundColor = GUI.backgroundColor; + GUISkin originalSkin = GUI.skin; + + try { - Settings.Settings.errorMessageDisplayTime += Time.deltaTime; - if (Settings.Settings.errorMessageDisplayTime >= Settings.Settings.errorMessageMaxDisplayTime) - { - Settings.Settings.showErrorMessage = false; - } - } + GUI.backgroundColor = Color.grey; - // Render error message box - if (Settings.Settings.showErrorMessage) - { - // Set message box style - GUIStyle errorBoxStyle = new GUIStyle(GUI.skin.box); - errorBoxStyle.normal.background = GUIHelper.MakeTex(2, 2, new Color(0.8f, 0.2f, 0.2f, 0.9f)); - errorBoxStyle.normal.textColor = Color.white; - errorBoxStyle.fontSize = 14; - errorBoxStyle.padding = new RectOffset(10, 10, 10, 10); - errorBoxStyle.wordWrap = true; - errorBoxStyle.clipping = TextClipping.Overflow; + // 设置按钮样式 + GUI.skin.button.normal.background = GUIHelper.MakeTex(2, 2, Color.black); + GUI.skin.button.normal.textColor = Color.white; + GUI.skin.button.hover.background = GUIHelper.MakeTex(2, 2, Color.green); + GUI.skin.button.hover.textColor = Color.black; - // Calculate message box position (bottom center) - float boxWidth = 400f; - float boxHeight = 60f; - float boxX = (Screen.width - boxWidth) / 2f; - float boxY = Screen.height - boxHeight - 20f; + // 设置切换按钮样式 + GUI.skin.toggle.onNormal.textColor = Color.yellow; - // Draw message box - GUI.Box(new Rect(boxX, boxY, boxWidth, boxHeight), Settings.Settings.errorMessage, errorBoxStyle); - } + // 设置文本框样式 - 这是关键修复 + GUI.skin.textField.normal.background = GUIHelper.MakeTex(2, 2, new Color(0.2f, 0.2f, 0.2f, 0.8f)); + GUI.skin.textField.normal.textColor = Color.white; + GUI.skin.textField.focused.background = GUIHelper.MakeTex(2, 2, new Color(0.3f, 0.3f, 0.3f, 0.9f)); + GUI.skin.textField.focused.textColor = Color.yellow; + GUI.skin.textField.border = new RectOffset(2, 2, 2, 2); - GUI.backgroundColor = Color.grey; + // 设置标签样式 + GUI.skin.label.normal.textColor = Color.white; - // Set button style - var buttonStyle = new GUIStyle(GUI.skin.button); - buttonStyle.normal.background = GUIHelper.MakeTex(2, 2, Color.black); - buttonStyle.normal.textColor = Color.white; - buttonStyle.border = new RectOffset(2, 2, 2, 2); - GUI.skin.button = buttonStyle; + // 设置滑块样式 + GUI.skin.horizontalSlider.normal.background = GUIHelper.MakeTex(2, 2, new Color(0.3f, 0.3f, 0.3f, 0.8f)); + GUI.skin.horizontalSliderThumb.normal.background = GUIHelper.MakeTex(2, 2, Color.white); - // Set label style - var labelStyle = new GUIStyle(GUI.skin.label); - labelStyle.normal.textColor = Color.white; - labelStyle.border = new RectOffset(2, 2, 2, 2); - GUI.skin.label = labelStyle; - - // Set text field style - var textFieldStyle = new GUIStyle(GUI.skin.textField); - textFieldStyle.normal.textColor = Color.white; - textFieldStyle.border = new RectOffset(2, 2, 2, 2); - GUI.skin.textField = textFieldStyle; - - // Set slider style - var sliderStyle = new GUIStyle(GUI.skin.horizontalSlider); - sliderStyle.border = new RectOffset(2, 2, 2, 2); - GUI.skin.horizontalSlider = sliderStyle; - - // Set toggle style - var toggleStyle = new GUIStyle(GUI.skin.toggle); - toggleStyle.normal.textColor = Color.white; - toggleStyle.border = new RectOffset(2, 2, 2, 2); - toggleStyle.onNormal.textColor = Color.yellow; - GUI.skin.toggle = toggleStyle; - - //from https://www.unknowncheats.me/forum/unity/437277-mono-internal-optimisation-tips.html if (UnityEngine.Event.current.type == EventType.Repaint) { if (player_esp || player_snapline || player_skel_esp) @@ -432,6 +397,13 @@ namespace DevourClient Render.Render.DrawNameESP(lump.transform.position, "Lump", new Color(1.0f, 0.0f, 0.0f, 1.0f)); } } + foreach (Il2Cpp.MonkeyBehaviour monkey in Helpers.Entities.Monkeys) + { + if (monkey != null) + { + Render.Render.DrawNameESP(monkey.transform.position, "Monkey", new Color(1.0f, 0.0f, 0.0f, 1.0f)); + } + } } if (azazel_esp || azazel_snapline || azazel_skel_esp) @@ -450,7 +422,7 @@ namespace DevourClient } } - if (crosshair && in_game_cache) //&& !Player.IsPlayerCrawling()) + if (crosshair && in_game_cache) { const float crosshairSize = 4; @@ -466,11 +438,21 @@ namespace DevourClient } } - if (Settings.Settings.menu_enable) //Si on appuie sur INSERT + if (Settings.Settings.menu_enable) { windowRect = GUI.Window(0, windowRect, (GUI.WindowFunction)Tabs, "DevourClient"); } - + } + catch (System.Exception ex) + { + MelonLogger.Msg($"OnGUI Error: {ex.Message}"); + } + finally + { + // 恢复原始GUI状态 + GUI.backgroundColor = originalBackgroundColor; + GUI.skin = originalSkin; + } } public static void Tabs(int windowID) @@ -557,7 +539,7 @@ namespace DevourClient { flashlight_colorpick = !flashlight_colorpick; MelonLogger.Msg("Flashlight color picker : " + flashlight_colorpick.ToString()); - Hacks.Misc.ShowMessageBox("Flashlight color picker : " + flashlight_colorpick.ToString()); + } if (flashlight_colorpick) @@ -580,7 +562,6 @@ namespace DevourClient { Hacks.Misc.TPItems(); MelonLogger.Msg("TP Items!"); - Hacks.Misc.ShowMessageBox("TP Items!"); } if (GUI.Button(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 110, 130, 30), "Freeze azazel")) @@ -590,8 +571,6 @@ namespace DevourClient GUI.Label(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 150, 120, 30), "Azazel & Demons"); - // azazel - if (GUI.Button(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 180, 60, 25), "Sam") && Player.IsInGameOrLobby() && BoltNetwork.IsServer) { Hacks.Misc.SpawnAzazel((PrefabId)BoltPrefabs.AzazelSam); @@ -622,7 +601,10 @@ namespace DevourClient BoltNetwork.Instantiate(BoltPrefabs.AzazelApril, Player.GetPlayer().transform.position, Quaternion.identity); } - // demon + if (GUI.Button(new Rect(Settings.Settings.x + 430, Settings.Settings.y + 180, 60, 25), "Kai") && Player.IsInGameOrLobby() && BoltNetwork.IsServer) + { + BoltNetwork.Instantiate(BoltPrefabs.AzazelKai, Player.GetPlayer().transform.position, Quaternion.identity); + } if (GUI.Button(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 220, 60, 25), "Ghost") && Player.IsInGameOrLobby() && BoltNetwork.IsServer) { @@ -659,7 +641,10 @@ namespace DevourClient BoltNetwork.Instantiate(BoltPrefabs.ManorLump, Player.GetPlayer().transform.position, Quaternion.identity); } - // Animal + if (GUI.Button(new Rect(Settings.Settings.x + 500, Settings.Settings.y + 220, 60, 25), "Monkey") && BoltNetwork.IsServer && Player.IsInGameOrLobby()) + { + BoltNetwork.Instantiate(BoltPrefabs.Monkey, Player.GetPlayer().transform.position, Quaternion.identity); + } if (GUI.Button(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 260, 60, 25), "Rat")) { @@ -712,7 +697,6 @@ namespace DevourClient { Hacks.Misc.InstantWin(); MelonLogger.Msg("EZ Win"); - Hacks.Misc.ShowMessageBox("EZ Win"); } if (GUI.Button(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 110, 150, 30), "Burn a ritual object")) @@ -747,7 +731,6 @@ namespace DevourClient catch { MelonLogger.Msg("Azazel not found !"); - Hacks.Misc.ShowMessageBox("Azazel not found !"); } } @@ -768,7 +751,6 @@ namespace DevourClient catch { MelonLogger.Msg("Azazel not found !"); - Hacks.Misc.ShowMessageBox("Azazel not found !"); } } @@ -789,7 +771,6 @@ namespace DevourClient catch { MelonLogger.Msg("Azazel not found !"); - Hacks.Misc.ShowMessageBox("Azazel not found !"); } } @@ -816,7 +797,6 @@ namespace DevourClient catch { MelonLogger.Msg("Azazel not found !"); - Hacks.Misc.ShowMessageBox("Azazel not found !"); } } @@ -838,7 +818,6 @@ namespace DevourClient catch { MelonLogger.Msg("Azazel not found !"); - Hacks.Misc.ShowMessageBox("Azazel not found !"); } } @@ -865,7 +844,6 @@ namespace DevourClient catch { MelonLogger.Msg("Azazel not found !"); - Hacks.Misc.ShowMessageBox("Azazel not found !"); } } @@ -888,7 +866,6 @@ namespace DevourClient if (realm == null) { MelonLogger.Warning("realm was null."); - Hacks.Misc.ShowMessageBox("realm was null."); return; } @@ -920,7 +897,6 @@ namespace DevourClient if (realm == null) { MelonLogger.Warning("realm was null."); - Hacks.Misc.ShowMessageBox("realm was null."); return; } @@ -945,41 +921,66 @@ namespace DevourClient infinite_mirrors = GUI.Toggle(new Rect(Settings.Settings.x + 370, Settings.Settings.y + 150, 150, 20), infinite_mirrors, "Infinite mirrors"); break; + + case "Carnival": + if (GUI.Button(new Rect(Settings.Settings.x + 190, Settings.Settings.y + 70, 150, 30), "TP to Azazel")) + { + try + { + Il2Cpp.NolanBehaviour nb = Player.GetPlayer(); + + nb.TeleportTo(Helpers.Map.GetAzazel().transform.position, Quaternion.identity); + } + catch + { + MelonLogger.Msg("Azazel not found !"); + } + } + + if (GUI.Button(new Rect(Settings.Settings.x + 190, Settings.Settings.y + 110, 150, 30), "Despawn Monkeys")) + { + Hacks.Misc.DespawnMonkeys(); + } + break; } - // load map GUI.Label(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 210, 100, 30), "Load Map: "); - if (GUI.Button(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 240, 100, 30), "Farmhouse") && BoltNetwork.IsServer) + if (GUI.Button(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 240, 90, 30), "Farmhouse") && BoltNetwork.IsServer) { Helpers.Map.LoadMap("Devour"); } - if (GUI.Button(new Rect(Settings.Settings.x + 120, Settings.Settings.y + 240, 100, 30), "Asylum") && BoltNetwork.IsServer) + if (GUI.Button(new Rect(Settings.Settings.x + 110, Settings.Settings.y + 240, 90, 30), "Asylum") && BoltNetwork.IsServer) { Helpers.Map.LoadMap("Molly"); } - if (GUI.Button(new Rect(Settings.Settings.x + 230, Settings.Settings.y + 240, 100, 30), "Inn") && BoltNetwork.IsServer) + if (GUI.Button(new Rect(Settings.Settings.x + 210, Settings.Settings.y + 240, 90, 30), "Inn") && BoltNetwork.IsServer) { Helpers.Map.LoadMap("Inn"); } - if (GUI.Button(new Rect(Settings.Settings.x + 340, Settings.Settings.y + 240, 100, 30), "Town") && BoltNetwork.IsServer) + if (GUI.Button(new Rect(Settings.Settings.x + 310, Settings.Settings.y + 240, 90, 30), "Town") && BoltNetwork.IsServer) { Helpers.Map.LoadMap("Town"); } - if (GUI.Button(new Rect(Settings.Settings.x + 450, Settings.Settings.y + 240, 100, 30), "Slaughterhouse") && BoltNetwork.IsServer) + if (GUI.Button(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 280, 90, 30), "Slaughterhouse") && BoltNetwork.IsServer) { Helpers.Map.LoadMap("Slaughterhouse"); } - if (GUI.Button(new Rect(Settings.Settings.x + 560, Settings.Settings.y + 240, 100, 30), "Manor") && BoltNetwork.IsServer) + if (GUI.Button(new Rect(Settings.Settings.x + 110, Settings.Settings.y + 280, 90, 30), "Manor") && BoltNetwork.IsServer) { Helpers.Map.LoadMap("Manor"); } + if (GUI.Button(new Rect(Settings.Settings.x + 210, Settings.Settings.y + 280, 90, 30), "Carnival") && BoltNetwork.IsServer) + { + Helpers.Map.LoadMap("Carnival"); + } + } private static void EspTab() @@ -1136,7 +1137,7 @@ namespace DevourClient } } - if (GUILayout.Button("Shovel")) + if (GUILayout.Button("Spade")) { if (BoltNetwork.IsServer && !Player.IsInGame()) { @@ -1159,6 +1160,29 @@ namespace DevourClient Hacks.Misc.CarryObject("SurvivalCake"); } } + if (GUILayout.Button("MusicBox")) + { + if (BoltNetwork.IsServer && !Player.IsInGame()) + { + BoltNetwork.Instantiate(BoltPrefabs.SurvivalMusicBox, Player.GetPlayer().transform.position, Quaternion.identity); + } + else + { + Hacks.Misc.CarryObject("MusicBox-Idle"); + } + } + if (GUILayout.Button("Coin")) + { + if (BoltNetwork.IsServer && !Player.IsInGame()) + { + BoltNetwork.Instantiate(BoltPrefabs.SurvivalCoin, Player.GetPlayer().transform.position, Quaternion.identity); + } + else + { + Hacks.Misc.CarryObject("SurvivalCoin"); + } + } + GUILayout.EndScrollView(); GUILayout.EndVertical(); @@ -1231,29 +1255,40 @@ namespace DevourClient } } - if (GUILayout.Button("Dirty head")) - { - if (BoltNetwork.IsServer && !Player.IsInGame()) - { - BoltNetwork.Instantiate(BoltPrefabs.SurvivalHead, Player.GetPlayer().transform.position, Quaternion.identity); - } - else - { - Hacks.Misc.CarryObject("SurvivalHead"); - } - } + // if (GUILayout.Button("Dirty head")) + // { + // if (BoltNetwork.IsServer && !Player.IsInGame()) + // { + // BoltNetwork.Instantiate(BoltPrefabs.SurvivalHead, Player.GetPlayer().transform.position, Quaternion.identity); + // } + // else + // { + // Hacks.Misc.CarryObject("SurvivalHead"); + // } + // } - if (GUILayout.Button("Clean head")) + // if (GUILayout.Button("Clean head")) + // { + // if (BoltNetwork.IsServer && !Player.IsInGame()) + // { + // BoltNetwork.Instantiate(BoltPrefabs.SurvivalCleanHead, Player.GetPlayer().transform.position, Quaternion.identity); + // } + // else + // { + // Hacks.Misc.CarryObject("SurvivalCleanHead"); + // } + // } + if (GUILayout.Button("Doll Head")) { if (BoltNetwork.IsServer && !Player.IsInGame()) { - BoltNetwork.Instantiate(BoltPrefabs.SurvivalCleanHead, Player.GetPlayer().transform.position, Quaternion.identity); + BoltNetwork.Instantiate(BoltPrefabs.SurvivalDollHead, Player.GetPlayer().transform.position, Quaternion.identity); } else { - Hacks.Misc.CarryObject("SurvivalCleanHead"); + Hacks.Misc.CarryObject("SurvivalDollHead"); } - } + } GUILayout.EndScrollView(); GUILayout.EndVertical(); @@ -1545,105 +1580,67 @@ namespace DevourClient private static void MiscTab() { - if (GUI.Button(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 70, 150, 30), "Unlock Achievements")) + // === 游戏功能按钮区域 (左上) === + if (GUI.Button(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 70, 140, 25), "Unlock Achievements")) { Thread AchievementsThread = new Thread(new ThreadStart(Hacks.Unlock.Achievements)); AchievementsThread.Start(); - MelonLogger.Msg("Achievements Unlocked!"); - Hacks.Misc.ShowMessageBox("Achievements Unlocked!"); + MelonLogger.Msg("Achievements unlocked!"); + Hacks.Misc.ShowMessageBox("Achievements unlocked!"); } - if (GUI.Button(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 110, 150, 30), "Unlock Doors")) + if (GUI.Button(new Rect(Settings.Settings.x + 160, Settings.Settings.y + 70, 140, 25), "Unlock Doors")) { Hacks.Unlock.Doors(); - MelonLogger.Msg("Doors Unlocked!"); - Hacks.Misc.ShowMessageBox("Doors Unlocked!"); + MelonLogger.Msg("Doors unlocked!"); + Hacks.Misc.ShowMessageBox("Doors unlocked!"); } - if (GUI.Button(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 150, 150, 30), "TP Keys") && Player.IsInGame()) + if (GUI.Button(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 105, 140, 25), "Teleport Keys") && Player.IsInGame()) { Hacks.Misc.TPKeys(); - MelonLogger.Msg("Here are your keys!"); - Hacks.Misc.ShowMessageBox("Here are your keys!"); + MelonLogger.Msg("Keys teleported!"); + Hacks.Misc.ShowMessageBox("Keys teleported!"); } - if (GUI.Button(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 190, 150, 30), "Make Random Noise")) + if (GUI.Button(new Rect(Settings.Settings.x + 160, Settings.Settings.y + 105, 140, 25), "Play Random Sound")) { Hacks.Misc.PlaySound(); - MelonLogger.Msg("Playing a random sound!"); - Hacks.Misc.ShowMessageBox("Playing a random sound!"); + MelonLogger.Msg("Playing random sound!"); + Hacks.Misc.ShowMessageBox("Playing random sound!"); } - spam_message = GUI.Toggle(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 240, 140, 30), spam_message, "Chat spam"); - if (spam_message) - { - spamMessageText = GUI.TextField(new Rect(Settings.Settings.x + 160, Settings.Settings.y + 240, 200, 30), spamMessageText); - GUI.Label(new Rect(Settings.Settings.x + 370, Settings.Settings.y + 240, 60, 30), "Send Interval(s):"); - spamMessageInterval = GUI.HorizontalSlider(new Rect(Settings.Settings.x + 440, Settings.Settings.y + 240, 100, 30), spamMessageInterval, 1f, 30f); - GUI.Label(new Rect(Settings.Settings.x + 550, Settings.Settings.y + 240, 60, 30), ((int)spamMessageInterval).ToString()); - } + // === 基础开关区域 (左中) === + _walkInLobby = GUI.Toggle(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 150, 140, 20), _walkInLobby, "Walk In Lobby"); + _IsAutoRespawn = GUI.Toggle(new Rect(Settings.Settings.x + 160, Settings.Settings.y + 150, 140, 20), _IsAutoRespawn, "Auto Respawn"); - change_steam_name = GUI.Toggle(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 270, 140, 30), change_steam_name, "Change Steam Name"); - if (change_steam_name) - { - steamNameText = GUI.TextField(new Rect(Settings.Settings.x + 160, Settings.Settings.y + 270, 200, 30), steamNameText); - if (GUI.Button(new Rect(Settings.Settings.x + 370, Settings.Settings.y + 270, 60, 30), "Apply")) - { - Hacks.Misc.SetSteamName(steamNameText); - } - } - - change_server_name = GUI.Toggle(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 300, 140, 30), change_server_name, "Change Server Name"); - if (change_server_name) - { - serverNameText = GUI.TextField(new Rect(Settings.Settings.x + 160, Settings.Settings.y + 300, 200, 30), serverNameText); - if (GUI.Button(new Rect(Settings.Settings.x + 370, Settings.Settings.y + 300, 60, 30), "Apply")) - { - Hacks.Misc.SetServerName(serverNameText); - } - } - - _walkInLobby = GUI.Toggle(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 330, 140, 30), _walkInLobby, "Walk In Lobby"); - _IsAutoRespawn = GUI.Toggle(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 360, 140, 30), _IsAutoRespawn, "Auto Respawn"); - - fly = GUI.Toggle(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 400, 40, 20), fly, "Fly"); - if (GUI.Button(new Rect(Settings.Settings.x + 60, Settings.Settings.y + 400, 40, 20), Settings.Settings.flyKey.ToString())) + // === 飞行控制区域 (左中下) === + fly = GUI.Toggle(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 180, 40, 20), fly, "Fly"); + if (GUI.Button(new Rect(Settings.Settings.x + 60, Settings.Settings.y + 180, 50, 20), Settings.Settings.flyKey.ToString())) { Settings.Settings.flyKey = Settings.Settings.GetKey(); } + GUI.Label(new Rect(Settings.Settings.x + 120, Settings.Settings.y + 180, 80, 20), "Speed:"); + fly_speed = GUI.HorizontalSlider(new Rect(Settings.Settings.x + 170, Settings.Settings.y + 185, 80, 10), fly_speed, 5f, 20f); + GUI.Label(new Rect(Settings.Settings.x + 260, Settings.Settings.y + 180, 40, 20), ((int)fly_speed).ToString()); - fly_speed = GUI.HorizontalSlider(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 430, 100, 10), fly_speed, 5f, 20f); - GUI.Label(new Rect(Settings.Settings.x + 120, Settings.Settings.y + 425, 100, 30), ((int)fly_speed).ToString()); + // === 等级欺骗区域 (左下) === + spoofLevel = GUI.Toggle(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 210, 100, 20), spoofLevel, "Spoof Level"); + spoofLevelValue = GUI.HorizontalSlider(new Rect(Settings.Settings.x + 120, Settings.Settings.y + 215, 80, 10), spoofLevelValue, 0f, 666f); + GUI.Label(new Rect(Settings.Settings.x + 210, Settings.Settings.y + 210, 50, 20), ((int)spoofLevelValue).ToString()); + // === 经验修改区域 (左下) === + exp_modifier = GUI.Toggle(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 240, 100, 20), exp_modifier, "Exp Modifier"); + exp = GUI.HorizontalSlider(new Rect(Settings.Settings.x + 120, Settings.Settings.y + 245, 80, 10), exp, 1000f, 6000f); + GUI.Label(new Rect(Settings.Settings.x + 210, Settings.Settings.y + 240, 50, 20), ((int)exp).ToString()); - spoofLevel = GUI.Toggle(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 470, 150, 20), spoofLevel, "Spoof Level"); - spoofLevelValue = GUI.HorizontalSlider(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 500, 100, 10), spoofLevelValue, 0f, 666f); - GUI.Label(new Rect(Settings.Settings.x + 120, Settings.Settings.y + 495, 100, 30), ((int)spoofLevelValue).ToString()); + // === 速度修改区域 (左下) === + fastMove = GUI.Toggle(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 270, 100, 20), fastMove, "Player Speed"); + _PlayerSpeedMultiplier = GUI.HorizontalSlider(new Rect(Settings.Settings.x + 120, Settings.Settings.y + 275, 80, 10), _PlayerSpeedMultiplier, (int)1f, (int)10f); + GUI.Label(new Rect(Settings.Settings.x + 210, Settings.Settings.y + 270, 50, 20), ((int)_PlayerSpeedMultiplier).ToString()); - - exp_modifier = GUI.Toggle(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 540, 150, 20), exp_modifier, "EXP Modifier"); - exp = GUI.HorizontalSlider(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 570, 100, 10), exp, 1000f, 6000f); - GUI.Label(new Rect(Settings.Settings.x + 120, Settings.Settings.y + 565, 100, 30), ((int)exp).ToString()); - - - fastMove = GUI.Toggle(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 610, 150, 20), fastMove, "Player Speed"); - _PlayerSpeedMultiplier = GUI.HorizontalSlider(new Rect(Settings.Settings.x + 10, Settings.Settings.y + 640, 100, 10), _PlayerSpeedMultiplier, (int)1f, (int)10f); - GUI.Label(new Rect(Settings.Settings.x + 120, Settings.Settings.y + 635, 100, 30), ((int)_PlayerSpeedMultiplier).ToString()); - - GUI.Label(new Rect(Settings.Settings.x + 295, Settings.Settings.y + 70, 150, 30), "Max players"); - lobbySize = GUI.HorizontalSlider(new Rect(Settings.Settings.x + 295, Settings.Settings.y + 90, 100, 10), lobbySize, (int)0f, (int)30f); - GUI.Label(new Rect(Settings.Settings.x + 405, Settings.Settings.y + 85, 100, 30), ((int)lobbySize).ToString()); - - if (GUI.Button(new Rect(Settings.Settings.x + 285, Settings.Settings.y + 110, 150, 30), "Create server")) - { - MelonLogger.Msg("Creating the server..."); - Hacks.Misc.ShowMessageBox("Creating the server..."); - Hacks.Misc.CreateCustomizedLobby((int)lobbySize); - MelonLogger.Msg("Done !"); - Hacks.Misc.ShowMessageBox("Done !"); - } } private static void PlayersTab() @@ -1657,7 +1654,6 @@ namespace DevourClient if (bp == null || bp.Name == "") { MelonLogger.Warning("players is null"); - Hacks.Misc.ShowMessageBox("players is null"); continue; } @@ -1710,5 +1706,69 @@ namespace DevourClient } } + private void OnDestroy() + { + try + { + base.StopAllCoroutines(); + + Dispose(); + } + catch (Exception ex) + { + MelonLogger.Error($"Error in OnDestroy: {ex.Message}"); + } + } + + private void OnApplicationQuit() + { + try + { + Dispose(); + } + catch (Exception ex) + { + MelonLogger.Error($"Error in OnApplicationQuit: {ex.Message}"); + } + } + + public void Dispose() + { + try + { + MelonLogger.Msg("Starting ClientMain cleanup..."); + + long memoryBeforeCleanup = GC.GetTotalMemory(false); + MelonLogger.Msg($"[Memory Monitor] Pre-cleanup managed memory: {memoryBeforeCleanup / 1024 / 1024} MB"); + + Helpers.Entities.StopAllCoroutines(); + + if (crosshairTexture != null) + { + UnityEngine.Object.DestroyImmediate(crosshairTexture); + crosshairTexture = null; + } + + Helpers.GUIHelper.Cleanup(); + + Helpers.Entities.CleanupCachedObjects(); + + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); + + long memoryAfterCleanup = GC.GetTotalMemory(true); + long memoryFreed = memoryBeforeCleanup - memoryAfterCleanup; + MelonLogger.Msg($"[Memory Monitor] Post-cleanup managed memory: {memoryAfterCleanup / 1024 / 1024} MB"); + MelonLogger.Msg($"[Memory Monitor] Memory freed: {memoryFreed / 1024 / 1024} MB"); + + MelonLogger.Msg("ClientMain disposed successfully."); + } + catch (Exception ex) + { + MelonLogger.Error($"Error disposing ClientMain: {ex.Message}"); + } + } } } + diff --git a/DevourClient/DevourClient.csproj b/DevourClient/DevourClient.csproj index 91b5fbf..a9a350e 100644 --- a/DevourClient/DevourClient.csproj +++ b/DevourClient/DevourClient.csproj @@ -12,4 +12,78 @@ 0 + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\net6\0Harmony.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\Il2CppAssemblies\Assembly-CSharp.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\Il2CppAssemblies\Il2CppBehaviorDesigner.Runtime.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\Il2CppAssemblies\Il2Cppbolt.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\Il2CppAssemblies\Il2Cppbolt.user.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\Il2CppAssemblies\Il2Cppcom.rlabrecque.steamworks.net.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\net6\Il2CppInterop.Runtime.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\Il2CppAssemblies\Il2Cppmscorlib.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\Il2CppAssemblies\Il2CppOpsive.UltimateCharacterController.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\Il2CppAssemblies\Il2Cppudpkit.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\Il2CppAssemblies\Il2Cppudpkit.common.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\Il2CppAssemblies\Il2Cppudpkit.platform.photon.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\net6\MelonLoader.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\Il2CppAssemblies\UnityEngine.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\Il2CppAssemblies\UnityEngine.AnimationModule.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\Il2CppAssemblies\UnityEngine.CoreModule.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\Il2CppAssemblies\UnityEngine.HotReloadModule.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\Il2CppAssemblies\UnityEngine.IMGUIModule.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\Il2CppAssemblies\UnityEngine.InputLegacyModule.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\Il2CppAssemblies\UnityEngine.InputModule.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\Il2CppAssemblies\UnityEngine.PhysicsModule.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\Il2CppAssemblies\UnityEngine.UI.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\Il2CppAssemblies\UnityEngine.UIModule.dll + + + E:\SteamLibrary\steamapps\common\Devour\MelonLoader\Il2CppAssemblies\Unity.TextMeshPro.dll + + \ No newline at end of file diff --git a/DevourClient/Hacks/Misc.cs b/DevourClient/Hacks/Misc.cs index ae8e681..29c7285 100644 --- a/DevourClient/Hacks/Misc.cs +++ b/DevourClient/Hacks/Misc.cs @@ -91,12 +91,11 @@ namespace DevourClient.Hacks if (burnAll) { - _slaughterhouseAltarController.SkipToGoat(10); + _slaughterhouseAltarController.BurnGoat(); } else { - _slaughterhouseAltarController.BurnGoat(); - + _slaughterhouseAltarController.SkipToGoat(10); } break; @@ -163,13 +162,11 @@ namespace DevourClient.Hacks else { MelonLogger.Error("azazelBehaviour is null!"); - Hacks.Misc.ShowMessageBox("azazelBehaviour is null!"); } } else { MelonLogger.Error("azazel is null!"); - Hacks.Misc.ShowMessageBox("azazel is null!"); } } } @@ -233,26 +230,6 @@ namespace DevourClient.Hacks _menu.ShowCanvasGroup(_menu.mainMenuCanvasGroup, false); } - public static void SetSteamName(string name) - { - Il2CppHorror.Menu Menu_ = UnityEngine.Object.FindObjectOfType(); - if (Menu_ == null) - { - return; - } - - Menu_.steamName = name; - } - public static void SetServerName(string name) - { - Il2CppHorror.Menu Menu_ = UnityEngine.Object.FindObjectOfType(); - if (Menu_ == null) - { - return; - } - - Menu_.serverNameText.text = name; - } public static void BigFlashlight(bool reset) { @@ -379,23 +356,6 @@ namespace DevourClient.Hacks NolanRank.SetRank(rank); } - public static void MessageSpam(string message) - { - //TOFIX : not spamming anymore :/ - if (Helpers.Player.IsInGame()) - { - Il2Cpp.GameUI game_ui_class = UnityEngine.Object.FindObjectOfType(); - - game_ui_class.textChatInput.text = message; - game_ui_class.OnChatMessageSubmit(); - } - else - { - Il2CppHorror.Menu menu_class = UnityEngine.Object.FindObjectOfType(); - menu_class.textChatInput.text = message; - menu_class.OnChatMessageSubmit(); - } - } public static void DespawnDemons() { @@ -474,13 +434,26 @@ namespace DevourClient.Hacks } } + public static void DespawnMonkeys() + { + foreach (Il2Cpp.MonkeyBehaviour monkey in Helpers.Entities.Monkeys) + { + if (monkey != null) + { + monkey.Despawn(); + } + } + } + public static int ShowMessageBox(string message) { - Settings.Settings.errorMessage = message; - Settings.Settings.errorMessageDisplayTime = 0f; - Settings.Settings.showErrorMessage = true; - return 0; - } + //not used, might be useful, some day + Il2CppHorror.Menu menu = UnityEngine.Object.FindObjectOfType(); + if (menu == null) + return 1; + menu.ShowMessageModal(message); + return 0; + } public static void PlaySound() { diff --git a/DevourClient/Hacks/Unlock.cs b/DevourClient/Hacks/Unlock.cs index daec655..49da7f4 100644 --- a/DevourClient/Hacks/Unlock.cs +++ b/DevourClient/Hacks/Unlock.cs @@ -22,7 +22,9 @@ namespace DevourClient.Hacks } MelonLoader.MelonLogger.Warning("You need to restart your game for the achievements to be unlocked !!!"); - Hacks.Misc.ShowMessageBox("You need to restart your game for the achievements to be unlocked !!!"); + MelonLoader.MelonLogger.Warning("You need to restart your game for the achievements to be unlocked !!!"); + MelonLoader.MelonLogger.Warning("You need to restart your game for the achievements to be unlocked !!!"); + MelonLoader.MelonLogger.Warning("You need to restart your game for the achievements to be unlocked !!!"); } public static void Doors() diff --git a/DevourClient/Helpers/GUIHelper.cs b/DevourClient/Helpers/GUIHelper.cs index 51f6e2e..fd78081 100644 --- a/DevourClient/Helpers/GUIHelper.cs +++ b/DevourClient/Helpers/GUIHelper.cs @@ -1,27 +1,120 @@ using UnityEngine; -using MelonLoader; using System.Collections.Generic; namespace DevourClient.Helpers { - public static class GUIHelper + class GUIHelper { - private static Texture2D previewTexture; - private static GUIStyle boxStyle; - + private static float R; + private static float G; + private static float B; + + private static Texture2D previewTexture = null; private static Dictionary colorTextureCache = new Dictionary(); private static Dictionary circularTextureCache = new Dictionary(); - - public static void Initialize() + private static Color lastPreviewColor = Color.clear; + private static GUIStyle cachedBoxStyle = null; + + public static Color ColorPick(string title, Color color) { - if (previewTexture == null) - { - previewTexture = new Texture2D(1, 1); - boxStyle = new GUIStyle(GUI.skin.box); - } - } + GUI.Label(new Rect(Settings.Settings.x + 195, Settings.Settings.y + 70, 250, 30), title); + R = GUI.VerticalSlider(new Rect(Settings.Settings.x + 240, Settings.Settings.y + 100, 30, 90), color.r, 0f, 1f); + G = GUI.VerticalSlider(new Rect(Settings.Settings.x + 270, Settings.Settings.y + 100, 30, 90), color.g, 0f, 1f); + B = GUI.VerticalSlider(new Rect(Settings.Settings.x + 300, Settings.Settings.y + 100, 30, 90), color.b, 0f, 1f); + + GUI.Label(new Rect(Settings.Settings.x + 240, Settings.Settings.y + 190, 30, 30), "R"); + GUI.Label(new Rect(Settings.Settings.x + 270, Settings.Settings.y + 190, 30, 30), "G"); + GUI.Label(new Rect(Settings.Settings.x + 300, Settings.Settings.y + 190, 30, 30), "B"); + + color = new Color(R, G, B, 1); + + void DrawPreview(Rect position, Color color_to_draw) + { + if (previewTexture == null || lastPreviewColor != color_to_draw) + { + if (previewTexture == null) + { + previewTexture = new Texture2D(1, 1); + } + + previewTexture.SetPixel(0, 0, color_to_draw); + previewTexture.Apply(); + lastPreviewColor = color_to_draw; + } + + if (cachedBoxStyle == null) + { + cachedBoxStyle = new GUIStyle(GUI.skin.box); + } + cachedBoxStyle.normal.background = previewTexture; + GUI.Box(position, GUIContent.none, cachedBoxStyle); + } + + DrawPreview(new Rect(Settings.Settings.x + 195, Settings.Settings.y + 100, 20, 90), color); + + return color; + } + + public static Texture2D MakeTex(int width, int height, Color col) + { + if (colorTextureCache.TryGetValue(col, out Texture2D cachedTexture)) + { + if (cachedTexture != null) + { + return cachedTexture; + } + } + + Color[] pix = new Color[width * height]; + for (int i = 0; i < pix.Length; ++i) + { + pix[i] = col; + } + Texture2D result = new Texture2D(width, height); + result.SetPixels(pix); + result.Apply(); + + colorTextureCache[col] = result; + + return result; + } + + public static Texture2D GetCircularTexture(int width, int height) + { + int cacheKey = width; + + if (circularTextureCache.TryGetValue(cacheKey, out Texture2D cachedTexture)) + { + if (cachedTexture != null) + { + return cachedTexture; + } + } + + Texture2D texture = new Texture2D(width, height); + for (int x = 0; x < texture.width; x++) + { + for (int y = 0; y < texture.height; y++) + { + if (Vector2.Distance(new Vector2(x, y), new Vector2(texture.width / 2, texture.height / 2)) <= texture.width / 2) + { + texture.SetPixel(x, y, Color.white); + } + else + { + texture.SetPixel(x, y, Color.clear); + } + } + } + + texture.Apply(); + + circularTextureCache[cacheKey] = texture; + + return texture; + } public static void Cleanup() { @@ -49,114 +142,5 @@ namespace DevourClient.Helpers } circularTextureCache.Clear(); } - - private static float R; - private static float G; - private static float B; - - public static Color ColorPick(string title, Color color) - { - Initialize(); - - GUILayout.BeginArea(new Rect(Settings.Settings.x + 195, Settings.Settings.y + 70, 250, 250)); - - GUILayout.Label(title); - GUILayout.Space(10); - - - GUILayout.BeginHorizontal(); - GUILayout.Label("R", GUILayout.Width(20)); - R = GUILayout.HorizontalSlider(color.r, 0f, 1f, GUILayout.Width(150)); - GUILayout.Label(((int)(R * 255)).ToString(), GUILayout.Width(30)); - GUILayout.EndHorizontal(); - - - GUILayout.BeginHorizontal(); - GUILayout.Label("G", GUILayout.Width(20)); - G = GUILayout.HorizontalSlider(color.g, 0f, 1f, GUILayout.Width(150)); - GUILayout.Label(((int)(G * 255)).ToString(), GUILayout.Width(30)); - GUILayout.EndHorizontal(); - - - GUILayout.BeginHorizontal(); - GUILayout.Label("B", GUILayout.Width(20)); - B = GUILayout.HorizontalSlider(color.b, 0f, 1f, GUILayout.Width(150)); - GUILayout.Label(((int)(B * 255)).ToString(), GUILayout.Width(30)); - GUILayout.EndHorizontal(); - - GUILayout.Space(10); - - - void DrawPreview(Color color_to_draw) - { - if (previewTexture == null) - { - previewTexture = new Texture2D(1, 1); - } - - previewTexture.SetPixel(0, 0, color_to_draw); - previewTexture.Apply(); - boxStyle.normal.background = previewTexture; - GUILayout.Box(GUIContent.none, boxStyle, GUILayout.Height(30)); - } - - DrawPreview(new Color(R, G, B, 1)); - - GUILayout.EndArea(); - - return new Color(R, G, B, 1); - } - - public static Texture2D MakeTex(int width, int height, Color col) - { - string cacheKey = $"{width}x{height}_{col.r}_{col.g}_{col.b}"; - - if (colorTextureCache.TryGetValue(col, out Texture2D cachedTexture)) - { - return cachedTexture; - } - - Texture2D result = new Texture2D(width, height); - Color[] pix = new Color[width * height]; - for (int i = 0; i < pix.Length; ++i) - { - pix[i] = col; - } - result.SetPixels(pix); - result.Apply(); - - colorTextureCache[col] = result; - return result; - } - - public static Texture2D GetCircularTexture(int width, int height) - { - int size = Mathf.Max(width, height); - if (circularTextureCache.TryGetValue(size, out Texture2D cachedTexture)) - { - return cachedTexture; - } - - Texture2D texture = new Texture2D(width, height); - for (int x = 0; x < texture.width; x++) - { - for (int y = 0; y < texture.height; y++) - { - if (Vector2.Distance(new Vector2(x, y), new Vector2(texture.width / 2, texture.height / 2)) <= texture.width / 2) - { - texture.SetPixel(x, y, Color.white); - } - else - { - texture.SetPixel(x, y, Color.clear); - } - } - } - - texture.Apply(); - - circularTextureCache[size] = texture; - return texture; - } } } diff --git a/DevourClient/Helpers/Map.cs b/DevourClient/Helpers/Map.cs index 6540006..76bc7db 100644 --- a/DevourClient/Helpers/Map.cs +++ b/DevourClient/Helpers/Map.cs @@ -11,7 +11,7 @@ { switch (sceneName) { - case "Devour": + case "Anna": return "Farmhouse"; case "Molly": return "Asylum"; @@ -23,6 +23,8 @@ return "Slaughterhouse"; case "Manor": return "Manor"; + case "Carnival": + return "Carnival"; default: return "Menu"; } @@ -40,12 +42,10 @@ Il2CppPhoton.Bolt.BoltNetwork.LoadScene(mapName); MelonLoader.MelonLogger.Warning("Please press the button only once, it may take some time for the map to load."); - Hacks.Misc.ShowMessageBox("Please press the button only once, it may take some time for the map to load."); } else { MelonLoader.MelonLogger.Warning("You must be the host to use this command!"); - Hacks.Misc.ShowMessageBox("You must be the host to use this command!"); } } } diff --git a/DevourClient/Helpers/Render.cs b/DevourClient/Helpers/Render.cs index d309334..2756910 100644 --- a/DevourClient/Helpers/Render.cs +++ b/DevourClient/Helpers/Render.cs @@ -12,14 +12,32 @@ namespace DevourClient.Render { public static GUIStyle StringStyle { get; set; } = new GUIStyle(GUI.skin.label); + private static GUIContent cachedContent = new GUIContent(); + private static Dictionary sizeCache = new Dictionary(); + private static int frameCacheClearCounter = 0; + private const int CACHE_CLEAR_INTERVAL = 1800; + public static void DrawString(Vector2 position, Color color, string label, bool centered = true) { - var content = new GUIContent(label); - var size = StringStyle.CalcSize(content); + cachedContent.text = label; + + if (!sizeCache.TryGetValue(label, out Vector2 size)) + { + size = StringStyle.CalcSize(cachedContent); + sizeCache[label] = size; + + frameCacheClearCounter++; + if (frameCacheClearCounter >= CACHE_CLEAR_INTERVAL) + { + sizeCache.Clear(); + frameCacheClearCounter = 0; + } + } + var upperLeft = centered ? position - size / 2f : position; Color color2 = GUI.color; GUI.color = color; - GUI.Label(new Rect(upperLeft, size), content); + GUI.Label(new Rect(upperLeft, size), cachedContent); GUI.color = color2; } @@ -63,7 +81,7 @@ namespace DevourClient.Render } public static void DrawBones(Transform bone1, Transform bone2, Color c) { - if (!Camera.main) //fix the crash maybe + if (!Camera.main) { return; } diff --git a/DevourClient/Helpers/StateHelper.cs b/DevourClient/Helpers/StateHelper.cs index 6590536..39d406e 100644 --- a/DevourClient/Helpers/StateHelper.cs +++ b/DevourClient/Helpers/StateHelper.cs @@ -40,7 +40,8 @@ namespace DevourClient.Helpers Il2Cpp.NolanBehaviour nb = p_GameObject.GetComponent(); Il2Cpp.SurvivalReviveInteractable _reviveInteractable = UnityEngine.Object.FindObjectOfType(); - _reviveInteractable.Interact(nb.gameObject); + if (_reviveInteractable.CanInteract(nb.gameObject) == true) { _reviveInteractable.Interact(nb.gameObject); } + } public void Jumpscare() @@ -48,7 +49,6 @@ namespace DevourClient.Helpers if (!BoltNetwork.IsServer) { MelonLogger.Msg("You need to be server !"); - Hacks.Misc.ShowMessageBox("You need to be server !"); return; } @@ -66,9 +66,6 @@ namespace DevourClient.Helpers sab.OnPickedUpPlayer(sab.gameObject, p_GameObject, false); - MelonLogger.Msg(Name); - Hacks.Misc.ShowMessageBox(Name); - /* MelonLogger.Msg(Name); Il2Cpp.JumpScare _jumpscare = UnityEngine.Object.FindObjectOfType(); @@ -114,7 +111,6 @@ namespace DevourClient.Helpers else { MelonLogger.Error("Azazel not found!"); - Hacks.Misc.ShowMessageBox("Azazel not found!"); return; } } @@ -124,7 +120,6 @@ namespace DevourClient.Helpers if (!BoltNetwork.IsServer) { MelonLogger.Msg("You need to be server !"); - Hacks.Misc.ShowMessageBox("You need to be server !"); return; } @@ -180,9 +175,6 @@ namespace DevourClient.Helpers public class Entities { - private static bool isRunning = true; // Control coroutine running state - private static List activeCoroutines = new List(); // Track active coroutines - public static int MAX_PLAYERS = 4; //will change by calling CreateCustomizedLobby public static BasePlayer LocalPlayer_ = new BasePlayer(); @@ -198,106 +190,28 @@ namespace DevourClient.Helpers public static Il2Cpp.CorpseBehaviour[] Corpses = default!; public static Il2Cpp.CrowBehaviour[] Crows = default!; public static Il2Cpp.ManorLumpController[] Lumps = default!; + public static Il2Cpp.MonkeyBehaviour[] Monkeys = default!; - // Method to stop all coroutines - public static void StopAllCoroutines() - { - isRunning = false; - foreach (var coroutine in activeCoroutines) - { - if (coroutine != null) - { - MelonCoroutines.Stop(coroutine); - } - } - activeCoroutines.Clear(); - - // Clean up all cached objects - CleanupCachedObjects(); - } - - // Clean up cached objects - private static void CleanupCachedObjects() - { - if (Players != null) - { - foreach (var player in Players) - { - if (player != null) - { - player.p_GameObject = null; - } - } - Players = null; - } - - LocalPlayer_.p_GameObject = null; - GoatsAndRats = null; - SurvivalInteractables = null; - Keys = null; - Demons = null; - Spiders = null; - Ghosts = null; - Azazels = null; - Boars = null; - Corpses = null; - Crows = null; - Lumps = null; - } - - // Method to start all coroutines - public static void StartAllCoroutines() - { - isRunning = true; - activeCoroutines.Clear(); - - // Start all coroutines and save references - activeCoroutines.Add(MelonCoroutines.Start(GetLocalPlayer())); - activeCoroutines.Add(MelonCoroutines.Start(GetAllPlayers())); - activeCoroutines.Add(MelonCoroutines.Start(GetGoatsAndRats())); - activeCoroutines.Add(MelonCoroutines.Start(GetSurvivalInteractables())); - activeCoroutines.Add(MelonCoroutines.Start(GetKeys())); - activeCoroutines.Add(MelonCoroutines.Start(GetDemons())); - activeCoroutines.Add(MelonCoroutines.Start(GetSpiders())); - activeCoroutines.Add(MelonCoroutines.Start(GetGhosts())); - activeCoroutines.Add(MelonCoroutines.Start(GetBoars())); - activeCoroutines.Add(MelonCoroutines.Start(GetCorpses())); - activeCoroutines.Add(MelonCoroutines.Start(GetCrows())); - activeCoroutines.Add(MelonCoroutines.Start(GetLumps())); - activeCoroutines.Add(MelonCoroutines.Start(GetAzazels())); - } + // 协程生命周期管理 + private static List activeCoroutines = new List(); + private static bool isRunning = false; public static IEnumerator GetLocalPlayer() { while (isRunning) { - try + GameObject[] currentPlayers = GameObject.FindGameObjectsWithTag("Player"); + + for (int i = 0; i < currentPlayers.Length; i++) { - GameObject[] currentPlayers = GameObject.FindGameObjectsWithTag("Player"); - if (currentPlayers != null) + if (currentPlayers[i].GetComponent().entity.IsOwner) { - for (int i = 0; i < currentPlayers.Length; i++) - { - if (currentPlayers[i].GetComponent().entity.IsOwner) - { - // Clean up old references before updating - if (LocalPlayer_.p_GameObject != currentPlayers[i]) - { - LocalPlayer_.p_GameObject = currentPlayers[i]; - } - break; - } - } + LocalPlayer_.p_GameObject = currentPlayers[i]; + break; } } - catch (System.Exception e) - { - string err = $"GetLocalPlayer coroutine encountered an error: {e.Message}"; - MelonLogger.Error(err); - DevourClient.Settings.Settings.errorMessage = err; - DevourClient.Settings.Settings.showErrorMessage = true; - } + // Wait 5 seconds before caching objects again. yield return new WaitForSeconds(5f); } } @@ -306,70 +220,46 @@ namespace DevourClient.Helpers { while (isRunning) { - try + GameObject[] players = GameObject.FindGameObjectsWithTag("Player"); + Players = new BasePlayer[players.Length]; + + int i = 0; + foreach (GameObject p in players) { - GameObject[] players = GameObject.FindGameObjectsWithTag("Player"); - - // Clean up old array before creating new one - if (Players != null) + string player_name = ""; + string player_id = "-1"; + + Il2Cpp.DissonancePlayerTracking dpt = p.gameObject.GetComponent(); + if (dpt != null) { - foreach (var player in Players) - { - if (player != null) - { - player.p_GameObject = null; - } - } + player_name = dpt.state.PlayerName; + player_id = dpt.state.PlayerId; } - // Create new array - Players = new BasePlayer[players.Length]; - - for (int i = 0; i < players.Length; i++) + if (Players[i] == null) { - if (Players[i] == null) - { - Players[i] = new BasePlayer(); - } - - Players[i].p_GameObject = players[i]; - - Il2Cpp.DissonancePlayerTracking dpt = players[i].GetComponent(); - if (dpt != null) - { - Players[i].Name = dpt.state.PlayerName; - Players[i].Id = dpt.state.PlayerId; - } + Players[i] = new BasePlayer(); } - } - catch (System.Exception e) - { - string err = $"GetAllPlayers coroutine encountered an error: {e.Message}"; - MelonLogger.Error(err); - DevourClient.Settings.Settings.errorMessage = err; - DevourClient.Settings.Settings.showErrorMessage = true; + + Players[i].Id = player_id; + Players[i].Name = player_name; + Players[i].p_GameObject = p; + + i++; } + + // Wait 5 seconds before caching objects again. yield return new WaitForSeconds(5f); } } - public static IEnumerator GetGoatsAndRats() { while (isRunning) { - try - { - GoatsAndRats = Il2Cpp.GoatBehaviour.FindObjectsOfType(); - } - catch (System.Exception e) - { - string err = $"GetGoatsAndRats coroutine encountered an error: {e.Message}"; - MelonLogger.Error(err); - DevourClient.Settings.Settings.errorMessage = err; - DevourClient.Settings.Settings.showErrorMessage = true; - } + GoatsAndRats = Il2Cpp.GoatBehaviour.FindObjectsOfType(); + // Wait 5 seconds before caching objects again. yield return new WaitForSeconds(5f); } } @@ -378,18 +268,9 @@ namespace DevourClient.Helpers { while (isRunning) { - try - { - SurvivalInteractables = Il2Cpp.SurvivalInteractable.FindObjectsOfType(); - } - catch (System.Exception e) - { - string err = $"GetSurvivalInteractables coroutine encountered an error: {e.Message}"; - MelonLogger.Error(err); - DevourClient.Settings.Settings.errorMessage = err; - DevourClient.Settings.Settings.showErrorMessage = true; - } + SurvivalInteractables = Il2Cpp.SurvivalInteractable.FindObjectsOfType(); + // Wait 5 seconds before caching objects again. yield return new WaitForSeconds(5f); } } @@ -398,18 +279,9 @@ namespace DevourClient.Helpers { while (isRunning) { - try - { - Keys = Il2Cpp.KeyBehaviour.FindObjectsOfType(); - } - catch (System.Exception e) - { - string err = $"GetKeys coroutine encountered an error: {e.Message}"; - MelonLogger.Error(err); - DevourClient.Settings.Settings.errorMessage = err; - DevourClient.Settings.Settings.showErrorMessage = true; - } + Keys = Il2Cpp.KeyBehaviour.FindObjectsOfType(); + // Wait 5 seconds before caching objects again. yield return new WaitForSeconds(5f); } } @@ -418,18 +290,9 @@ namespace DevourClient.Helpers { while (isRunning) { - try - { - Demons = Il2Cpp.SurvivalDemonBehaviour.FindObjectsOfType(); - } - catch (System.Exception e) - { - string err = $"GetDemons coroutine encountered an error: {e.Message}"; - MelonLogger.Error(err); - DevourClient.Settings.Settings.errorMessage = err; - DevourClient.Settings.Settings.showErrorMessage = true; - } + Demons = Il2Cpp.SurvivalDemonBehaviour.FindObjectsOfType(); + // Wait 5 seconds before caching objects again. yield return new WaitForSeconds(5f); } } @@ -438,18 +301,9 @@ namespace DevourClient.Helpers { while (isRunning) { - try - { - Spiders = Il2Cpp.SpiderBehaviour.FindObjectsOfType(); - } - catch (System.Exception e) - { - string err = $"GetSpiders coroutine encountered an error: {e.Message}"; - MelonLogger.Error(err); - DevourClient.Settings.Settings.errorMessage = err; - DevourClient.Settings.Settings.showErrorMessage = true; - } + Spiders = Il2Cpp.SpiderBehaviour.FindObjectsOfType(); + // Wait 5 seconds before caching objects again. yield return new WaitForSeconds(5f); } } @@ -458,18 +312,9 @@ namespace DevourClient.Helpers { while (isRunning) { - try - { - Ghosts = Il2Cpp.GhostBehaviour.FindObjectsOfType(); - } - catch (System.Exception e) - { - string err = $"GetGhosts coroutine encountered an error: {e.Message}"; - MelonLogger.Error(err); - DevourClient.Settings.Settings.errorMessage = err; - DevourClient.Settings.Settings.showErrorMessage = true; - } + Ghosts = Il2Cpp.GhostBehaviour.FindObjectsOfType(); + // Wait 5 seconds before caching objects again. yield return new WaitForSeconds(5f); } } @@ -478,18 +323,9 @@ namespace DevourClient.Helpers { while (isRunning) { - try - { - Boars = Il2Cpp.BoarBehaviour.FindObjectsOfType(); - } - catch (System.Exception e) - { - string err = $"GetBoars coroutine encountered an error: {e.Message}"; - MelonLogger.Error(err); - DevourClient.Settings.Settings.errorMessage = err; - DevourClient.Settings.Settings.showErrorMessage = true; - } + Boars = Il2Cpp.BoarBehaviour.FindObjectsOfType(); + // Wait 5 seconds before caching objects again. yield return new WaitForSeconds(5f); } } @@ -498,18 +334,9 @@ namespace DevourClient.Helpers { while (isRunning) { - try - { - Corpses = Il2Cpp.CorpseBehaviour.FindObjectsOfType(); - } - catch (System.Exception e) - { - string err = $"GetCorpses coroutine encountered an error: {e.Message}"; - MelonLogger.Error(err); - DevourClient.Settings.Settings.errorMessage = err; - DevourClient.Settings.Settings.showErrorMessage = true; - } + Corpses = Il2Cpp.CorpseBehaviour.FindObjectsOfType(); + // Wait 5 seconds before caching objects again. yield return new WaitForSeconds(5f); } } @@ -518,18 +345,9 @@ namespace DevourClient.Helpers { while (isRunning) { - try - { - Crows = Il2Cpp.CrowBehaviour.FindObjectsOfType(); - } - catch (System.Exception e) - { - string err = $"GetCrows coroutine encountered an error: {e.Message}"; - MelonLogger.Error(err); - DevourClient.Settings.Settings.errorMessage = err; - DevourClient.Settings.Settings.showErrorMessage = true; - } + Crows = Il2Cpp.CrowBehaviour.FindObjectsOfType(); + // Wait 5 seconds before caching objects again. yield return new WaitForSeconds(5f); } } @@ -538,39 +356,135 @@ namespace DevourClient.Helpers { while (isRunning) { - try - { - Lumps = Il2Cpp.ManorLumpController.FindObjectsOfType(); - } - catch (System.Exception e) - { - string err = $"GetLumps coroutine encountered an error: {e.Message}"; - MelonLogger.Error(err); - DevourClient.Settings.Settings.errorMessage = err; - DevourClient.Settings.Settings.showErrorMessage = true; - } + Lumps = Il2Cpp.ManorLumpController.FindObjectsOfType(); + // Wait 5 seconds before caching objects again. + yield return new WaitForSeconds(5f); + } + } + + public static IEnumerator GetMonkeys() + { + while (isRunning) + { + Monkeys = Il2Cpp.MonkeyBehaviour.FindObjectsOfType(); + + // Wait 5 seconds before caching objects again. yield return new WaitForSeconds(5f); } } public static IEnumerator GetAzazels() { + /* + * ikr AzazelS, because in case we spawn multiple we want the esp to render all of them + */ while (isRunning) { - try + Azazels = Il2Cpp.SurvivalAzazelBehaviour.FindObjectsOfType(); + + // Wait 5 seconds before caching objects again. + yield return new WaitForSeconds(5f); + } + } + + /// + /// 启动所有协程 + /// + public static void StartAllCoroutines() + { + isRunning = true; + } + + /// + /// 停止所有协程并清理协程引用 + /// + public static void StopAllCoroutines() + { + try + { + // 设置标志,让所有协程循环自然退出 + isRunning = false; + + // 停止所有记录的协程 + foreach (var coroutine in activeCoroutines) { - Azazels = Il2Cpp.SurvivalAzazelBehaviour.FindObjectsOfType(); - } - catch (System.Exception e) - { - string err = $"Error in GetAzazels coroutine: {e.Message}"; - MelonLogger.Error(err); - DevourClient.Settings.Settings.errorMessage = err; - DevourClient.Settings.Settings.showErrorMessage = true; + if (coroutine != null) + { + MelonCoroutines.Stop(coroutine); + } } - yield return new WaitForSeconds(5f); + // 清空协程引用列表 + activeCoroutines.Clear(); + + // 清理缓存对象 + CleanupCachedObjects(); + + MelonLogger.Msg("All coroutines stopped and cleaned up successfully."); + } + catch (System.Exception ex) + { + MelonLogger.Error($"Error stopping coroutines: {ex.Message}"); + } + } + + /// + /// 清理所有缓存的游戏对象引用 + /// + public static void CleanupCachedObjects() + { + try + { + // 清理玩家对象引用 + if (Players != null) + { + foreach (var player in Players) + { + if (player != null) + { + player.p_GameObject = null; + } + } + } + + // 将所有实体数组设为null,释放对游戏对象的引用 + Players = null; + GoatsAndRats = null; + SurvivalInteractables = null; + Keys = null; + Demons = null; + Spiders = null; + Ghosts = null; + Azazels = null; + Boars = null; + Corpses = null; + Crows = null; + Lumps = null; + Monkeys = null; + + // 清理本地玩家引用 + if (LocalPlayer_ != null) + { + LocalPlayer_.p_GameObject = null; + } + + MelonLogger.Msg("Cached objects cleaned up successfully."); + } + catch (System.Exception ex) + { + MelonLogger.Error($"Error cleaning up cached objects: {ex.Message}"); + } + } + + /// + /// 注册协程引用用于后续管理 + /// + public static void RegisterCoroutine(object coroutine) + { + if (coroutine != null && !activeCoroutines.Contains(coroutine)) + { + activeCoroutines.Add(coroutine); } } } diff --git a/DevourClient/Settings/Settings.cs b/DevourClient/Settings/Settings.cs index c66fe11..a8dd9b4 100644 --- a/DevourClient/Settings/Settings.cs +++ b/DevourClient/Settings/Settings.cs @@ -13,17 +13,12 @@ namespace DevourClient.Settings public static Color player_esp_color = new Color(0.00f, 1.00f, 0.00f, 1); public static Color azazel_esp_color = new Color(1.00f, 0.00f, 0.00f, 1); public static float speed = 1f; + public const string message_to_spam = "Deez Nutz"; public static KeyCode flyKey = KeyCode.None; public static Vector2 itemsScrollPosition = Vector2.zero; public static Vector2 rituelObjectsScrollPosition = Vector2.zero; public static Vector2 stuffsScrollPosition = Vector2.zero; - // Error message box settings - public static bool showErrorMessage = false; - public static string errorMessage = ""; - public static float errorMessageDisplayTime = 0f; - public static float errorMessageMaxDisplayTime = 4f; // Maximum display time for error messages (in seconds) - public static KeyCode GetKey() { Thread.Sleep(50); //TOFIX tried using anyKeydown, no success