fix crashed issue #85

Merged
mana-feng merged 17 commits from MelonLoader into MelonLoader 2025-10-13 19:28:44 +00:00
3 changed files with 687 additions and 395 deletions
Showing only changes of commit d7597b055f - Show all commits

View File

@@ -1,57 +1,143 @@
using UnityEngine; using UnityEngine;
using MelonLoader;
using System.Collections.Generic;
namespace DevourClient.Helpers namespace DevourClient.Helpers
{ {
class GUIHelper public static class GUIHelper // 改为静态类
{ {
private static Texture2D previewTexture;
private static GUIStyle boxStyle;
private static Dictionary<Color, Texture2D> colorTextureCache = new Dictionary<Color, Texture2D>();
private static Dictionary<int, Texture2D> circularTextureCache = new Dictionary<int, Texture2D>();
// 初始化方法
public static void Initialize()
{
if (previewTexture == null)
{
previewTexture = new Texture2D(1, 1);
boxStyle = new GUIStyle(GUI.skin.box);
}
}
// 清理方法
public static void Cleanup()
{
if (previewTexture != null)
{
UnityEngine.Object.Destroy(previewTexture);
previewTexture = null;
}
foreach (var texture in colorTextureCache.Values)
{
if (texture != null)
{
UnityEngine.Object.Destroy(texture);
}
}
colorTextureCache.Clear();
foreach (var texture in circularTextureCache.Values)
{
if (texture != null)
{
UnityEngine.Object.Destroy(texture);
}
}
circularTextureCache.Clear();
}
private static float R; private static float R;
private static float G; private static float G;
private static float B; private static float B;
public static Color ColorPick(string title, Color color) public static Color ColorPick(string title, Color color)
{ {
GUI.Label(new Rect(Settings.Settings.x + 195, Settings.Settings.y + 70, 250, 30), title); Initialize(); // 确保已初始化
R = GUI.VerticalSlider(new Rect(Settings.Settings.x + 240, Settings.Settings.y + 100, 30, 90), color.r, 0f, 1f); // 使用 GUILayout 来创建更可靠的滑动条
G = GUI.VerticalSlider(new Rect(Settings.Settings.x + 270, Settings.Settings.y + 100, 30, 90), color.g, 0f, 1f); GUILayout.BeginArea(new Rect(Settings.Settings.x + 195, Settings.Settings.y + 70, 250, 250));
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"); GUILayout.Label(title);
GUI.Label(new Rect(Settings.Settings.x + 270, Settings.Settings.y + 190, 30, 30), "G"); GUILayout.Space(10);
GUI.Label(new Rect(Settings.Settings.x + 300, Settings.Settings.y + 190, 30, 30), "B");
color = new Color(R, G, B, 1); // R 通道
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();
void DrawPreview(Rect position, Color color_to_draw) // G 通道
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();
// B 通道
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)
{ {
Texture2D texture = new Texture2D(1, 1); if (previewTexture == null)
texture.SetPixel(0, 0, color_to_draw); {
texture.Apply(); previewTexture = new Texture2D(1, 1);
GUIStyle boxStyle = new GUIStyle(GUI.skin.box); }
boxStyle.normal.background = texture;
GUI.Box(position, GUIContent.none, boxStyle); previewTexture.SetPixel(0, 0, color_to_draw);
previewTexture.Apply();
boxStyle.normal.background = previewTexture;
GUILayout.Box(GUIContent.none, boxStyle, GUILayout.Height(30));
} }
DrawPreview(new Rect(Settings.Settings.x + 195, Settings.Settings.y + 100, 20, 90), color); DrawPreview(new Color(R, G, B, 1));
return color; GUILayout.EndArea();
return new Color(R, G, B, 1);
} }
public static Texture2D MakeTex(int width, int height, Color col) 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]; Color[] pix = new Color[width * height];
for (int i = 0; i < pix.Length; ++i) for (int i = 0; i < pix.Length; ++i)
{ {
pix[i] = col; pix[i] = col;
} }
Texture2D result = new Texture2D(width, height);
result.SetPixels(pix); result.SetPixels(pix);
result.Apply(); result.Apply();
colorTextureCache[col] = result;
return result; return result;
} }
public static Texture2D GetCircularTexture(int width, int height) 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); Texture2D texture = new Texture2D(width, height);
for (int x = 0; x < texture.width; x++) for (int x = 0; x < texture.width; x++)
{ {
@@ -70,6 +156,7 @@ namespace DevourClient.Helpers
texture.Apply(); texture.Apply();
circularTextureCache[size] = texture;
return texture; return texture;
} }
} }

