Decompiled source of Jinx It v1.0.0

JinxIt.dll

Decompiled 19 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("JinxIt")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("JinxIt")]
[assembly: AssemblyTitle("JinxIt")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace JinxIt;

[BepInPlugin("tchernobill.jinxit", "JinxIt", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
	public const string GUID = "tchernobill.jinxit";

	public const string NAME = "JinxIt";

	public const string VERSION = "1.0.0";

	internal static ManualLogSource Log;

	private void Awake()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		Log = ((BaseUnityPlugin)this).Logger;
		new Harmony("tchernobill.jinxit").PatchAll(typeof(JinxPatches));
		TestHarness.StartIfRequested(((Component)this).gameObject);
	}
}
[HarmonyPatch]
internal static class JinxPatches
{
	[HarmonyPrefix]
	[HarmonyPatch(typeof(AddStatusEffectRandom), "TryTriggerConditions")]
	private static void BeforeDraw(AddStatusEffectRandom __instance, Character ___m_affectedCharacter, out int __state)
	{
		__state = __instance.ForceID;
		if (__state < 0)
		{
			__instance.ForceID = PickMissing(__instance.Statuses, (___m_affectedCharacter != null) ? ___m_affectedCharacter.StatusEffectMngr : null);
		}
	}

	[HarmonyFinalizer]
	[HarmonyPatch(typeof(AddStatusEffectRandom), "TryTriggerConditions")]
	private static void AfterDraw(AddStatusEffectRandom __instance, int __state)
	{
		__instance.ForceID = __state;
	}

	internal static int PickMissing(StatusEffect[] statuses, StatusEffectManager target)
	{
		if (statuses == null || (Object)(object)target == (Object)null)
		{
			return -1;
		}
		List<int> list = new List<int>(statuses.Length);
		for (int i = 0; i < statuses.Length; i++)
		{
			if ((Object)(object)statuses[i] != (Object)null && (Object)(object)target.GetStatusEffectOfName(statuses[i].IdentifierName) == (Object)null)
			{
				list.Add(i);
			}
		}
		if (list.Count == 0 || list.Count == statuses.Length)
		{
			return -1;
		}
		return list[Random.Range(0, list.Count)];
	}
}
public class TestHarness : MonoBehaviour
{
	private const int Draws = 400;

	private static readonly MethodInfo s_tryTrigger = AccessTools.Method(typeof(AddStatusEffectRandom), "TryTriggerConditions", Type.EmptyTypes, (Type[])null);

	private static readonly FieldRef<Effect, Character> s_affected = AccessTools.FieldRefAccess<Effect, Character>("m_affectedCharacter");

	private static readonly FieldRef<AddStatusEffectRandom, int> s_id = AccessTools.FieldRefAccess<AddStatusEffectRandom, int>("m_id");

	public static void StartIfRequested(GameObject host)
	{
		if (UnityEngineExtensions.Contains<string>(Environment.GetCommandLineArgs(), "--jinx-test"))
		{
			host.AddComponent<TestHarness>();
		}
	}

	private void Start()
	{
		((MonoBehaviour)this).StartCoroutine(Run());
	}

	private static void Log(string message)
	{
		Plugin.Log.LogMessage((object)("jinx-test: " + message));
	}

	private static void Fail(string reason)
	{
		Plugin.Log.LogError((object)("jinx-test: FAILED " + reason));
	}

	private static IEnumerator WaitRealtime(float seconds)
	{
		float end = Time.realtimeSinceStartup + seconds;
		while (Time.realtimeSinceStartup < end)
		{
			yield return null;
		}
	}

	private static void SaveIcon(Sprite sprite)
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Expected O, but got Unknown
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)sprite == (Object)null)
		{
			Log("Jinx has no icon");
			return;
		}
		Texture2D texture = sprite.texture;
		RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2);
		Graphics.Blit((Texture)(object)texture, temporary);
		RenderTexture active = RenderTexture.active;
		RenderTexture.active = temporary;
		Rect textureRect = sprite.textureRect;
		Texture2D val = new Texture2D((int)((Rect)(ref textureRect)).width, (int)((Rect)(ref textureRect)).height, (TextureFormat)5, false);
		val.ReadPixels(textureRect, 0, 0);
		val.Apply();
		RenderTexture.active = active;
		RenderTexture.ReleaseTemporary(temporary);
		string text = Path.Combine(Paths.BepInExRootPath, "JinxItTest");
		Directory.CreateDirectory(text);
		string text2 = Path.Combine(text, "jinx_icon.png");
		File.WriteAllBytes(text2, ImageConversion.EncodeToPNG(val));
		Log($"icon {((Object)sprite).name} ({((Texture)texture).width}x{((Texture)texture).height}, rect {textureRect}) saved to {text2}");
	}

	private static string PathOf(Transform t)
	{
		if (!((Object)(object)t.parent == (Object)null))
		{
			return PathOf(t.parent) + "/" + ((Object)t).name;
		}
		return ((Object)t).name;
	}

	private IEnumerator Run()
	{
		Character character = null;
		float deadline = Time.realtimeSinceStartup + 900f;
		while ((Object)(object)character == (Object)null)
		{
			if (Time.realtimeSinceStartup > deadline)
			{
				Fail("no local character after 900 s");
				yield break;
			}
			yield return null;
			if (!((Object)(object)NetworkLevelLoader.Instance == (Object)null) && NetworkLevelLoader.Instance.IsOverallLoadingDone)
			{
				try
				{
					CharacterManager instance = CharacterManager.Instance;
					character = ((instance != null) ? instance.GetFirstLocalCharacter() : null);
				}
				catch (NullReferenceException)
				{
				}
			}
		}
		yield return WaitRealtime(3f);
		Log("local character " + character.Name);
		Item val = ((IEnumerable<Item>)((Dictionary<string, Item>)AccessTools.Field(typeof(ResourcesPrefabManager), "ITEM_PREFABS").GetValue(null)).Values).FirstOrDefault((Func<Item, bool>)((Item i) => (Object)(object)i != (Object)null && i.Name == "Jinx"));
		if ((Object)(object)val == (Object)null)
		{
			Fail("no item named Jinx");
			yield break;
		}
		Log($"Jinx = item {val.ItemID} ({((object)val).GetType().Name})");
		SaveIcon(val.ItemIcon);
		List<AddStatusEffectRandom> list = new List<AddStatusEffectRandom>();
		ShootProjectile[] componentsInChildren = ((Component)val).GetComponentsInChildren<ShootProjectile>(true);
		foreach (ShootProjectile val2 in componentsInChildren)
		{
			if ((Object)(object)val2.BaseProjectile != (Object)null)
			{
				list.AddRange(((Component)val2.BaseProjectile).GetComponentsInChildren<AddStatusEffectRandom>(true));
			}
		}
		AddStatusEffectRandom[] array = Resources.FindObjectsOfTypeAll<AddStatusEffectRandom>();
		foreach (AddStatusEffectRandom val3 in array)
		{
			object[] obj = new object[4]
			{
				PathOf(((Component)val3).transform),
				null,
				null,
				null
			};
			Scene scene = ((Component)val3).gameObject.scene;
			obj[1] = ((Scene)(ref scene)).name;
			obj[2] = val3.ForceID;
			obj[3] = ((AddStatusEffect)val3).BaseChancesToContract;
			Log(string.Format("in memory: {0} (scene '{1}'), ForceID {2}, chances {3}, ", obj) + "statuses " + string.Join(", ", val3.Statuses.Select((StatusEffect s) => (!((Object)(object)s == (Object)null)) ? (s.IdentifierName + " [" + s.EffectFamily?.Name + "]") : "null")));
		}
		if (list.Count == 0)
		{
			Fail("no AddStatusEffectRandom on Jinx's projectile");
			yield break;
		}
		AddStatusEffectRandom effect = list[0];
		StatusEffect[] hexes = effect.Statuses;
		StatusEffectManager statuses = character.StatusEffectMngr;
		string problem = null;
		StatusEffect[] array3;
		for (int k = 0; k <= hexes.Length; k++)
		{
			if (problem != null)
			{
				break;
			}
			bool[] array2 = ((k == 0 || k == hexes.Length) ? new bool[1] : new bool[2] { false, true });
			foreach (bool flag in array2)
			{
				HashSet<int> present = new HashSet<int>(Enumerable.Range(flag ? (hexes.Length - k) : 0, k));
				array3 = hexes;
				foreach (StatusEffect val4 in array3)
				{
					statuses.RemoveStatusWithIdentifierName(val4.IdentifierName);
				}
				foreach (int item in present)
				{
					statuses.AddStatusEffect(hexes[item], (Character)null);
				}
				yield return null;
				int[] landed = new int[hexes.Length];
				s_affected.Invoke((Effect)(object)effect) = character;
				for (int num3 = 0; num3 < 400; num3++)
				{
					s_tryTrigger.Invoke(effect, null);
					landed[s_id.Invoke(effect)]++;
				}
				string arg = string.Join(",", from h in hexes
					where (Object)(object)statuses.GetStatusEffectOfName(h.IdentifierName) != (Object)null
					select h.IdentifierName);
				Log($"{k} on target [{arg}]: " + string.Join(", ", hexes.Select((StatusEffect h, int i) => $"{h.IdentifierName} {landed[i]}")) + $", ForceID back to {effect.ForceID}");
				bool flag2 = k == 0 || k == hexes.Length;
				for (int num4 = 0; num4 < hexes.Length; num4++)
				{
					if (problem != null)
					{
						break;
					}
					bool flag3 = flag2 || !present.Contains(num4);
					if (flag3 && landed[num4] == 0)
					{
						problem = $"{hexes[num4].IdentifierName} never drawn with {k} hexes on the target";
					}
					else if (!flag3 && landed[num4] > 0)
					{
						problem = $"{hexes[num4].IdentifierName} drawn {landed[num4]} times while already on the target";
					}
				}
				if (problem == null && present.Count((int i) => (Object)(object)statuses.GetStatusEffectOfName(hexes[i].IdentifierName) == (Object)null) > 0)
				{
					problem = $"could not put {k} hexes on the target";
				}
				if (problem == null && effect.ForceID != -1)
				{
					problem = $"ForceID left at {effect.ForceID}";
				}
				if (problem != null)
				{
					break;
				}
			}
		}
		array3 = hexes;
		foreach (StatusEffect val5 in array3)
		{
			statuses.RemoveStatusWithIdentifierName(val5.IdentifierName);
		}
		if (problem != null)
		{
			Fail(problem);
		}
		else
		{
			Log("done");
		}
	}
}