Skip to content

Commit

Permalink
Add quick access Instances and Lists classes
Browse files Browse the repository at this point in the history
  • Loading branch information
doombubbles committed Sep 19, 2023
1 parent 7613a7b commit af181fe
Show file tree
Hide file tree
Showing 5 changed files with 235 additions and 1 deletion.
182 changes: 182 additions & 0 deletions BloonsTD6 Mod Helper/Api/Helpers/Instances.cs
Original file line number Diff line number Diff line change
@@ -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;

/// <summary>
/// Provides quick access to many major BTD6 singleton classes
/// </summary>
[RegisterTypeInIl2Cpp(false)]
public class Instances : MonoBehaviour
{
/// <inheritdoc />
public Instances(IntPtr pointer) : base(pointer)
{
}

/// <summary>
/// The instance of the Game class
/// </summary>
public static Game Game => Game.instance;

/// <summary>
/// The instance of the GameData class
/// </summary>
public static GameData GameData => GameData.Instance;

/// <summary>
/// The base GameModel class
/// </summary>
public static GameModel BaseGameModel => Game.instance.model;

/// <summary>
/// The current instance of the InGame class. Will be null if not in a match.
/// </summary>
public static InGame InGame => InGame.instance;

/// <summary>
/// The instance of the InGameData class that will be used for the next match
/// </summary>
public static InGameData NextInGameData => InGameData.Editable;

/// <summary>
/// The instance of the InGameData class for the current match
/// </summary>
public static ReadonlyInGameData CurrentInGameData => InGameData.CurrentGame;

/// <summary>
/// The current UnityToSimulation bridge. Will be null if not in a game, or if the game isn't fully loaded in
/// </summary>
public static UnityToSimulation UnityToSimulation => InGame?.bridge;

/// <summary>
/// The current UnityToSimulation bridge. Will be null if not in a game, or if the game isn't fully loaded in
/// </summary>
public static UnityToSimulation Bridge => InGame?.bridge;

/// <summary>
/// The current game Simulation. Will be null if not in a game, or if the game isn't fully loaded in.
/// </summary>
public static Simulation Simulation => InGame?.bridge?.simulation;

/// <summary>
/// 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
/// </summary>
public static GameModel CurrentGameModel => UnityToSimulation?.Model;

/// <summary>
/// The TowerManger for the current game. Will be null if not in a game, or if the game isn't fully loaded yet
/// </summary>
public static TowerManager TowerManager => Simulation?.towerManager;

/// <summary>
/// The InputManager for the current player.
/// </summary>
public static InputManager InputManager => Simulation?.GetInputManager(Bridge.MyPlayerNumber);

/// <summary>
/// The CashManager for the current player.
/// </summary>
public static Simulation.CashManager CashManager => Simulation?.GetCashManager(Bridge.MyPlayerNumber);

/// <summary>
/// The current Btd6Player
/// </summary>
public static Btd6Player Btd6Player => Game.Player;

/// <summary>
/// The current player's profile
/// </summary>
public static ProfileModel Profile => Btd6Player?.Data;

/// <summary>
/// The current Display Factory
/// </summary>
public static Factory DisplayFactory => Game.scene?.factory;

/// <summary>
/// The current FactoryFactory (factory for in game factories), or null if not in game
/// </summary>
public static FactoryFactory FactoryFactory => Simulation?.factory;

/// <summary>
/// The current Map in simulation, or null if not in game
/// </summary>
public static Map Map => Simulation?.Map;

#region UI

/// <summary>
/// The current instance of the TowerSelectionMenu component, may be null
/// </summary>
public static TowerSelectionMenu TowerSelectionMenu => TowerSelectionMenu.instance;

/// <summary>
/// The current instance of the PopupScreen component
/// </summary>
public static PopupScreen PopupScreen => PopupScreen.instance;

/// <summary>
/// The current instance of the ShopMenu component, may be null
/// </summary>
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

/// <summary>
/// The current NetworkedUnityToSimulation bridge. Will be null if not in a coop game, or if the game isn't fully loaded in
/// </summary>
public static NetworkedUnityToSimulation CoOpUnityToSimulation => InGame?.bridge?.TryCast<NetworkedUnityToSimulation>();

/// <summary>
/// The current NetworkedUnityToSimulation bridge. Will be null if not in a coop game, or if the game isn't fully loaded in
/// </summary>
public static UnityToSimulation CoOpBridge => InGame?.bridge?.TryCast<NetworkedUnityToSimulation>();

/// <summary>
/// The instance of the Btd6CoopGameNetworked class. Will be null if not in a coop game
/// </summary>
public static Btd6CoopGameNetworked Btd6CoopGame => InGame?.coopGame?.TryCast<Btd6CoopGameNetworked>();

/// <summary>
/// The instance of the GameConnection class. Will be null if not in a coop game
/// </summary>
public static GameConnection GameConnection => Btd6CoopGame?.Connection;

/// <summary>
/// The instance of the NKMultiConnection class. Will be null if not in a coop game
/// </summary>
public static NKMultiConnection NKMultiConnection => GameConnection?.Connection;

/// <summary>
/// The instance of the NKMultiGameInterface class. Will be null if not in a coop game
/// </summary>
public static NKMultiGameInterface NKGI => NKMultiConnection?.NKGI;

#endregion
}
34 changes: 34 additions & 0 deletions BloonsTD6 Mod Helper/Api/Helpers/Lists.cs
Original file line number Diff line number Diff line change
@@ -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;

/// <summary>
/// Provides quick access to many major BTD6 object lists
/// </summary>
[RegisterTypeInIl2Cpp(false)]
public class Lists : MonoBehaviour
{
/// <inheritdoc />
public Lists(IntPtr pointer) : base(pointer)
{
}

/// <summary>
/// All towers currently placed in the game, or null if not in a game
/// </summary>
public static Tower[] AllTowers => Instances.TowerManager?.GetTowers().ToIl2CppList().ToArray();

/// <summary>
/// All TowerToSimulation objects currently placed in the game, or null if not in a game
/// </summary>
public static TowerToSimulation[] AllTTS => Instances.Bridge?.ttss.ToArray();

/// <summary>
/// All Entities in the current game, or null if not in a game
/// </summary>
public static Entity[] AllEntities => Instances.FactoryFactory?.GetUncast<Entity>().ToArray();
}
5 changes: 4 additions & 1 deletion BloonsTD6 Mod Helper/LATEST.md
Original file line number Diff line number Diff line change
@@ -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
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<Btd6CoopGameNetworked>().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
5 changes: 5 additions & 0 deletions BloonsTD6 Mod Helper/MelonMain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ public void Schedule_GameData_Loaded()
() => GameData.Instance != null);
}

public override void OnInGameLoaded(InGame inGame)
{
inGame.gameObject.AddComponent<Instances>();
}

public override void OnLoadSettings(JObject settings)
{
var version = settings["Version"];
Expand Down
10 changes: 10 additions & 0 deletions BloonsTD6 Mod Helper/Patches/UI/TitleScreen_Start.cs
Original file line number Diff line number Diff line change
@@ -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))]
Expand All @@ -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<Instances>();
gameObject.AddComponent<Lists>();

// Tests.ModelSerializationTests.TestSerialization(Game.instance.model);

Expand Down

0 comments on commit af181fe

Please sign in to comment.