diff --git a/BloonsTD6 Mod Helper/Api/Helpers/Instances.cs b/BloonsTD6 Mod Helper/Api/Helpers/Instances.cs new file mode 100644 index 000000000..81e5a1e24 --- /dev/null +++ b/BloonsTD6 Mod Helper/Api/Helpers/Instances.cs @@ -0,0 +1,182 @@ +using System; +using Il2CppAssets.Scripts.Data; +using Il2CppAssets.Scripts.Models; +using Il2CppAssets.Scripts.Models.Profile; +using Il2CppAssets.Scripts.Simulation; +using Il2CppAssets.Scripts.Simulation.Factory; +using Il2CppAssets.Scripts.Simulation.Towers; +using Il2CppAssets.Scripts.Simulation.Track; +using Il2CppAssets.Scripts.Unity; +using Il2CppAssets.Scripts.Unity.Bridge; +using Il2CppAssets.Scripts.Unity.Display; +using Il2CppAssets.Scripts.Unity.Network; +using Il2CppAssets.Scripts.Unity.Player; +using Il2CppAssets.Scripts.Unity.UI_New.InGame; +using Il2CppAssets.Scripts.Unity.UI_New.InGame.RightMenu; +using Il2CppAssets.Scripts.Unity.UI_New.InGame.TowerSelectionMenu; +using Il2CppAssets.Scripts.Unity.UI_New.Popups; +using Il2CppNinjaKiwi.LiNK.Lobbies; +using Il2CppNinjaKiwi.NKMulti; +using UnityEngine; +using InputManager = Il2CppAssets.Scripts.Simulation.Input.InputManager; +using NKMultiConnection = Il2CppNinjaKiwi.LiNK.Lobbies.NKMultiConnection; + +// ReSharper disable Unity.NoNullPropagation +namespace BTD_Mod_Helper.Api.Helpers; + +/// +/// Provides quick access to many major BTD6 singleton classes +/// +[RegisterTypeInIl2Cpp(false)] +public class Instances : MonoBehaviour +{ + /// + public Instances(IntPtr pointer) : base(pointer) + { + } + + /// + /// The instance of the Game class + /// + public static Game Game => Game.instance; + + /// + /// The instance of the GameData class + /// + public static GameData GameData => GameData.Instance; + + /// + /// The base GameModel class + /// + public static GameModel BaseGameModel => Game.instance.model; + + /// + /// The current instance of the InGame class. Will be null if not in a match. + /// + public static InGame InGame => InGame.instance; + + /// + /// The instance of the InGameData class that will be used for the next match + /// + public static InGameData NextInGameData => InGameData.Editable; + + /// + /// The instance of the InGameData class for the current match + /// + public static ReadonlyInGameData CurrentInGameData => InGameData.CurrentGame; + + /// + /// The current UnityToSimulation bridge. Will be null if not in a game, or if the game isn't fully loaded in + /// + public static UnityToSimulation UnityToSimulation => InGame?.bridge; + + /// + /// The current UnityToSimulation bridge. Will be null if not in a game, or if the game isn't fully loaded in + /// + public static UnityToSimulation Bridge => InGame?.bridge; + + /// + /// The current game Simulation. Will be null if not in a game, or if the game isn't fully loaded in. + /// + public static Simulation Simulation => InGame?.bridge?.simulation; + + /// + /// The modified GameModel that's being used for the current game. Will be null if not in a game, or if the game isn't fully loaded yet + /// + public static GameModel CurrentGameModel => UnityToSimulation?.Model; + + /// + /// The TowerManger for the current game. Will be null if not in a game, or if the game isn't fully loaded yet + /// + public static TowerManager TowerManager => Simulation?.towerManager; + + /// + /// The InputManager for the current player. + /// + public static InputManager InputManager => Simulation?.GetInputManager(Bridge.MyPlayerNumber); + + /// + /// The CashManager for the current player. + /// + public static Simulation.CashManager CashManager => Simulation?.GetCashManager(Bridge.MyPlayerNumber); + + /// + /// The current Btd6Player + /// + public static Btd6Player Btd6Player => Game.Player; + + /// + /// The current player's profile + /// + public static ProfileModel Profile => Btd6Player?.Data; + + /// + /// The current Display Factory + /// + public static Factory DisplayFactory => Game.scene?.factory; + + /// + /// The current FactoryFactory (factory for in game factories), or null if not in game + /// + public static FactoryFactory FactoryFactory => Simulation?.factory; + + /// + /// The current Map in simulation, or null if not in game + /// + public static Map Map => Simulation?.Map; + + #region UI + + /// + /// The current instance of the TowerSelectionMenu component, may be null + /// + public static TowerSelectionMenu TowerSelectionMenu => TowerSelectionMenu.instance; + + /// + /// The current instance of the PopupScreen component + /// + public static PopupScreen PopupScreen => PopupScreen.instance; + + /// + /// The current instance of the ShopMenu component, may be null + /// + public static ShopMenu ShopMenu => ShopMenu.instance; + + // There's a bunch of other `.instance`s for other menus, but that's getting a bit niche to list them all + + #endregion + + #region Co-Op + + /// + /// The current NetworkedUnityToSimulation bridge. Will be null if not in a coop game, or if the game isn't fully loaded in + /// + public static NetworkedUnityToSimulation CoOpUnityToSimulation => InGame?.bridge?.TryCast(); + + /// + /// The current NetworkedUnityToSimulation bridge. Will be null if not in a coop game, or if the game isn't fully loaded in + /// + public static UnityToSimulation CoOpBridge => InGame?.bridge?.TryCast(); + + /// + /// The instance of the Btd6CoopGameNetworked class. Will be null if not in a coop game + /// + public static Btd6CoopGameNetworked Btd6CoopGame => InGame?.coopGame?.TryCast(); + + /// + /// The instance of the GameConnection class. Will be null if not in a coop game + /// + public static GameConnection GameConnection => Btd6CoopGame?.Connection; + + /// + /// The instance of the NKMultiConnection class. Will be null if not in a coop game + /// + public static NKMultiConnection NKMultiConnection => GameConnection?.Connection; + + /// + /// The instance of the NKMultiGameInterface class. Will be null if not in a coop game + /// + public static NKMultiGameInterface NKGI => NKMultiConnection?.NKGI; + + #endregion +} \ No newline at end of file diff --git a/BloonsTD6 Mod Helper/Api/Helpers/Lists.cs b/BloonsTD6 Mod Helper/Api/Helpers/Lists.cs new file mode 100644 index 000000000..480a68648 --- /dev/null +++ b/BloonsTD6 Mod Helper/Api/Helpers/Lists.cs @@ -0,0 +1,34 @@ +using System; +using Il2CppAssets.Scripts.Simulation.Objects; +using Il2CppAssets.Scripts.Simulation.Towers; +using Il2CppAssets.Scripts.Unity.Bridge; +using Il2CppSystem.IO; +using UnityEngine; +namespace BTD_Mod_Helper.Api.Helpers; + +/// +/// Provides quick access to many major BTD6 object lists +/// +[RegisterTypeInIl2Cpp(false)] +public class Lists : MonoBehaviour +{ + /// + public Lists(IntPtr pointer) : base(pointer) + { + } + + /// + /// All towers currently placed in the game, or null if not in a game + /// + public static Tower[] AllTowers => Instances.TowerManager?.GetTowers().ToIl2CppList().ToArray(); + + /// + /// All TowerToSimulation objects currently placed in the game, or null if not in a game + /// + public static TowerToSimulation[] AllTTS => Instances.Bridge?.ttss.ToArray(); + + /// + /// All Entities in the current game, or null if not in a game + /// + public static Entity[] AllEntities => Instances.FactoryFactory?.GetUncast().ToArray(); +} \ No newline at end of file diff --git a/BloonsTD6 Mod Helper/LATEST.md b/BloonsTD6 Mod Helper/LATEST.md index 08f1b19f8..d8b852172 100644 --- a/BloonsTD6 Mod Helper/LATEST.md +++ b/BloonsTD6 Mod Helper/LATEST.md @@ -1,3 +1,6 @@ - Added setting to toggle Mod Browser Populating on Startup - From my personal testing, this leads to ~1s faster startup on average, in exchange for waiting 5s - 10s when you - first open the browser \ No newline at end of file + first open the browser +- Added `Instances` and `Lists` classes for modders that have getters for commonly used BTD6 singleton classes and game objects + - eg `InGame.instance.coopGame.Cast().Connection.Connection.NKGI` can instead be `Instances.NKGI` + - Also gets added as a component to a Game Object at the root of a global scene, so you can easily access fields with Unity Explorer \ No newline at end of file diff --git a/BloonsTD6 Mod Helper/MelonMain.cs b/BloonsTD6 Mod Helper/MelonMain.cs index a7ff2e620..fafddb1f3 100644 --- a/BloonsTD6 Mod Helper/MelonMain.cs +++ b/BloonsTD6 Mod Helper/MelonMain.cs @@ -126,6 +126,11 @@ public void Schedule_GameData_Loaded() () => GameData.Instance != null); } + public override void OnInGameLoaded(InGame inGame) + { + inGame.gameObject.AddComponent(); + } + public override void OnLoadSettings(JObject settings) { var version = settings["Version"]; diff --git a/BloonsTD6 Mod Helper/Patches/UI/TitleScreen_Start.cs b/BloonsTD6 Mod Helper/Patches/UI/TitleScreen_Start.cs index f7453600c..44b1cadac 100644 --- a/BloonsTD6 Mod Helper/Patches/UI/TitleScreen_Start.cs +++ b/BloonsTD6 Mod Helper/Patches/UI/TitleScreen_Start.cs @@ -1,11 +1,15 @@ using System.Linq; using BTD_Mod_Helper.Api; using BTD_Mod_Helper.Api.Data; +using BTD_Mod_Helper.Api.Helpers; using BTD_Mod_Helper.Api.Internal; using BTD_Mod_Helper.Api.ModOptions; using BTD_Mod_Helper.Api.Scenarios; using Il2CppAssets.Scripts.Data; +using Il2CppAssets.Scripts.Unity; using Il2CppAssets.Scripts.Unity.Scenes; +using UnityEngine; +using UnityEngine.SceneManagement; namespace BTD_Mod_Helper.Patches.UI; [HarmonyPatch(typeof(TitleScreen), nameof(TitleScreen.Start))] @@ -32,6 +36,12 @@ internal static void Postfix() ModSettingsHandler.SaveModSettings(true); ModHelperData.SaveAll(); ModGameMode.ModifyDefaultGameModes(GameData.Instance); + + + var gameObject = new GameObject("ModHelperQuickAccess"); + SceneManager.MoveGameObjectToScene(gameObject, Game.instance.gameObject.scene); + gameObject.AddComponent(); + gameObject.AddComponent(); // Tests.ModelSerializationTests.TestSerialization(Game.instance.model);