View File

@@ -40,10 +40,12 @@
Il2CppPhoton.Bolt.BoltNetwork.LoadScene(mapName); Il2CppPhoton.Bolt.BoltNetwork.LoadScene(mapName);
MelonLoader.MelonLogger.Warning("Please press the button only once, it may take some time for the map to load."); 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 else
{ {
MelonLoader.MelonLogger.Warning("You must be the host to use this command!"); MelonLoader.MelonLogger.Warning("You must be the host to use this command!");
Hacks.Misc.ShowMessageBox("You must be the host to use this command!");
} }
} }
} }

View File

@@ -48,6 +48,7 @@ namespace DevourClient.Helpers
if (!BoltNetwork.IsServer) if (!BoltNetwork.IsServer)
{ {
MelonLogger.Msg("You need to be server !"); MelonLogger.Msg("You need to be server !");
Hacks.Misc.ShowMessageBox("You need to be server !");
return; return;
} }
@@ -65,6 +66,9 @@ namespace DevourClient.Helpers
sab.OnPickedUpPlayer(sab.gameObject, p_GameObject, false); sab.OnPickedUpPlayer(sab.gameObject, p_GameObject, false);
MelonLogger.Msg(Name);
Hacks.Misc.ShowMessageBox(Name);
/* /*
MelonLogger.Msg(Name); MelonLogger.Msg(Name);
Il2Cpp.JumpScare _jumpscare = UnityEngine.Object.FindObjectOfType<Il2Cpp.JumpScare>(); Il2Cpp.JumpScare _jumpscare = UnityEngine.Object.FindObjectOfType<Il2Cpp.JumpScare>();
@@ -110,6 +114,7 @@ namespace DevourClient.Helpers
else else
{ {
MelonLogger.Error("Azazel not found!"); MelonLogger.Error("Azazel not found!");
Hacks.Misc.ShowMessageBox("Azazel not found!");
return; return;
} }
} }
@@ -119,6 +124,7 @@ namespace DevourClient.Helpers
if (!BoltNetwork.IsServer) if (!BoltNetwork.IsServer)
{ {
MelonLogger.Msg("You need to be server !"); MelonLogger.Msg("You need to be server !");
Hacks.Misc.ShowMessageBox("You need to be server !");
return; return;
} }
@@ -174,6 +180,9 @@ namespace DevourClient.Helpers
public class Entities public class Entities
{ {
private static bool isRunning = true; // Control coroutine running state
private static List<object> activeCoroutines = new List<object>(); // Track active coroutines
public static int MAX_PLAYERS = 4; //will change by calling CreateCustomizedLobby public static int MAX_PLAYERS = 4; //will change by calling CreateCustomizedLobby
public static BasePlayer LocalPlayer_ = new BasePlayer(); public static BasePlayer LocalPlayer_ = new BasePlayer();
@@ -190,183 +199,377 @@ namespace DevourClient.Helpers
public static Il2Cpp.CrowBehaviour[] Crows = default!; public static Il2Cpp.CrowBehaviour[] Crows = default!;
public static Il2Cpp.ManorLumpController[] Lumps = default!; public static Il2Cpp.ManorLumpController[] Lumps = default!;
public static IEnumerator GetLocalPlayer() // Method to stop all coroutines
public static void StopAllCoroutines()
{ {
while (true) isRunning = false;
foreach (var coroutine in activeCoroutines)
{ {
GameObject[] currentPlayers = GameObject.FindGameObjectsWithTag("Player"); if (coroutine != null)
for (int i = 0; i < currentPlayers.Length; i++)
{ {
if (currentPlayers[i].GetComponent<Il2Cpp.NolanBehaviour>().entity.IsOwner) 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)
{ {
LocalPlayer_.p_GameObject = currentPlayers[i]; player.p_GameObject = null;
break;
} }
} }
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()));
}
public static IEnumerator GetLocalPlayer()
{
while (isRunning)
{
try
{
GameObject[] currentPlayers = GameObject.FindGameObjectsWithTag("Player");
if (currentPlayers != null)
{
for (int i = 0; i < currentPlayers.Length; i++)
{
if (currentPlayers[i].GetComponent<Il2Cpp.NolanBehaviour>().entity.IsOwner)
{
// Clean up old references before updating
if (LocalPlayer_.p_GameObject != currentPlayers[i])
{
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); yield return new WaitForSeconds(5f);
} }
} }
public static IEnumerator GetAllPlayers() public static IEnumerator GetAllPlayers()
{ {
while (true) while (isRunning)
{ {
GameObject[] players = GameObject.FindGameObjectsWithTag("Player"); try
Players = new BasePlayer[players.Length];
int i = 0;
foreach (GameObject p in players)
{ {
string player_name = ""; GameObject[] players = GameObject.FindGameObjectsWithTag("Player");
string player_id = "-1";
Il2Cpp.DissonancePlayerTracking dpt = p.gameObject.GetComponent<Il2Cpp.DissonancePlayerTracking>(); // Clean up old array before creating new one
if (dpt != null) if (Players != null)
{ {
player_name = dpt.state.PlayerName; foreach (var player in Players)
player_id = dpt.state.PlayerId; {
if (player != null)
{
player.p_GameObject = null;
}
}
} }
if (Players[i] == null) // Create new array
Players = new BasePlayer[players.Length];
for (int i = 0; i < players.Length; i++)
{ {
Players[i] = new BasePlayer(); if (Players[i] == null)
{
Players[i] = new BasePlayer();
}
Players[i].p_GameObject = players[i];
Il2Cpp.DissonancePlayerTracking dpt = players[i].GetComponent<Il2Cpp.DissonancePlayerTracking>();
if (dpt != null)
{
Players[i].Name = dpt.state.PlayerName;
Players[i].Id = dpt.state.PlayerId;
}
} }
}
Players[i].Id = player_id; catch (System.Exception e)
Players[i].Name = player_name; {
Players[i].p_GameObject = p; string err = $"GetAllPlayers coroutine encountered an error: {e.Message}";
MelonLogger.Error(err);
i++; DevourClient.Settings.Settings.errorMessage = err;
DevourClient.Settings.Settings.showErrorMessage = true;
} }
// Wait 5 seconds before caching objects again.
yield return new WaitForSeconds(5f); yield return new WaitForSeconds(5f);
} }
} }
public static IEnumerator GetGoatsAndRats() public static IEnumerator GetGoatsAndRats()
{ {
while (true) while (isRunning)
{ {
GoatsAndRats = Il2Cpp.GoatBehaviour.FindObjectsOfType<Il2Cpp.GoatBehaviour>(); try
{
GoatsAndRats = Il2Cpp.GoatBehaviour.FindObjectsOfType<Il2Cpp.GoatBehaviour>();
}
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;
}
// Wait 5 seconds before caching objects again.
yield return new WaitForSeconds(5f); yield return new WaitForSeconds(5f);
} }
} }
public static IEnumerator GetSurvivalInteractables() public static IEnumerator GetSurvivalInteractables()
{ {
while (true) while (isRunning)
{ {
SurvivalInteractables = Il2Cpp.SurvivalInteractable.FindObjectsOfType<Il2Cpp.SurvivalInteractable>(); try
{
SurvivalInteractables = Il2Cpp.SurvivalInteractable.FindObjectsOfType<Il2Cpp.SurvivalInteractable>();
}
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;
}
// Wait 5 seconds before caching objects again.
yield return new WaitForSeconds(5f); yield return new WaitForSeconds(5f);
} }
} }
public static IEnumerator GetKeys() public static IEnumerator GetKeys()
{ {
while (true) while (isRunning)
{ {
Keys = Il2Cpp.KeyBehaviour.FindObjectsOfType<Il2Cpp.KeyBehaviour>(); try
{
Keys = Il2Cpp.KeyBehaviour.FindObjectsOfType<Il2Cpp.KeyBehaviour>();
}
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;
}
// Wait 5 seconds before caching objects again.
yield return new WaitForSeconds(5f); yield return new WaitForSeconds(5f);
} }
} }
public static IEnumerator GetDemons() public static IEnumerator GetDemons()
{ {
while (true) while (isRunning)
{ {
Demons = Il2Cpp.SurvivalDemonBehaviour.FindObjectsOfType<Il2Cpp.SurvivalDemonBehaviour>(); try
{
Demons = Il2Cpp.SurvivalDemonBehaviour.FindObjectsOfType<Il2Cpp.SurvivalDemonBehaviour>();
}
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;
}
// Wait 5 seconds before caching objects again.
yield return new WaitForSeconds(5f); yield return new WaitForSeconds(5f);
} }
} }
public static IEnumerator GetSpiders() public static IEnumerator GetSpiders()
{ {
while (true) while (isRunning)
{ {
Spiders = Il2Cpp.SpiderBehaviour.FindObjectsOfType<Il2Cpp.SpiderBehaviour>(); try
{
Spiders = Il2Cpp.SpiderBehaviour.FindObjectsOfType<Il2Cpp.SpiderBehaviour>();
}
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;
}
// Wait 5 seconds before caching objects again.
yield return new WaitForSeconds(5f); yield return new WaitForSeconds(5f);
} }
} }
public static IEnumerator GetGhosts() public static IEnumerator GetGhosts()
{ {
while (true) while (isRunning)
{ {
Ghosts = Il2Cpp.GhostBehaviour.FindObjectsOfType<Il2Cpp.GhostBehaviour>(); try
{
Ghosts = Il2Cpp.GhostBehaviour.FindObjectsOfType<Il2Cpp.GhostBehaviour>();
}
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;
}
// Wait 5 seconds before caching objects again.
yield return new WaitForSeconds(5f); yield return new WaitForSeconds(5f);
} }
} }
public static IEnumerator GetBoars() public static IEnumerator GetBoars()
{ {
while (true) while (isRunning)
{ {
Boars = Il2Cpp.BoarBehaviour.FindObjectsOfType<Il2Cpp.BoarBehaviour>(); try
{
Boars = Il2Cpp.BoarBehaviour.FindObjectsOfType<Il2Cpp.BoarBehaviour>();
}
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;
}
// Wait 5 seconds before caching objects again.
yield return new WaitForSeconds(5f); yield return new WaitForSeconds(5f);
} }
} }
public static IEnumerator GetCorpses() public static IEnumerator GetCorpses()
{ {
while (true) while (isRunning)
{ {
Corpses = Il2Cpp.CorpseBehaviour.FindObjectsOfType<Il2Cpp.CorpseBehaviour>(); try
{
Corpses = Il2Cpp.CorpseBehaviour.FindObjectsOfType<Il2Cpp.CorpseBehaviour>();
}
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;
}
// Wait 5 seconds before caching objects again.
yield return new WaitForSeconds(5f); yield return new WaitForSeconds(5f);
} }
} }
public static IEnumerator GetCrows() public static IEnumerator GetCrows()
{ {
while (true) while (isRunning)
{ {
Crows = Il2Cpp.CrowBehaviour.FindObjectsOfType<Il2Cpp.CrowBehaviour>(); try
{
Crows = Il2Cpp.CrowBehaviour.FindObjectsOfType<Il2Cpp.CrowBehaviour>();
}
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;
}
// Wait 5 seconds before caching objects again.
yield return new WaitForSeconds(5f); yield return new WaitForSeconds(5f);
} }
} }
public static IEnumerator GetLumps() public static IEnumerator GetLumps()
{ {
while (true) while (isRunning)
{ {
Lumps = Il2Cpp.ManorLumpController.FindObjectsOfType<Il2Cpp.ManorLumpController>(); try
{
Lumps = Il2Cpp.ManorLumpController.FindObjectsOfType<Il2Cpp.ManorLumpController>();
}
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;
}
// Wait 5 seconds before caching objects again.
yield return new WaitForSeconds(5f); yield return new WaitForSeconds(5f);
} }
} }
public static IEnumerator GetAzazels() public static IEnumerator GetAzazels()
{ {
/* while (isRunning)
* ikr AzazelS, because in case we spawn multiple we want the esp to render all of them
*/
while (true)
{ {
Azazels = Il2Cpp.SurvivalAzazelBehaviour.FindObjectsOfType<Il2Cpp.SurvivalAzazelBehaviour>(); try
{
Azazels = Il2Cpp.SurvivalAzazelBehaviour.FindObjectsOfType<Il2Cpp.SurvivalAzazelBehaviour>();
}
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;
}
// Wait 5 seconds before caching objects again.
yield return new WaitForSeconds(5f); yield return new WaitForSeconds(5f);
} }
} }