Decompiled source of RainbowEffects v1.0.0

Mods/RainbowEffects.dll

Decompiled a day ago
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppRUMBLE.Managers;
using Il2CppRUMBLE.Pools;
using Il2CppRUMBLE.Utilities;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using RainbowEffects;
using RumbleModdingAPI.RMAPI;
using UIFramework;
using UIFramework.UiExtensions;
using UnityEngine;
using UnityEngine.VFX;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(global::RainbowEffects.RainbowEffects), "RainbowEffects", "1.0.0", "ninjaguardian", "https://thunderstore.io/c/rumble/p/ninjaguardian/RainbowEffects")]
[assembly: MelonGame("Buckethead Entertainment", "RUMBLE")]
[assembly: MelonColor(255, 0, 160, 230)]
[assembly: MelonAuthorColor(255, 0, 160, 230)]
[assembly: MelonPlatformDomain(/*Could not decode attribute arguments.*/)]
[assembly: VerifyLoaderVersion("0.7.2", true)]
[assembly: MelonIncompatibleAssemblies(new string[] { "RainbowGuard" })]
[assembly: UIInfo("Rainbow Effects")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("ninjaguardian")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © 2026 ninjaguardian")]
[assembly: AssemblyDescription("Changes the colors of various effects")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("RainbowEffects")]
[assembly: AssemblyTitle("RainbowEffects")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/ninjaguardian/RainbowEffects")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace RainbowEffects
{
	public static class BuildInfo
	{
		public const string ProperName = "Rainbow Effects";

		public const string ModName = "RainbowEffects";

		public const string ModVersion = "1.0.0";

		public const string MLVersion = "0.7.2";

		public const string Author = "ninjaguardian";

		public const string DownloadLink = "https://thunderstore.io/c/rumble/p/ninjaguardian/RainbowEffects";

		public const string ConfigFile = "config.cfg";
	}
	internal record RainbowEffectsResource(Material Mat, Shader Original, Shader Rainbow)
	{
		public RainbowEffectsResource(Material mat, Shader rainbow)
			: this(mat, mat.shader, rainbow)
		{
		}

		internal void SetRainbow()
		{
			Mat.shader = Rainbow;
		}

		internal void SetOriginal()
		{
			Mat.shader = Original;
		}
	}
	public class RainbowEffects : MelonMod
	{
		private const float Phase120 = (float)Math.PI * 2f / 3f;

		private const float Phase240 = 4.1887903f;

		private static readonly string ConfigDir = Path.Combine(MelonEnvironment.UserDataDirectory, "RainbowEffects");

		private static readonly string Config = Path.Combine(ConfigDir, "config.cfg");

		private Effect? _mainEffect;

		private Effect? _particles;

		private Effect? _boulderBall;

		private void Init(string sceneName)
		{
			Actions.onMapInitialized -= Init;
			InitGuardStone();
			InitBoulderBall();
		}

		private void InitGuardStone()
		{
			PooledMonoBehaviour pooledObject = Singleton<PoolManager>.Instance.GetPooledObject("Guardstone_VFX");
			if ((Object)(object)pooledObject == (Object)null)
			{
				((MelonBase)this).LoggerInstance.Error("Could not get Guardstone_VFX");
				return;
			}
			Il2CppReferenceArray<Material> sharedMaterials = ((Renderer)((Component)pooledObject).GetComponent<VFXRenderer>()).sharedMaterials;
			if (((Il2CppArrayBase<Material>)(object)sharedMaterials).Length != 2)
			{
				((MelonBase)this).LoggerInstance.Error($"Guardstone's sharedMaterials is malformed (size: {((Il2CppArrayBase<Material>)(object)sharedMaterials).Length})");
				return;
			}
			AssetBundle obj = AssetBundles.LoadAssetBundleFromStream((MelonMod)(object)this, "RainbowEffects.rainbowGuard");
			Shader val = obj.LoadAsset<Shader>("guard.shader");
			Shader val2 = obj.LoadAsset<Shader>("guard2.shader");
			obj.Unload(false);
			((Object)val).hideFlags = (HideFlags)61;
			((Object)val2).hideFlags = (HideFlags)61;
			_mainEffect.Resource = new RainbowEffectsResource(((Il2CppArrayBase<Material>)(object)sharedMaterials)[0], val);
			_particles.Resource = new RainbowEffectsResource(((Il2CppArrayBase<Material>)(object)sharedMaterials)[1], val2);
			if (_mainEffect.Enabled.Value)
			{
				_mainEffect.Resource.SetRainbow();
			}
			if (_particles.Enabled.Value)
			{
				_particles.Resource.SetRainbow();
			}
		}

		private void InitBoulderBall()
		{
			PooledMonoBehaviour pooledObject = Singleton<PoolManager>.Instance.GetPooledObject("PlayerBoxInteractionVFX");
			if ((Object)(object)pooledObject == (Object)null)
			{
				((MelonBase)this).LoggerInstance.Error("Could not get PlayerBoxInteractionVFX");
				return;
			}
			Shader val = AssetBundles.LoadAssetFromStream<Shader>((MelonMod)(object)this, "RainbowEffects.boulderBall", "boulderball.shader");
			((Object)val).hideFlags = (HideFlags)61;
			_boulderBall.Resource = new RainbowEffectsResource(((Renderer)((Component)pooledObject).GetComponent<VFXRenderer>()).sharedMaterial, val);
			if (_boulderBall.Enabled.Value)
			{
				_boulderBall.Resource.SetRainbow();
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveOptimization)]
		public override void OnUpdate()
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			if (_mainEffect.Enabled.Value && _mainEffect.Mode.Value == ColorMode.Rainbow)
			{
				float num = Time.time * _mainEffect.Speed.Value + _mainEffect.Offset.Value;
				_mainEffect.SetVector(new Vector4(Mathf.Sin(num) * 0.5f + 0.5f, Mathf.Sin(num + (float)Math.PI * 2f / 3f) * 0.5f + 0.5f, Mathf.Sin(num + 4.1887903f) * 0.5f + 0.5f, 0f));
			}
			if (_particles.Enabled.Value && _particles.Mode.Value == ColorMode.Rainbow)
			{
				float num2 = Time.time * _particles.Speed.Value + _particles.Offset.Value;
				_particles.SetVector(new Vector4(Mathf.Sin(num2) * 0.5f + 0.5f, Mathf.Sin(num2 + (float)Math.PI * 2f / 3f) * 0.5f + 0.5f, Mathf.Sin(num2 + 4.1887903f) * 0.5f + 0.5f, 0f));
			}
			if (_boulderBall.Enabled.Value && _boulderBall.Mode.Value == ColorMode.Rainbow)
			{
				float num3 = Time.time * _boulderBall.Speed.Value + _boulderBall.Offset.Value;
				_boulderBall.SetVector(new Vector4(Mathf.Sin(num3) * 0.5f + 0.5f, Mathf.Sin(num3 + (float)Math.PI * 2f / 3f) * 0.5f + 0.5f, Mathf.Sin(num3 + 4.1887903f) * 0.5f + 0.5f, 1f));
			}
		}

		public override void OnInitializeMelon()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			if (!Directory.Exists(ConfigDir))
			{
				Directory.CreateDirectory(ConfigDir);
			}
			_mainEffect = new Effect("Guard Effect", "rainbowGuard", new Vector3(1f, 0.20507877f, 0f));
			_particles = new Effect("Guard Particles", "rainbowGuard2", new Vector3(1f, 0.20507877f, 0f));
			_boulderBall = new Effect("Fist Bump", "RainbowEffectsBoulderBall", new Vector3(1f, 0.83077f, 0.212231f));
			MelonPreferences_Entry<ColorMode> mode = _boulderBall.Mode;
			((MelonPreferences_Entry)mode).Description = ((MelonPreferences_Entry)mode).Description + "\n(These settings also apply to the scoring effect for the hoop minigame)";
			UI.RegisterMelon((MelonBase)(object)this, (MelonPreferences_Category[])(object)new MelonPreferences_Category[3] { _mainEffect.Category, _particles.Category, _boulderBall.Category });
		}

		public override void OnLateInitializeMelon()
		{
			Actions.onMapInitialized += Init;
		}

		internal static MelonPreferences_Category CreateCategory(string categoryID, string categoryName)
		{
			MelonPreferences_Category obj = MelonPreferences.CreateCategory("RainbowEffects_" + categoryID, categoryName);
			obj.SetFilePath(Config);
			return obj;
		}

		internal static MelonPreferences_Entry<T> CreateEntry<T>(MelonPreferences_Category category, string entryID, T defaultValue, string entryName, string? description = null, ValueValidator? validator = null)
		{
			return category.CreateEntry<T>(category.Identifier + "_" + entryID, defaultValue, entryName, description, false, false, validator, (string)null);
		}
	}
	internal enum ColorMode
	{
		Rainbow,
		Static
	}
	internal class Effect
	{
		private readonly int _shaderID;

		internal readonly MelonPreferences_Category Category;

		internal readonly MelonPreferences_Entry<bool> Enabled;

		internal readonly MelonPreferences_Entry<float> Speed;

		internal readonly MelonPreferences_Entry<float> Offset;

		internal readonly MelonPreferences_Entry<Vector3> Color;

		internal readonly MelonPreferences_Entry<ColorMode> Mode;

		internal RainbowEffectsResource? Resource;

		internal Effect(string name, string property, Vector3 defaultColor)
		{
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Expected O, but got Unknown
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			_shaderID = Shader.PropertyToID(property);
			string text = name.ToLower();
			Category = RainbowEffects.CreateCategory(name.Replace(" ", null), name);
			Enabled = RainbowEffects.CreateEntry(Category, "Enabled", defaultValue: true, "Enabled", "Should Rainbow Effects edit this effect?");
			((MelonEventBase<LemonAction<bool, bool>>)(object)Enabled.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)delegate(bool _, bool newValue)
			{
				if (!(Resource == null))
				{
					if (newValue)
					{
						Resource.SetRainbow();
					}
					else
					{
						Resource.SetOriginal();
					}
				}
			}, 0, false);
			Speed = RainbowEffects.CreateEntry(Category, "Speed", 1f, "Speed", "Speed of the rainbow");
			Offset = RainbowEffects.CreateEntry(Category, "Offset", 0f, "Offset", "Offset of the rainbow");
			Color = RainbowEffects.CreateEntry<Vector3>(Category, "Color", defaultColor, "Color", "The color of the " + text, (ValueValidator?)(object)new VectorRange(0f, 1f));
			((MelonEventBase<LemonAction<Vector3, Vector3>>)(object)Color.OnEntryValueChanged).Subscribe((LemonAction<Vector3, Vector3>)delegate(Vector3 _, Vector3 newColor)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				SetVector(Vector4.op_Implicit(newColor));
			}, 0, false);
			Mode = RainbowEffects.CreateEntry(Category, "Mode", ColorMode.Rainbow, "Mode", "The color mode of the " + text, (ValueValidator?)new UserEditNotifier
			{
				OnUserEdit = ModeToggled
			});
			((MelonEventBase<LemonAction<ColorMode, ColorMode>>)(object)Mode.OnEntryValueChanged).Subscribe((LemonAction<ColorMode, ColorMode>)delegate(ColorMode _, ColorMode newMode)
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				if (newMode == ColorMode.Static)
				{
					SetVector(Vector4.op_Implicit(Color.Value));
				}
			}, 0, false);
			ModeToggled(Mode.Value);
			if (Mode.Value == ColorMode.Static)
			{
				SetVector(Vector4.op_Implicit(Color.Value));
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal void SetVector(Vector4 v)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			Shader.SetGlobalVector(_shaderID, v);
		}

		private void ModeToggled(object newValue)
		{
			if (newValue is ColorMode colorMode)
			{
				switch (colorMode)
				{
				case ColorMode.Rainbow:
					((MelonPreferences_Entry)Speed).IsHidden = false;
					((MelonPreferences_Entry)Offset).IsHidden = false;
					((MelonPreferences_Entry)Color).IsHidden = true;
					return;
				case ColorMode.Static:
					((MelonPreferences_Entry)Speed).IsHidden = true;
					((MelonPreferences_Entry)Offset).IsHidden = true;
					((MelonPreferences_Entry)Color).IsHidden = false;
					return;
				}
			}
			throw new ArgumentOutOfRangeException("newValue", newValue, "Value not present in enum ColorMode");
		}
	}
	internal class VectorRange : ValueValidator
	{
		private readonly float _minValue;

		private readonly float _maxValue;

		public VectorRange(float minValue, float maxValue)
		{
			if (maxValue < minValue)
			{
				throw new ArgumentException($"Min value ({minValue}) must be less than or equal to max value ({maxValue})!");
			}
			_minValue = minValue;
			_maxValue = maxValue;
		}

		public override bool IsValid(object value)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			if (!(value is Vector4 val))
			{
				if (!(value is Vector3 val2))
				{
					if (value is Vector2 val3)
					{
						return IsValid(val3.x) && IsValid(val3.y);
					}
					throw new ArgumentException($"Unsupported type: {value.GetType()}");
				}
				return IsValid(val2.x) && IsValid(val2.y) && IsValid(val2.z);
			}
			return IsValid(val.x) && IsValid(val.y) && IsValid(val.z) && IsValid(val.w);
		}

		private bool IsValid(float value)
		{
			if (value >= _minValue)
			{
				return value <= _maxValue;
			}
			return false;
		}

		private float EnsureValid(float value)
		{
			if (!(value < _minValue))
			{
				if (!(value > _maxValue))
				{
					return value;
				}
				return _maxValue;
			}
			return _minValue;
		}

		public override object EnsureValid(object value)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			if (!(value is Vector4 val))
			{
				if (!(value is Vector3 val2))
				{
					if (value is Vector2 val3)
					{
						val3.x = EnsureValid(val3.x);
						val3.y = EnsureValid(val3.y);
						return val3;
					}
					throw new ArgumentException($"Unsupported type: {value.GetType()}");
				}
				val2.x = EnsureValid(val2.x);
				val2.y = EnsureValid(val2.y);
				val2.z = EnsureValid(val2.z);
				return val2;
			}
			val.x = EnsureValid(val.x);
			val.y = EnsureValid(val.y);
			val.z = EnsureValid(val.z);
			val.w = EnsureValid(val.w);
			return val;
		}
	}
}