fix mentioned issues + add more functionality

This commit is contained in:
Az committed 2026-10-14 00:18:56 -04:00
1 parent 3b336fb27c
commit 19dd1bb497
7 files changed
+167 -46

No files matched your search

+1 -1
View File
@@ -17,7 +17,7 @@ public static class ExampleColors
public static CustomColor Gold { get; } = new("color.gold", new Color(1.0f, 0.84f, 0.0f)); public static CustomColor Gold { get; } = new("color.gold", new Color(1.0f, 0.84f, 0.0f));
public static VariableColor Rainbow { get; } = new("color.rainbow", t => new HsbColor(MathUtilities.PingPong(t, 1f), 1f, 1f)) public static VariableColor Rainbow { get; } = new("color.rainbow", t => new HsbColor(MathUtilities.PingPong(t, 1f, 0.3f), 1f, 1f))
{ {
ColorBrightness = CustomColorBrightness.Lighter, ColorBrightness = CustomColorBrightness.Lighter,
}; };
@@ -80,4 +80,5 @@ Eliminate every other faction.</string>
<string name="color.cerulean">Cerulean</string> <string name="color.cerulean">Cerulean</string>
<string name="color.rose">Rose</string> <string name="color.rose">Rose</string>
<string name="color.gold">Gold</string> <string name="color.gold">Gold</string>
<string name="color.rainbow">Rainbow</string>
</resources> </resources>
+5
View File
@@ -80,6 +80,11 @@ public class CustomColor(StringNames name, Color32 mainColor, Color32 shadowColo
/// </summary> /// </summary>
public enum CustomColorBrightness public enum CustomColorBrightness
{ {
/// <summary>
/// An invalid color.
/// </summary>
Invalid = -1,
/// <summary> /// <summary>
/// A lighter color. /// A lighter color.
/// </summary> /// </summary>
+64 -14
View File
@@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using HarmonyLib; using HarmonyLib;
using UnityEngine; using UnityEngine;
@@ -17,25 +18,45 @@ public static class PaletteManager
internal static readonly List<CustomColor> CustomColors = []; internal static readonly List<CustomColor> CustomColors = [];
internal static readonly HashSet<StringNames> VariableColorNames = []; internal static readonly HashSet<StringNames> VariableColorNames = [];
internal static readonly Dictionary<int, CustomColor> ColorIdToColorMap = [];
private static readonly CustomColorBrightness[] ColorBrightnessMap =
[
CustomColorBrightness.Darker, // Red
CustomColorBrightness.Darker, // Blue
CustomColorBrightness.Darker, // Green
CustomColorBrightness.Lighter, // Pink
CustomColorBrightness.Lighter, // Orange
CustomColorBrightness.Lighter, // Yellow
CustomColorBrightness.Darker, // Black
CustomColorBrightness.Lighter, // White
CustomColorBrightness.Darker, // Purple
CustomColorBrightness.Darker, // Brown
CustomColorBrightness.Lighter, // Cyan
CustomColorBrightness.Lighter, // Lime
CustomColorBrightness.Darker, // Maroon
CustomColorBrightness.Lighter, // Rose
CustomColorBrightness.Lighter, // Banana
CustomColorBrightness.Darker, // Gray
CustomColorBrightness.Darker, // Tan
CustomColorBrightness.Lighter, // Coral
];
private static int originalLength;
internal static void RegisterAllColors() internal static void RegisterAllColors()
{ {
originalLength = Palette.PlayerColors.Length;
var colors = CustomColors.Select(x => x.MainColor).ToArray(); var colors = CustomColors.Select(x => x.MainColor).ToArray();
var shadowColors = CustomColors.Select(x => x.ShadowColor).ToArray(); var shadowColors = CustomColors.Select(x => x.ShadowColor).ToArray();
var stringNames = CustomColors.Select(x => x.Name).ToArray(); var stringNames = CustomColors.Select(x => x.Name).ToArray();
var originalLength = Palette.PlayerColors.Length;
Palette.PlayerColors = Palette.PlayerColors.ToArray().AddRangeToArray(colors); Palette.PlayerColors = Palette.PlayerColors.ToArray().AddRangeToArray(colors);
Palette.ShadowColors = Palette.ShadowColors.ToArray().AddRangeToArray(shadowColors); Palette.ShadowColors = Palette.ShadowColors.ToArray().AddRangeToArray(shadowColors);
Palette.ColorNames = Palette.ColorNames.ToArray().AddRangeToArray(stringNames); Palette.ColorNames = Palette.ColorNames.ToArray().AddRangeToArray(stringNames);
Palette.TextColors = Palette.TextColors.ToArray().AddRangeToArray(colors); Palette.TextColors = Palette.TextColors.ToArray().AddRangeToArray(colors);
Palette.TextOutlineColors = Palette.TextOutlineColors.ToArray().AddRangeToArray(shadowColors); Palette.TextOutlineColors = Palette.TextOutlineColors.ToArray().AddRangeToArray(shadowColors);
for (var i = 0; i < CustomColors.Count; i++)
ColorIdToColorMap[i + originalLength] = CustomColors[i];
} }
/// <summary> /// <summary>
@@ -45,7 +66,7 @@ public static class PaletteManager
/// <returns><c>true</c> if the color is a variable color; <c>false</c> otherwise.</returns> /// <returns><c>true</c> if the color is a variable color; <c>false</c> otherwise.</returns>
public static bool IsVariable(int colorId) public static bool IsVariable(int colorId)
{ {
if (colorId < 0 || colorId >= Palette.ColorNames.Length) if ((uint)colorId >= (uint)Palette.ColorNames.Length)
return false; return false;
return VariableColorNames.Contains(Palette.ColorNames[colorId]); return VariableColorNames.Contains(Palette.ColorNames[colorId]);
@@ -54,11 +75,11 @@ public static class PaletteManager
/// <summary> /// <summary>
/// Checks to see if the provided color ID belongs to a custom color. /// Checks to see if the provided color ID belongs to a custom color.
/// </summary> /// </summary>
/// <param name="colorId">The id of the color.</param> /// <param name="colorId">The ID of the color.</param>
/// <returns><c>true</c> if the color is a custom color; <c>false</c> otherwise.</returns> /// <returns><c>true</c> if the color is a custom color; <c>false</c> otherwise.</returns>
public static bool IsCustomColor(int colorId) public static bool IsCustomColor(int colorId)
{ {
return ColorIdToColorMap.ContainsKey(colorId); return (uint)(colorId - originalLength) < (uint)CustomColors.Count;
} }
/// <summary> /// <summary>
@@ -68,10 +89,10 @@ public static class PaletteManager
/// <returns>The main color associated with the provided ID.</returns> /// <returns>The main color associated with the provided ID.</returns>
public static Color GetMainColor(int colorId) public static Color GetMainColor(int colorId)
{ {
if (colorId < 0 || colorId >= Palette.ColorNames.Length) if ((uint)colorId >= (uint)Palette.ColorNames.Length)
return Color.white; return Color.white;
return !ColorIdToColorMap.TryGetValue(colorId, out var custom) return !TryGetCustomColor(colorId, out var custom)
? Palette.PlayerColors[colorId] ? Palette.PlayerColors[colorId]
: (custom is VariableColor variable : (custom is VariableColor variable
? variable.EvaluateMainColor(Time.time) ? variable.EvaluateMainColor(Time.time)
@@ -81,17 +102,46 @@ public static class PaletteManager
/// <summary> /// <summary>
/// Gets the shadow color of the provided color ID. /// Gets the shadow color of the provided color ID.
/// </summary> /// </summary>
/// <param name="colorId">The id of the color.</param> /// <param name="colorId">The ID of the color.</param>
/// <returns>The shadow color associated with the provided ID.</returns> /// <returns>The shadow color associated with the provided ID.</returns>
public static Color GetShadowColor(int colorId) public static Color GetShadowColor(int colorId)
{ {
if (colorId < 0 || colorId >= Palette.ColorNames.Length) if ((uint)colorId >= (uint)Palette.ColorNames.Length)
return Color.white; return Color.white;
return !ColorIdToColorMap.TryGetValue(colorId, out var custom) return !TryGetCustomColor(colorId, out var custom)
? Palette.ShadowColors[colorId] ? Palette.ShadowColors[colorId]
: (custom is VariableColor variable : (custom is VariableColor variable
? variable.EvaluateShadowColor(Time.time) ? variable.EvaluateShadowColor(Time.time)
: custom.InternalShadowColor); : custom.InternalShadowColor);
} }
/// <summary>
/// Gets the brightness type of the color associated with the provided ID.
/// </summary>
/// <param name="colorId">The ID of the color.</param>
/// <returns>The brightness type of the provided ID.</returns>
public static CustomColorBrightness GetBrightness(int colorId)
{
if ((uint)colorId >= (uint)Palette.ColorNames.Length)
return CustomColorBrightness.Invalid;
return TryGetCustomColor(colorId, out var custom)
? custom.ColorBrightness
: ColorBrightnessMap[colorId];
}
internal static bool TryGetCustomColor(int colorId, [NotNullWhen(true)] out CustomColor? custom)
{
var index = colorId - originalLength;
if ((uint)index >= (uint)CustomColors.Count)
{
custom = null;
return false;
}
custom = CustomColors[index];
return true;
}
} }
+9 -8
View File
@@ -14,8 +14,9 @@ namespace MiraAPI.Colors;
/// <param name="shadowEvaluator">The function to evaluate the dynamic shadow color.</param> /// <param name="shadowEvaluator">The function to evaluate the dynamic shadow color.</param>
/// <param name="mainColor">The static main color used when dynamic colors are disabled.</param> /// <param name="mainColor">The static main color used when dynamic colors are disabled.</param>
/// <param name="shadowColor">The static shadow color used when dynamic colors are disabled.</param> /// <param name="shadowColor">The static shadow color used when dynamic colors are disabled.</param>
public sealed class VariableColor(StringNames name, Func<float, Color> mainEvaluator, Func<float, Color>? shadowEvaluator, Color32? mainColor = null, Color32? shadowColor = null) /// <param name="defaultTime">The default time that is used to automatically fill in the static colors when the latter are not provided.</param>
: CustomColor(name, mainColor ?? mainEvaluator(0f), shadowColor ?? shadowEvaluator?.Invoke(0f) ?? (mainColor ?? mainEvaluator(0f)).GetShadowColor(60)) public sealed class VariableColor(StringNames name, Func<float, Color> mainEvaluator, Func<float, Color>? shadowEvaluator, Color32? mainColor = null, Color32? shadowColor = null, float defaultTime = 0f)
: CustomColor(name, mainColor ?? mainEvaluator(defaultTime), shadowColor ?? shadowEvaluator?.Invoke(defaultTime) ?? (mainColor ?? mainEvaluator(defaultTime)).GetShadowColor(60))
{ {
/// <summary> /// <summary>
/// Gets or sets a delegate that takes in a time value and returns the dynamic main color. /// Gets or sets a delegate that takes in a time value and returns the dynamic main color.
@@ -28,20 +29,20 @@ public sealed class VariableColor(StringNames name, Func<float, Color> mainEvalu
public Func<float, Color> ShadowEvaluator { get; set; } = shadowEvaluator ?? (t => mainEvaluator(t).GetShadowColor(0.24f)); public Func<float, Color> ShadowEvaluator { get; set; } = shadowEvaluator ?? (t => mainEvaluator(t).GetShadowColor(0.24f));
/// <inheritdoc cref="VariableColor"/> /// <inheritdoc cref="VariableColor"/>
public VariableColor(StringNames name, Func<float, Color> mainEvaluator, Color32? mainColor = null) public VariableColor(StringNames name, Func<float, Color> mainEvaluator, Color32? mainColor = null, float defaultTime = 0f)
: this(name, mainEvaluator, null, mainColor, null) : this(name, mainEvaluator, null, mainColor, null, defaultTime)
{ {
} }
/// <inheritdoc cref="VariableColor"/> /// <inheritdoc cref="VariableColor"/>
public VariableColor(string name, Func<float, Color> mainEvaluator, Color32? mainColor = null) public VariableColor(string name, Func<float, Color> mainEvaluator, Color32? mainColor = null, float defaultTime = 0f)
: this(name, mainEvaluator, null, mainColor, null) : this(name, mainEvaluator, null, mainColor, null, defaultTime)
{ {
} }
/// <inheritdoc cref="VariableColor"/> /// <inheritdoc cref="VariableColor"/>
public VariableColor(string name, Func<float, Color> mainEvaluator, Func<float, Color>? shadowEvaluator, Color32? mainColor = null, Color32? shadowColor = null) public VariableColor(string name, Func<float, Color> mainEvaluator, Func<float, Color>? shadowEvaluator, Color32? mainColor = null, Color32? shadowColor = null, float defaultTime = 0f)
: this(MiraLocaleManager.GetOrCreateLocaleString(name), mainEvaluator, shadowEvaluator, mainColor, shadowColor) : this(MiraLocaleManager.GetOrCreateLocaleString(name), mainEvaluator, shadowEvaluator, mainColor, shadowColor, defaultTime)
{ {
} }
+70 -18
View File
@@ -8,43 +8,95 @@ using UnityEngine;
namespace MiraAPI; namespace MiraAPI;
/// <summary> /// <summary>
/// A mono script that adjusts the material colors of a <see cref="SpriteRenderer"/> component that it's attached to based on the provided variable color. /// The base class for variable color behaviour on <see cref="SpriteRenderer"/>s.
/// </summary> /// </summary>
[RegisterInIl2Cpp]
[SuppressMessage("Style", "IDE0051:Remove unused private members", Justification = "Unity methods.")] [SuppressMessage("Style", "IDE0051:Remove unused private members", Justification = "Unity methods.")]
[SuppressMessage("Design", "CA1051:Do not declare visible instance fields", Justification = "Unity fields.")] [SuppressMessage("Design", "CA1051:Do not declare visible instance fields", Justification = "Unity fields.")]
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "Read above.")] [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "Read above.")]
public sealed class VariableColorBehaviour : MonoBehaviour public abstract class BaseVariableColorBehaviour : MonoBehaviour
{ {
private SpriteRenderer rend; /// <summary>
private VariableColor? color; /// The <see cref="VariableColor"/> to apply.
/// </summary>
private static readonly Color VisorColor = Palette.VisorColor; protected VariableColor? color;
/// <summary> /// <summary>
/// Sets the current variable color. /// Sets the current variable color.
/// </summary> /// </summary>
/// <param name="col">The new variable color.</param> /// <param name="newColor">The new <see cref="VariableColor"/>.</param>
[HideFromIl2Cpp] [HideFromIl2Cpp]
public void SetColor(VariableColor? col) public void SetColor(VariableColor? newColor)
{ {
color = col; color = newColor;
}
}
/// <summary>
/// A mono script that adjusts the material colors of a <see cref="Renderer"/> component that it's attached to based on the provided variable color.
/// </summary>
[RegisterInIl2Cpp]
[SuppressMessage("Style", "IDE0051:Remove unused private members", Justification = "Unity methods.")]
public sealed class VariableColorBehaviour : BaseVariableColorBehaviour
{
private Renderer? rend;
private static readonly Color VisorColor = Palette.VisorColor;
/// <summary>
/// Sets the new <see cref="Renderer"/> target.
/// </summary>
/// <param name="newRend">The new <see cref="Renderer"/> that the script must target.</param>
public void SetRend(Renderer? newRend)
{
rend = newRend;
}
private void Awake()
{
rend = GetComponent<Renderer>();
}
private void Update()
{
if (color == null || rend == null)
return;
var time = Time.time;
var material = rend.material;
material.SetColor(ShaderID.VisorColor, VisorColor);
material.SetColor(ShaderID.BodyColor, color.EvaluateMainColor(time));
material.SetColor(ShaderID.BackColor, color.EvaluateShadowColor(time));
}
}
/// <summary>
/// A mono script that adjusts the graphic colors of a <see cref="SpriteRenderer"/> component that it's attached to based on the provided variable color.
/// </summary>
[RegisterInIl2Cpp]
[SuppressMessage("Style", "IDE0051:Remove unused private members", Justification = "Unity methods.")]
public sealed class BasicVariableColorBehaviour : BaseVariableColorBehaviour
{
private SpriteRenderer? rend;
/// <summary>
/// Sets the new <see cref="SpriteRenderer"/> target.
/// </summary>
/// <param name="newRend">The new <see cref="SpriteRenderer"/> that the script must target.</param>
public void SetRend(SpriteRenderer? newRend)
{
rend = newRend;
} }
private void Awake() private void Awake()
{ {
rend = GetComponent<SpriteRenderer>(); rend = GetComponent<SpriteRenderer>();
rend.material.SetColor(ShaderID.VisorColor, VisorColor);
} }
private void Update() private void Update()
{ {
if (!rend || color == null) if (color != null && rend != null)
return; rend.color = color.EvaluateMainColor(Time.time);
var time = Time.time;
var material = rend.material;
material.SetColor(ShaderID.BodyColor, color.EvaluateMainColor(time));
material.SetColor(ShaderID.BackColor, color.EvaluateShadowColor(time));
} }
} }
@@ -7,7 +7,7 @@ using MiraAPI.Utilities;
using Reactor.Utilities.Extensions; using Reactor.Utilities.Extensions;
using UnityEngine; using UnityEngine;
namespace MiraAPI.Patches.Hud; namespace MiraAPI.Patches.Colors;
[HarmonyPatch(typeof(PlayerMaterial))] [HarmonyPatch(typeof(PlayerMaterial))]
internal static class SetPlayerMaterialPatch internal static class SetPlayerMaterialPatch
@@ -16,7 +16,7 @@ internal static class SetPlayerMaterialPatch
public static bool Prefix(int colorId, Renderer rend) public static bool Prefix(int colorId, Renderer rend)
{ {
rend.gameObject.GetOrAddComponent<VariableColorBehaviour>().SetColor( rend.gameObject.GetOrAddComponent<VariableColorBehaviour>().SetColor(
PaletteManager.ColorIdToColorMap.TryGetValue(colorId, out var color) && color is VariableColor variable PaletteManager.TryGetCustomColor(colorId, out var color) && color is VariableColor variable
? variable ? variable
: null); : null);
return !PaletteManager.IsVariable(colorId); return !PaletteManager.IsVariable(colorId);
@@ -48,11 +48,19 @@ internal static class ChatNotifRainbowPatch
public static void Postfix(ChatNotification __instance) public static void Postfix(ChatNotification __instance)
{ {
if (!__instance.gameObject.active || !PaletteManager.IsVariable(__instance.player.cosmetics.ColorId)) if (!__instance.gameObject.active)
return; return;
var str = PaletteManager.GetMainColor(__instance.player.cosmetics.ColorId).ToHtmlStringRGBA(); var colorId = __instance.player.cosmetics.ColorId;
__instance.playerNameText.text = "<color=#" + str + ">" + RichTags.Replace(__instance.playerNameText.text, string.Empty);
if (!PaletteManager.IsVariable(colorId))
return;
var color = PaletteManager.GetMainColor(colorId);
var str = color.ToHtmlStringRGBA();
var nameText = __instance.playerNameText;
nameText.text = "<color=#" + str + ">" + RichTags.Replace(nameText.text, string.Empty);
nameText.outlineColor = color.GetShadowColor(0.5f);
} }
} }
@@ -68,6 +76,10 @@ internal static class RainbowLobbyInfoPanePatch
} }
var host = GameData.Instance.GetHost(); var host = GameData.Instance.GetHost();
if (!host)
return;
var text = PaletteManager.GetMainColor(__instance.player.cosmetics.ColorId).ToHtmlStringRGBA(); var text = PaletteManager.GetMainColor(__instance.player.cosmetics.ColorId).ToHtmlStringRGBA();
__instance.hostLabel.text = TranslationController.Instance.GetString(StringNames.HostNounLabel); __instance.hostLabel.text = TranslationController.Instance.GetString(StringNames.HostNounLabel);