Skip to content

Commit

Permalink
Add mainmenu support
Browse files Browse the repository at this point in the history
  • Loading branch information
js6pak committed Aug 22, 2024
1 parent 7c9fe57 commit 6ec8b5b
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 25 deletions.
2 changes: 1 addition & 1 deletion Reactor.Example/ExamplePlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public partial class ExamplePlugin : BasePlugin

public override void Load()
{
ReactorPingTracker.Register<ExamplePlugin>(ReactorPingTracker.AlwaysShow);
ReactorCredits.Register<ExamplePlugin>(ReactorCredits.AlwaysShow);

this.AddComponent<ExampleComponent>();

Expand Down
2 changes: 1 addition & 1 deletion Reactor/Patches/Miscellaneous/PingTrackerPatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ internal static class PingTrackerPatch
[HarmonyPriority(Priority.Last)]
public static void Postfix(PingTracker __instance)
{
var extraText = ReactorPingTracker.GetText();
var extraText = ReactorCredits.GetText(ReactorCredits.Location.PingTracker);
if (extraText != null)
{
if (!__instance.text.text.EndsWith("\n", StringComparison.InvariantCulture)) __instance.text.text += "\n";
Expand Down
8 changes: 8 additions & 0 deletions Reactor/Patches/ReactorVersionShower.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using BepInEx;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Reactor.Utilities;
using Reactor.Utilities.Extensions;
using TMPro;
using UnityEngine;
Expand Down Expand Up @@ -98,6 +99,13 @@ public static void UpdateText()
Text.text = "Reactor " + Version.Parse(ReactorPlugin.Version).WithoutBuild();
Text.text += "\nBepInEx " + Paths.BepInExVersion.WithoutBuild();
Text.text += "\nMods: " + IL2CPPChainloader.Instance.Plugins.Count;

var creditsText = ReactorCredits.GetText(ReactorCredits.Location.MainMenu);
if (creditsText != null)
{
Text.text += "\n" + creditsText;
}

TextUpdated?.Invoke(Text);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,57 +2,78 @@
using System.Collections.Generic;
using System.Linq;
using BepInEx.Unity.IL2CPP;
using Reactor.Patches;
using Reactor.Utilities.Extensions;

namespace Reactor.Utilities;

/// <summary>
/// Controls the PingTracker.
/// Provides a way for mods to show their version information in-game.
/// </summary>
public static class ReactorPingTracker
public static class ReactorCredits
{
private readonly struct ModIdentifier(string name, string version, Func<bool>? shouldShow, bool isPreRelease)
private readonly struct ModIdentifier(string name, string version, Func<Location, bool>? shouldShow, bool isPreRelease)
{
private const string NormalColor = "#fff";
private const string PreReleaseColor = "#f00";

public string Name => name;

public bool ShouldShow => shouldShow == AlwaysShow || shouldShow();
public string Text { get; } = $"{name} {version}".EscapeRichText().Color(isPreRelease ? PreReleaseColor : NormalColor);

public bool ShouldShow(Location location)
{
return shouldShow == AlwaysShow || shouldShow(location);
}
}

private static readonly List<ModIdentifier> _modIdentifiers = [];

/// <summary>
/// Represents the location of where the credit is shown.
/// </summary>
public enum Location
{
/// <summary>
/// In the main menu under Reactor/BepInEx versions.
/// </summary>
MainMenu,

/// <summary>
/// During game under the ping tracker.
/// </summary>
PingTracker,
}

/// <summary>
/// A special value indicating a mod should always show.
/// </summary>
public const Func<bool>? AlwaysShow = null;
public const Func<Location, bool>? AlwaysShow = null;

/// <summary>
/// Registers a mod with the <see cref="ReactorPingTracker"/>, adding it to the list of mods that will be displayed in the PingTracker.
/// Registers a mod with the <see cref="ReactorCredits"/>, adding it to the list of mods that will be displayed.
/// </summary>
/// <param name="name">The user-friendly name of the mod. Can contain spaces or special characters.</param>
/// <param name="version">The version of the mod.</param>
/// <param name="isPreRelease">If this version is a development or beta version. If true, it will display the mod in red in the PingTracker.</param>
/// <param name="isPreRelease">If this version is a development or beta version. If true, it will display the mod in red.</param>
/// <param name="shouldShow">
/// This function will be called every frame to determine if the mod should be displayed or not.
/// This function should return false if your mod is currently disabled or has no effect on gameplay at the time.
/// If you want the mod to be displayed at all times, you can set this parameter to <see cref="ReactorPingTracker.AlwaysShow"/>.
/// If you want the mod to be displayed at all times, you can set this parameter to <see cref="ReactorCredits.AlwaysShow"/>.
/// </param>
public static void Register(string name, string version, bool isPreRelease, Func<bool>? shouldShow)
public static void Register(string name, string version, bool isPreRelease, Func<Location, bool>? shouldShow)
{
const int MaxLength = 60;

if (name.Length + version.Length > MaxLength)
{
Error($"Not registering mod \"{name}\" with version \"{version}\" in {nameof(ReactorPingTracker)} because the combined length of the mod name and version is greater than {MaxLength} characters.");
Error($"Not registering mod \"{name}\" with version \"{version}\" in {nameof(ReactorCredits)} because the combined length of the mod name and version is greater than {MaxLength} characters.");
return;
}

if (_modIdentifiers.Any(m => m.Name == name))
{
Error($"Mod \"{name}\" is already registered in {nameof(ReactorPingTracker)}.");
Error($"Mod \"{name}\" is already registered in {nameof(ReactorCredits)}.");
return;
}

Expand All @@ -62,20 +83,22 @@ public static void Register(string name, string version, bool isPreRelease, Func

if (!isPreRelease)
{
Info($"Mod \"{name}\" registered in {nameof(ReactorPingTracker)} with version {version}.");
Info($"Mod \"{name}\" registered in {nameof(ReactorCredits)} with version {version}.");
}
else
{
Warning($"Mod \"{name}\" registered in {nameof(ReactorPingTracker)} with DEVELOPMENT/BETA version {version}.");
Warning($"Mod \"{name}\" registered in {nameof(ReactorCredits)} with DEVELOPMENT/BETA version {version}.");
}

ReactorVersionShower.UpdateText();
}

/// <summary>
/// Registers a mod with the <see cref="ReactorPingTracker"/>, adding it to the list of mods that will be displayed in the PingTracker.
/// Registers a mod with the <see cref="ReactorCredits"/>, adding it to the list of mods that will be displayed.
/// </summary>
/// <typeparam name="T">The BepInEx plugin type to get the name and version from.</typeparam>
/// <param name="shouldShow"><inheritdoc cref="Register(string,string,bool,System.Func{bool})" path="/param[@name='shouldShow']"/></param>
public static void Register<T>(Func<bool>? shouldShow) where T : BasePlugin
/// <param name="shouldShow"><inheritdoc cref="Register(string,string,bool,System.Func{Location,bool})" path="/param[@name='shouldShow']"/></param>
public static void Register<T>(Func<Location, bool>? shouldShow) where T : BasePlugin
{
var pluginInfo = IL2CPPChainloader.Instance.Plugins.Values.SingleOrDefault(p => p.TypeName == typeof(T).FullName)
?? throw new ArgumentException("Couldn't find the metadata for the provided plugin type", nameof(T));
Expand All @@ -85,14 +108,16 @@ public static void Register<T>(Func<bool>? shouldShow) where T : BasePlugin
Register(metadata.Name, metadata.Version.WithoutBuild().Clean(), metadata.Version.IsPreRelease, shouldShow);
}

internal static string? GetText()
internal static string? GetText(Location location)
{
var mods = _modIdentifiers.Where(m => m.ShouldShow).Select(m => m.Text).ToArray();
if (mods.Length == 0)
{
return null;
}
var modTexts = _modIdentifiers.Where(m => m.ShouldShow(location)).Select(m => m.Text).ToArray();
if (modTexts.Length == 0) return null;

return ("<space=3em>" + string.Join(", ", mods)).Size("50%").Align("center");
return location switch
{
Location.MainMenu => string.Join('\n', modTexts),
Location.PingTracker => ("<space=3em>" + string.Join(", ", modTexts)).Size("50%").Align("center"),
_ => throw new ArgumentOutOfRangeException(nameof(location), location, null),
};
}
}

0 comments on commit 6ec8b5b

Please sign in to comment.