diff --git a/CLre/API/App/Client.cs b/CLre/API/App/Client.cs index c1c6ca3..51d4bcf 100644 --- a/CLre/API/App/Client.cs +++ b/CLre/API/App/Client.cs @@ -29,14 +29,43 @@ namespace CLre.API.App add => FrontEndGuiEngine_SetMainMenuEnabled_Patch.postMenuEnabled += value; remove => FrontEndGuiEngine_SetMainMenuEnabled_Patch.postMenuEnabled -= value; } + + public static event EventHandler MenuReady + { + add => MenuReadyEngine.menuEngineReady += value; + remove => MenuReadyEngine.menuEngineReady -= value; + } + + public static event EventHandler GameReady + { + add => GameReadyEngine.gameEngineReady += value; + remove => GameReadyEngine.gameEngineReady -= value; + } + + public static event EventHandler GameFrameworkReady + { + add => GameFrameworkEngine.gameFrameworkReady += value; + remove => GameFrameworkEngine.gameFrameworkReady += value; + } + + public static event EventHandler GameFrameworkExit + { + add => GameFrameworkEngine.gameFrameworkExit += value; + remove => GameFrameworkEngine.gameFrameworkExit += value; + } public static string Version { get => Game.Utilities.VersionReader.GetVersion(); } + + static Client() + { + new MenuReadyEngine(); + new GameReadyEngine(); + new GameFrameworkEngine(); + } } - - public struct SetupEventArgs {} [HarmonyPatch(typeof(FrontEnd.MainFrontEnd), "SetupContainer")] class FrontEnd_SetupContainer_Patch diff --git a/CLre/API/App/ClientEngines.cs b/CLre/API/App/ClientEngines.cs new file mode 100644 index 0000000..b699fad --- /dev/null +++ b/CLre/API/App/ClientEngines.cs @@ -0,0 +1,62 @@ +using System; +using CLre.API.Engines; +using Svelto.Context; +using Svelto.ECS; + +namespace CLre.API.App +{ + class GameReadyEngine : GameObsoleteEnginePostBuild, IWaitForFrameworkInitialization + { + internal static event EventHandler gameEngineReady; + + public override void Ready() + { + if (gameEngineReady != null) gameEngineReady(this, new GameReady { }); + } + + public override IEntitiesDB entitiesDB { get; set; } + public override IEntityFactory entityFactory { get; set; } + + public void OnFrameworkInitialized() + { + // TODO framework init event + } + } + + class GameFrameworkEngine : GameObsoleteEnginePostBuild, IWaitForFrameworkInitialization, IWaitForFrameworkDestruction + { + internal static event EventHandler gameFrameworkReady; + + internal static event EventHandler gameFrameworkExit; + + public override void Ready() + { + } + + public override IEntitiesDB entitiesDB { get; set; } + public override IEntityFactory entityFactory { get; set; } + + public void OnFrameworkInitialized() + { + if (gameFrameworkReady != null) gameFrameworkReady(this, new GameReady { }); + } + + public void OnFrameworkDestroyed() + { + if (gameFrameworkExit != null) gameFrameworkExit(this, new GameExit { }); + } + } + + class MenuReadyEngine : FrontEndObsoleteEnginePostBuild + { + internal static event EventHandler menuEngineReady; + + public override void Ready() + { + if (menuEngineReady != null) menuEngineReady(this, new MenuReady { }); + } + + public override IEntitiesDB entitiesDB { get; set; } + public override IEntityFactory entityFactory { get; set; } + } +} \ No newline at end of file diff --git a/CLre/API/App/ClientEventArgs.cs b/CLre/API/App/ClientEventArgs.cs new file mode 100644 index 0000000..6dc25b9 --- /dev/null +++ b/CLre/API/App/ClientEventArgs.cs @@ -0,0 +1,11 @@ +namespace CLre.API.App +{ + + public struct SetupEventArgs {} + + public struct GameReady{} + + public struct GameExit{} + + public struct MenuReady{} +} \ No newline at end of file diff --git a/CLre/API/Characters/AccountUtilityPatches.cs b/CLre/API/Characters/AccountUtilityPatches.cs new file mode 100644 index 0000000..65c3994 --- /dev/null +++ b/CLre/API/Characters/AccountUtilityPatches.cs @@ -0,0 +1,28 @@ +using System.Reflection; +using HarmonyLib; +using User.Server; + +namespace CLre.API.Characters +{ + [HarmonyPatch] + class AccountUtility_GetUserFlags_Patch + { + internal static bool superuser = false; + + private static UserFlags superFlags = UserFlags.userlogged | UserFlags.BucketB | UserFlags.BucketA | + UserFlags.NoDrop | UserFlags.GiveInv | UserFlags.Dev | UserFlags.None; + + [HarmonyPrefix] + public static bool BeforeMethodCall(ref UserFlags __result) + { + if (superuser) __result = superFlags; + return !superuser; + } + + [HarmonyTargetMethod] + public static MethodBase Target() + { + return AccessTools.Method("Game.Utilities.Account.AccountUtility:GetUserFlags"); + } + } +} \ No newline at end of file diff --git a/CLre/API/Characters/Character.cs b/CLre/API/Characters/Character.cs new file mode 100644 index 0000000..a16c05b --- /dev/null +++ b/CLre/API/Characters/Character.cs @@ -0,0 +1,107 @@ +using System; +using System.Reflection; +using CLre.API.Engines; +using HarmonyLib; +using NetworkFramework.Shared; +using Svelto.ECS; +using Svelto.Obsolete.ECS; + +namespace CLre.API.Characters +{ + public class Character + { + private bool isCurrent; + + private readonly CharacterEngine _characterEngine = new CharacterEngine(); + + private static readonly FieldInfo _AccountUtility__username = + AccessTools.Field(AccessTools.TypeByName("Game.Utilities.Account.AccountUtility"), "_username"); + + public string Username + { + get + { + if (isCurrent) + { + return _AccountUtility__username.GetValue(null) as string; + } + + return null; + } + } + + /// + /// When enabled, all user flags for the current user are set to one, so they unlock all client functionality + /// + public bool Superuser + { + get => AccountUtility_GetUserFlags_Patch.superuser; + set => AccountUtility_GetUserFlags_Patch.superuser = value; + } + + public static Character Local() + { + Character localChar = new Character(); + localChar.isCurrent = true; + return localChar; + } + } + + internal class CharacterEngine : GameObsoleteEnginePostBuild + { + + public override void Ready() + { + } + + public override IEntitiesDB entitiesDB { get; set; } + public override IEntityFactory entityFactory { get; set; } + + public bool GetGodModeRequested() + { + if (entitiesDB == null) return false; + // TODO cache this conversion operation + // equivalent to + // return DEPRECATED_SveltoExtensions.GetFirstNodeDeprecatedMethod()?.godModeRequestComponent.value + Type cgmrd = AccessTools.TypeByName("Game.GodMode.ClientGodModeRequestNode"); + Type igmrc = AccessTools.TypeByName("Game.GodMode.IGodModeRequestComponent"); + MethodInfo cgmrdFirstNode = AccessTools.Method(typeof(DEPRECATED_SveltoExtensions), "GetFirstNoteDeprecatedMethod") + .MakeGenericMethod(cgmrd); + FieldInfo cgmrdIField = AccessTools.Field(cgmrd, "godModeRequestComponent"); + MethodInfo igmrcReqGodMode = AccessTools.PropertyGetter(igmrc, "requestGodMode"); + // op start + object firstNode = cgmrdFirstNode.Invoke(null, new []{entitiesDB}); + if (firstNode != null) + { + object godModeRequestComponent = cgmrdIField.GetValue(firstNode); + ObsoleteDispatchOnSet requestGodMode = (ObsoleteDispatchOnSet)igmrcReqGodMode.Invoke(godModeRequestComponent, new object[]{}); + return requestGodMode.value; + } + return false; + } + + public void SetGodModeRequested(bool val) + { + if (entitiesDB == null) return; + // TODO cache this conversion operation + //DEPRECATED_SveltoExtensions.GetFirstNodeDeprecatedMethod() + Type cgmrd = AccessTools.TypeByName("Game.GodMode.ClientGodModeRequestNode"); + Type igmrc = AccessTools.TypeByName("Game.GodMode.IGodModeRequestComponent"); + MethodInfo cgmrdFirstNode = AccessTools.Method(typeof(DEPRECATED_SveltoExtensions), "GetFirstNoteDeprecatedMethod") + .MakeGenericMethod(cgmrd); + FieldInfo cgmrdIField = AccessTools.Field(cgmrd, "godModeRequestComponent"); + MethodInfo igmrcReqGodMode = AccessTools.PropertyGetter(igmrc, "requestGodMode"); + // operation start + object firstNode = cgmrdFirstNode.Invoke(null, new []{entitiesDB}); + Utility.Logging.MetaLog($"firstNode is null? {firstNode == null}"); + if (firstNode != null) + { + Utility.Logging.MetaLog($"firstNode is type {firstNode.GetType().FullName}"); + object godModeRequestComponent = cgmrdIField.GetValue(firstNode); + ObsoleteDispatchOnSet requestGodMode = (ObsoleteDispatchOnSet)igmrcReqGodMode.Invoke(godModeRequestComponent, new object[]{}); + requestGodMode.value = val; + Utility.Logging.MetaLog($"SetGodModeRequested completed successfully"); + } + } + } +} \ No newline at end of file diff --git a/CLre/CLre.cs b/CLre/CLre.cs index 99645d3..009a236 100644 --- a/CLre/CLre.cs +++ b/CLre/CLre.cs @@ -3,13 +3,14 @@ using System.Diagnostics; using System.Linq; using System.Reflection; using System.Text; +using CLre.API.Characters; using HarmonyLib; using Svelto.ECS; using UnityEngine; namespace CLre { - public class CLre : IllusionPlugin.IEnhancedPlugin // the Illusion Plugin Architecture (IPA) will ignore classes that don't implement IPlugin' + public class CLre : IllusionPlugin.IEnhancedPlugin // the Illusion Plugin Architecture (IPA) will ignore classes that don't implement IPlugin { public override string Name { get; } = Assembly.GetExecutingAssembly().GetName().Name; @@ -40,7 +41,7 @@ namespace CLre // misc LogIPAPlugins(); Fixes.BugfixAttributeUtility.LogBugfixes(); - + // Log info API.Utility.Logging.MetaLog($"{Name} init complete."); @@ -55,6 +56,14 @@ namespace CLre ? EasyAntiCheat.Client.Hydra.Runtime.Integrity.ViolationMessage : "")); }; + + API.App.Client.MenuReady += (_, __) => { API.Utility.Logging.MetaLog("Menu engine ready event fired!"); }; + API.App.Client.GameReady += (_, __) => { API.Utility.Logging.MetaLog("Game engine ready event fired!"); }; + API.App.Client.GameFrameworkReady += (_, __) => { API.Utility.Logging.MetaLog("Game framework ready event fired!"); }; + API.App.Client.GameFrameworkExit += (_, __) => { API.Utility.Logging.MetaLog("Game framework exit event fired!"); }; + + Character c = Character.Local(); + c.Superuser = true; #endif }