272 lines
8.9 KiB
C#
272 lines
8.9 KiB
C#
using System;
|
|
using System.Reflection;
|
|
using UnityEngine;
|
|
using MelonLoader;
|
|
|
|
namespace greg.Core.UI;
|
|
|
|
public static class GameMethodInvoker
|
|
{
|
|
private static readonly BindingFlags DefaultFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
|
|
|
|
public static bool Invoke(string typeName, string methodName, params object[] args)
|
|
{
|
|
try
|
|
{
|
|
var assembly = Assembly.Load("Assembly-CSharp");
|
|
var type = assembly.GetType(typeName);
|
|
if (type == null)
|
|
{
|
|
MelonLogger.Warning($"[GameMethodInvoker] Type not found: {typeName}");
|
|
return false;
|
|
}
|
|
|
|
return Invoke(type, methodName, null, args);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MelonLogger.Error($"[GameMethodInvoker] Failed: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static bool Invoke<T>(string methodName, T instance, params object[] args)
|
|
{
|
|
return Invoke(typeof(T), methodName, instance, args);
|
|
}
|
|
|
|
public static bool Invoke(Type type, string methodName, object instance, params object[] args)
|
|
{
|
|
try
|
|
{
|
|
var method = FindMethod(type, methodName, args?.Length ?? 0);
|
|
if (method == null)
|
|
{
|
|
MelonLogger.Warning($"[GameMethodInvoker] Method not found: {type.Name}.{methodName}");
|
|
return false;
|
|
}
|
|
|
|
var result = method.Invoke(instance, args);
|
|
|
|
if (result is bool boolResult && !boolResult)
|
|
{
|
|
MelonLogger.Warning($"[GameMethodInvoker] Method returned false: {type.Name}.{methodName}");
|
|
return false;
|
|
}
|
|
|
|
MelonLogger.Msg($"[GameMethodInvoker] Invoked: {type.Name}.{methodName}");
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MelonLogger.Error($"[GameMethodInvoker] {type.Name}.{methodName}: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static T GetStaticField<T>(string typeName, string fieldName)
|
|
{
|
|
try
|
|
{
|
|
var assembly = Assembly.Load("Assembly-CSharp");
|
|
var type = assembly.GetType(typeName);
|
|
if (type == null) return default;
|
|
|
|
var field = type.GetField(fieldName, DefaultFlags);
|
|
if (field == null) return default;
|
|
|
|
var value = field.GetValue(null);
|
|
return value != null ? (T)value : default;
|
|
}
|
|
catch
|
|
{
|
|
return default;
|
|
}
|
|
}
|
|
|
|
public static T GetInstanceField<T>(object instance, string fieldName)
|
|
{
|
|
try
|
|
{
|
|
if (instance == null) return default;
|
|
|
|
var type = instance.GetType();
|
|
var field = type.GetField(fieldName, DefaultFlags);
|
|
if (field == null) return default;
|
|
|
|
var value = field.GetValue(instance);
|
|
return value != null ? (T)value : default;
|
|
}
|
|
catch
|
|
{
|
|
return default;
|
|
}
|
|
}
|
|
|
|
public static void SetInstanceField(object instance, string fieldName, object value)
|
|
{
|
|
try
|
|
{
|
|
if (instance == null) return;
|
|
|
|
var type = instance.GetType();
|
|
var field = type.GetField(fieldName, DefaultFlags);
|
|
field?.SetValue(instance, value);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MelonLogger.Warning($"[GameMethodInvoker] SetField failed: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
private static MethodInfo FindMethod(Type type, string methodName, int argCount)
|
|
{
|
|
var methods = type.GetMethods(DefaultFlags);
|
|
|
|
foreach (var method in methods)
|
|
{
|
|
if (method.Name != methodName) continue;
|
|
|
|
var parameters = method.GetParameters();
|
|
if (parameters.Length != argCount) continue;
|
|
|
|
return method;
|
|
}
|
|
|
|
foreach (var method in methods)
|
|
{
|
|
if (method.Name != methodName) continue;
|
|
if (method.GetParameters().Length == 0 || argCount == 0) return method;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public static class GameUIElements
|
|
{
|
|
public static class Paths
|
|
{
|
|
public const string MainGameManager = "MainGameManager";
|
|
public const string PauseMenuCanvas = "PauseMenuCanvas";
|
|
public const string PauseMenu = "PauseMenu";
|
|
public const string MainMenu = "MainMenu";
|
|
public const string ComputerShop = "ComputerShop";
|
|
public const string GameManager = "GameManager";
|
|
}
|
|
|
|
public static class Methods
|
|
{
|
|
public const string LoadGame = "LoadGame";
|
|
public const string SaveGame = "SaveGame";
|
|
public const string Resume = "Resume";
|
|
public const string Pause = "Pause";
|
|
public const string OpenShop = "OpenShop";
|
|
public const string CloseShop = "CloseShop";
|
|
public const string ReturnToMenu = "ReturnToMenu";
|
|
}
|
|
|
|
public static class Types
|
|
{
|
|
public const string MainGameManager = "MainGameManager";
|
|
public const string GameManager = "GameManager";
|
|
public const string PauseMenu = "PauseMenu";
|
|
public const string MainMenu = "MainMenu";
|
|
public const string ComputerShop = "ComputerShop";
|
|
}
|
|
}
|
|
|
|
public static class GameUIButtons
|
|
{
|
|
public static bool ClickButton(string buttonPath)
|
|
{
|
|
var button = FindButton(buttonPath);
|
|
if (button == null) return false;
|
|
|
|
button.onClick?.Invoke();
|
|
MelonLogger.Msg($"[GameUIButtons] Clicked: {buttonPath}");
|
|
return true;
|
|
}
|
|
|
|
private static UnityEngine.UI.Button FindButton(string path)
|
|
{
|
|
var go = GameObject.Find(path);
|
|
if (go != null) return go.GetComponent<UnityEngine.UI.Button>();
|
|
|
|
// If not found (likely inactive), check all buttons
|
|
var allButtons = Resources.FindObjectsOfTypeAll<UnityEngine.UI.Button>();
|
|
foreach (var btn in allButtons)
|
|
{
|
|
if (GetGameObjectPath(btn.gameObject).Contains(path)) return btn;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private static string GetGameObjectPath(GameObject obj)
|
|
{
|
|
string path = "/" + obj.name;
|
|
while (obj.transform.parent != null)
|
|
{
|
|
obj = obj.transform.parent.gameObject;
|
|
path = "/" + obj.name + path;
|
|
}
|
|
return path;
|
|
}
|
|
|
|
public static bool ClickButtonByName(string buttonName)
|
|
{
|
|
var allButtons = Resources.FindObjectsOfTypeAll<UnityEngine.UI.Button>();
|
|
foreach (var btn in allButtons)
|
|
{
|
|
if (btn.name == buttonName)
|
|
{
|
|
btn.onClick?.Invoke();
|
|
MelonLogger.Msg($"[GameUIButtons] Clicked by name: {buttonName}");
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static bool ClickButtonInCanvas(string canvasName, string buttonName)
|
|
{
|
|
return ClickButton($"{canvasName}/{buttonName}");
|
|
}
|
|
|
|
public static bool ClickLoadButton()
|
|
{
|
|
return ClickButtonByName("LoadGame") || ClickButton("Canvas - MainMenuScript/HorizontalLayout/MainMenu/LoadGame") || ClickButton("PauseMenuCanvas/Pause menu - Settings Scripts/PanelArea/PanelBackground/SystemPanel/Game/LoadButton");
|
|
}
|
|
|
|
public static bool ClickNewGameButton()
|
|
{
|
|
return ClickButtonByName("NewGame") || ClickButton("Canvas - MainMenuScript/HorizontalLayout/MainMenu/NewGame");
|
|
}
|
|
|
|
public static bool ClickContinueButton()
|
|
{
|
|
return ClickButtonByName("Continue") || ClickButton("Canvas - MainMenuScript/HorizontalLayout/MainMenu/Continue");
|
|
}
|
|
|
|
public static bool ClickSaveButton()
|
|
{
|
|
return ClickButton("PauseMenuCanvas/Pause menu - Settings Scripts/PanelArea/PanelBackground/SystemPanel/Game/SaveButton");
|
|
}
|
|
|
|
public static bool ClickResumeButton()
|
|
{
|
|
return ClickButton("PauseMenuCanvas/Pause menu - Settings Scripts/PanelArea/PanelBackground/SystemPanel/Game/ResumeButton");
|
|
}
|
|
|
|
public static bool ClickMainMenuButton()
|
|
{
|
|
return ClickButton("PauseMenuCanvas/Pause menu - Settings Scripts/PanelArea/PanelBackground/SystemPanel/Game/MainMenuButton");
|
|
}
|
|
|
|
public static bool ClickReportBugButton() => ClickButtonByName("Report Bug") || ClickButton("Canvas - MainMenuScript/HorizontalLayout/MainMenu/Report Bug");
|
|
public static bool ClickDiscordButton() => ClickButtonByName("Discord") || ClickButton("Canvas - MainMenuScript/TopRight_VerticalLayout/Discord");
|
|
public static bool ClickWishlistButton() => ClickButtonByName("Wishlist") || ClickButton("Canvas - MainMenuScript/TopRight_VerticalLayout/Wishlist");
|
|
public static bool ClickTwitterButton() => ClickButton("Canvas - MainMenuScript/Twitter/Button");
|
|
public static bool ClickStatsButton() => ClickButtonByName("SteamStats") || ClickButton("Canvas - MainMenuScript/Leaderboards and stats/SteamStats");
|
|
}
|