using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using ModVerifier.Common;
using ModVerifier.Configuration;
using Mono.Cecil;
using Newtonsoft.Json;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.github.Kirshoo.ModVerifier")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("com.github.Kirshoo.ModVerifier")]
[assembly: AssemblyTitle("ModVerifier")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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]
[Microsoft.CodeAnalysis.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;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace BepInEx
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class BepInAutoPluginAttribute : Attribute
{
public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
{
}
}
}
namespace BepInEx.Preloader.Core.Patching
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class PatcherAutoPluginAttribute : Attribute
{
public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
{
}
}
}
namespace ModVerifier
{
public interface IHashFunc
{
byte[] Hash(Stream input);
}
internal class ModScanner
{
private IHashFunc hash;
public ModScanner(IHashFunc hashfunc)
{
hash = hashfunc;
}
public ModMetadata GetMetadata(string filepath)
{
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_00dd: 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)
ModuleDefinition val = ModuleDefinition.ReadModule(filepath);
TypeDefinition val2 = ((IEnumerable<TypeDefinition>)val.Types).FirstOrDefault((Func<TypeDefinition, bool>)((TypeDefinition t) => ((IEnumerable<CustomAttribute>)t.CustomAttributes).Any((CustomAttribute a) => ((MemberReference)a.AttributeType).FullName == "BepInEx.BepInPlugin")));
if (val2 == null)
{
throw new ArgumentException("file is not a valid bepinex plugin file");
}
CustomAttribute val3 = ((IEnumerable<CustomAttribute>)val2.CustomAttributes).First((CustomAttribute a) => ((MemberReference)a.AttributeType).FullName == "BepInEx.BepInPlugin");
ModMetadata result = new ModMetadata();
CustomAttributeArgument val4 = val3.ConstructorArguments[0];
result.GUID = ((CustomAttributeArgument)(ref val4)).Value?.ToString() ?? string.Empty;
val4 = val3.ConstructorArguments[1];
result.Name = ((CustomAttributeArgument)(ref val4)).Value?.ToString() ?? string.Empty;
val4 = val3.ConstructorArguments[2];
result.Version = ((CustomAttributeArgument)(ref val4)).Value?.ToString() ?? string.Empty;
result.SHA256 = ComputeHash(filepath);
return result;
}
public bool TryGetMetadata(string filepath, out ModMetadata metadata)
{
metadata = new ModMetadata();
try
{
metadata = GetMetadata(filepath);
return true;
}
catch (ArgumentException)
{
return false;
}
}
private string ComputeHash(string filepath)
{
using FileStream input = File.OpenRead(filepath);
byte[] array = hash.Hash(input);
return BitConverter.ToString(array).Replace("-", "").ToUpperInvariant();
}
}
public enum SourceType
{
Web,
LocalFile
}
[BepInPlugin("com.github.Kirshoo.ModVerifier", "ModVerifier", "1.1.0")]
public class Plugin : BaseUnityPlugin
{
public class WhitelistEntry
{
public string guid = string.Empty;
public string name = string.Empty;
public string version = string.Empty;
public string sha256 = string.Empty;
}
private const string WhitelistURL = "https://4ufps.github.io/peakverify.json";
private static readonly string LogPath = Path.Combine(Paths.BepInExRootPath, "verifier_result.log");
private static readonly StringBuilder LogBuffer = new StringBuilder();
private static int Unauthorized = 0;
private GameObject manager_go;
private VerifierReportManager ReportManager;
private ModScanner scanner = new ModScanner(new ShaHasher());
public const string Id = "com.github.Kirshoo.ModVerifier";
internal static ManualLogSource Logger { get; private set; } = null;
public static string Name => "ModVerifier";
public static string Version => "1.1.0";
private async void Awake()
{
Logger = ((BaseUnityPlugin)this).Logger;
BindConfig();
CreateManager();
Logger.LogInfo((object)"Starting verification...");
try
{
bool flag = await VerifyRunningPlugins(SourceType.Web, "https://4ufps.github.io/peakverify.json");
Logger.LogInfo((object)string.Format("Verification finished with {0} at {1:O}", flag ? "success" : "fail", DateTime.UtcNow));
Logger.LogInfo((object)("Writing report into " + LogPath));
File.WriteAllText(LogPath, LogBuffer.ToString());
UpdateText(Unauthorized);
}
catch (Exception ex)
{
Logger.LogError((object)("Verification failed: " + ex.Message));
ReportManager.SetReportError(ex.Message);
}
Logger.LogInfo((object)(Name + " was successfully loaded"));
}
private void BindConfig()
{
VerifierReport.BindConfig(((BaseUnityPlugin)this).Config);
}
private void CreateManager()
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Expected O, but got Unknown
if (!((Object)(object)manager_go != (Object)null))
{
manager_go = new GameObject("VerifierReportManager");
ReportManager = manager_go.AddComponent<VerifierReportManager>();
ReportManager.loadedMods = GetLoadedMods();
ReportManager.timestamp = DateTime.UtcNow;
Object.DontDestroyOnLoad((Object)(object)manager_go);
}
}
private void UpdateText(int unauthorized)
{
ReportManager.SetReportText(unauthorized);
}
private async Task<bool> VerifyRunningPlugins(SourceType type, string source)
{
_ = Paths.PluginPath;
LogBuffer.AppendLine("=== Verification Report (" + Name + " v" + Version + ") ===");
LogBuffer.AppendLine($"Timestamp: {DateTime.UtcNow:O}");
LogBuffer.AppendLine($"Whitelist source: {source} of type {type}\n");
Logger.LogDebug((object)("Fetching whitelist from " + source));
WhitelistEntry[] source2;
try
{
source2 = await FetchWhitelist(type, source);
}
catch (JsonSerializationException val)
{
JsonSerializationException innerException = val;
throw new Exception("Serializing the whitelist: malformed whitelist", (Exception?)(object)innerException);
}
catch (HttpRequestException ex)
{
throw new Exception("Fetching the whitelist: " + ex.Message, ex);
}
foreach (ModMetadata metadata in ReportManager.loadedMods)
{
bool flag = source2.Any((WhitelistEntry wMod) => string.Equals(wMod.guid, metadata.GUID, StringComparison.OrdinalIgnoreCase) && string.Equals(wMod.version, metadata.Version, StringComparison.OrdinalIgnoreCase) && string.Equals(wMod.sha256, metadata.SHA256, StringComparison.OrdinalIgnoreCase));
LogBuffer.AppendLine(metadata.Name + " (" + metadata.GUID + ") v" + metadata.Version);
LogBuffer.AppendLine(" SHA256: " + metadata.SHA256);
LogBuffer.AppendLine(" Status: " + (flag ? "Allowed" : "Unauthorized!"));
if (!flag)
{
Unauthorized++;
Logger.LogWarning((object)("Unauthorized mod: " + metadata.Name + " (" + metadata.Version + ")"));
}
}
return Unauthorized == 0;
}
private async Task<WhitelistEntry[]> FetchWhitelist(SourceType type, string source)
{
return type switch
{
SourceType.Web => await FetchWhitelistAsync(source),
SourceType.LocalFile => await LoadWhitelistFileAsync(source),
_ => throw new InvalidDataException($"Unknown source type: {type}"),
};
}
private async Task<WhitelistEntry[]> FetchWhitelistAsync(string web_url)
{
using HttpClient client = new HttpClient();
return JsonConvert.DeserializeObject<WhitelistEntry[]>(await client.GetStringAsync(web_url));
}
private async Task<WhitelistEntry[]> LoadWhitelistFileAsync(string filepath)
{
return JsonConvert.DeserializeObject<WhitelistEntry[]>(await File.ReadAllTextAsync(filepath));
}
private List<ModMetadata> GetLoadedMods()
{
List<ModMetadata> list = new List<ModMetadata>();
string[] files = Directory.GetFiles(Paths.PluginPath, "*.dll", SearchOption.AllDirectories);
foreach (string text in files)
{
if (!scanner.TryGetMetadata(text, out var metadata))
{
Logger.LogWarning((object)("Unable to retrieve metadata from " + text));
}
else
{
list.Add(metadata);
}
}
return list;
}
}
public class ShaHasher : IHashFunc
{
private SHA256 hashfunc;
public ShaHasher()
{
hashfunc = SHA256.Create();
}
public byte[] Hash(Stream input)
{
return hashfunc.ComputeHash(input);
}
}
public class Utils
{
public struct FontLoader
{
[CompilerGenerated]
private sealed class <>c__DisplayClass3_0
{
public string fontname;
internal bool <LoadFontCoroutine>b__0(TMP_FontAsset asset)
{
return ((Object)asset).name == fontname;
}
}
[CompilerGenerated]
private sealed class <LoadFontCoroutine>d__3 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public string fontname;
public FontLoader <>4__this;
private <>c__DisplayClass3_0 <>8__1;
public Action<TMP_FontAsset> callback;
private int <retries>5__2;
private TMP_FontAsset <font>5__3;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <LoadFontCoroutine>d__3(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>8__1 = null;
<font>5__3 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_011e: Unknown result type (might be due to invalid IL or missing references)
//IL_0128: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>8__1 = new <>c__DisplayClass3_0();
<>8__1.fontname = fontname;
<retries>5__2 = <>4__this.MAX_LOAD_FONT_RETRIES;
<font>5__3 = null;
break;
case 1:
<>1__state = -1;
break;
}
if (<retries>5__2 > 0)
{
<font>5__3 = ((IEnumerable<TMP_FontAsset>)Resources.FindObjectsOfTypeAll<TMP_FontAsset>()).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset asset) => ((Object)asset).name == <>8__1.fontname));
if (!((Object)(object)<font>5__3 != (Object)null))
{
<retries>5__2--;
Plugin.Logger.LogDebug((object)$"Failed to load {<>8__1.fontname} font, retrying after {(float)(<>4__this.MAX_LOAD_FONT_RETRIES - <retries>5__2) * <>4__this.BACKOFF_DELAY_MILLISECONDS}s...");
<>2__current = (object)new WaitForSeconds((float)(<>4__this.MAX_LOAD_FONT_RETRIES - <retries>5__2) * <>4__this.BACKOFF_DELAY_MILLISECONDS);
<>1__state = 1;
return true;
}
Plugin.Logger.LogDebug((object)("Found " + <>8__1.fontname + "! Proceeding..."));
}
if ((Object)(object)<font>5__3 == (Object)null)
{
Plugin.Logger.LogWarning((object)("Failed to load " + <>8__1.fontname + " font, fallback to built in font..."));
<font>5__3 = Resources.GetBuiltinResource<TMP_FontAsset>("LiberationSans SDF");
}
callback?.Invoke(<font>5__3);
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
public int MAX_LOAD_FONT_RETRIES;
public float BACKOFF_DELAY_MILLISECONDS;
public FontLoader()
{
MAX_LOAD_FONT_RETRIES = 5;
BACKOFF_DELAY_MILLISECONDS = 0.05f;
}
[IteratorStateMachine(typeof(<LoadFontCoroutine>d__3))]
public IEnumerator LoadFontCoroutine(string fontname, Action<TMP_FontAsset> callback)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <LoadFontCoroutine>d__3(0)
{
<>4__this = this,
fontname = fontname,
callback = callback
};
}
}
}
internal class VerifierReportManager : MonoBehaviour
{
[CompilerGenerated]
private sealed class <Cycle>d__14 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public VerifierReportManager <>4__this;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <Cycle>d__14(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Expected O, but got Unknown
int num = <>1__state;
VerifierReportManager verifierReportManager = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
goto IL_002d;
case 1:
<>1__state = -1;
<>2__current = verifierReportManager.Fade(1f, 0f);
<>1__state = 2;
return true;
case 2:
{
<>1__state = -1;
ModMetadata modMetadata = verifierReportManager.loadedMods[verifierReportManager.modIndex];
((TMP_Text)verifierReportManager.modcycle_textblock).text = $"[{verifierReportManager.modIndex + 1}/{verifierReportManager.loadedMods.Count}] {modMetadata.Name} v{modMetadata.Version} ({modMetadata.SHA256.Substring(0, 8)}...)";
verifierReportManager.modIndex = (verifierReportManager.modIndex + 1) % verifierReportManager.loadedMods.Count;
<>2__current = verifierReportManager.Fade(0f, 1f);
<>1__state = 3;
return true;
}
case 3:
{
<>1__state = -1;
goto IL_002d;
}
IL_002d:
<>2__current = (object)new WaitForSecondsRealtime(2f);
<>1__state = 1;
return true;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[CompilerGenerated]
private sealed class <Fade>d__15 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public VerifierReportManager <>4__this;
public float from;
public float to;
private float <t>5__2;
private Color <c>5__3;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <Fade>d__15(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
int num = <>1__state;
VerifierReportManager verifierReportManager = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
<t>5__2 = 0f;
<c>5__3 = ((Graphic)verifierReportManager.modcycle_textblock).color;
break;
case 1:
<>1__state = -1;
break;
}
if (<t>5__2 < 0.3f)
{
<t>5__2 += Time.deltaTime;
float num2 = Mathf.Lerp(from, to, <t>5__2 / 0.3f);
((Graphic)verifierReportManager.modcycle_textblock).color = new Color(<c>5__3.r, <c>5__3.g, <c>5__3.b, num2);
<>2__current = null;
<>1__state = 1;
return true;
}
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private readonly TextMeshProUGUI report_textblock;
private readonly TextMeshProUGUI modcycle_textblock;
internal List<ModMetadata> loadedMods;
private int modIndex;
private const float FADE_DURATION = 0.3f;
private const float CYCLE_INTERVAL = 2f;
internal DateTime timestamp;
private static TMP_FontAsset? FONT_ASSET;
public Utils.FontLoader fontLoader = new Utils.FontLoader();
public VerifierReportManager()
{
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Expected O, but got Unknown
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Expected O, but got Unknown
//IL_0108: Unknown result type (might be due to invalid IL or missing references)
//IL_0117: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: Expected O, but got Unknown
//IL_0159: Unknown result type (might be due to invalid IL or missing references)
Canvas val = ((Component)this).gameObject.AddComponent<Canvas>();
val.renderMode = (RenderMode)0;
val.sortingOrder = 1000;
CanvasScaler val2 = ((Component)this).gameObject.AddComponent<CanvasScaler>();
val2.uiScaleMode = (ScaleMode)1;
val2.referenceResolution = new Vector2(1920f, 1080f);
GameObject val3 = new GameObject("VerifierPanel");
val3.transform.SetParent(((Component)this).gameObject.transform, false);
val3.AddComponent<RectTransform>();
PlaceInPosition(val3.GetComponent<RectTransform>(), VerifierReport.Position, new Vector2(VerifierReport.PaddingLeft, VerifierReport.PaddingBottom));
VerticalLayoutGroup val4 = val3.AddComponent<VerticalLayoutGroup>();
((HorizontalOrVerticalLayoutGroup)val4).spacing = 10f;
((LayoutGroup)val4).childAlignment = PositionToTextAnchor(VerifierReport.Position);
GameObject val5 = new GameObject("VerifierReport");
val5.transform.SetParent(val3.transform, false);
report_textblock = val5.AddComponent<TextMeshProUGUI>();
((TMP_Text)report_textblock).text = "Loading report...";
((TMP_Text)report_textblock).alignment = PositionToAlignment(VerifierReport.Position);
GameObject val6 = new GameObject("ModCycle");
val6.transform.SetParent(val3.transform, false);
modcycle_textblock = val6.AddComponent<TextMeshProUGUI>();
((TMP_Text)modcycle_textblock).text = "";
((TMP_Text)modcycle_textblock).alignment = PositionToAlignment(VerifierReport.Position);
loadedMods = new List<ModMetadata>();
timestamp = DateTime.UtcNow;
}
private void Start()
{
LoadFont();
((MonoBehaviour)this).StartCoroutine(Cycle());
}
private void LoadFont()
{
if ((Object)(object)FONT_ASSET != (Object)null)
{
SetFont(report_textblock, FONT_ASSET);
SetFont(modcycle_textblock, FONT_ASSET);
return;
}
((MonoBehaviour)this).StartCoroutine(fontLoader.LoadFontCoroutine("DarumaDropOne-Regular SDF", delegate(TMP_FontAsset font)
{
FONT_ASSET = font;
SetFont(report_textblock, FONT_ASSET);
SetFont(modcycle_textblock, FONT_ASSET);
}));
}
public void SetReportText(int unauthorized)
{
((TMP_Text)report_textblock).text = $"Verification Time: {timestamp}\r\nMods: {loadedMods.Count - unauthorized}/{loadedMods.Count} allowed";
}
public void SetReportError(string error)
{
((TMP_Text)report_textblock).text = "Error during verification:\r\n" + error;
}
[IteratorStateMachine(typeof(<Cycle>d__14))]
private IEnumerator Cycle()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <Cycle>d__14(0)
{
<>4__this = this
};
}
[IteratorStateMachine(typeof(<Fade>d__15))]
private IEnumerator Fade(float from, float to)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <Fade>d__15(0)
{
<>4__this = this,
from = from,
to = to
};
}
public static TextAnchor PositionToTextAnchor(ReportPosition position)
{
return (TextAnchor)(position switch
{
ReportPosition.Top => 1,
ReportPosition.Bottom => 7,
ReportPosition.Left => 3,
ReportPosition.TopLeft => 0,
ReportPosition.BottomLeft => 6,
ReportPosition.Right => 5,
ReportPosition.TopRight => 2,
ReportPosition.BottomRight => 8,
_ => 3,
});
}
public static TextAlignmentOptions PositionToAlignment(ReportPosition position)
{
switch (position)
{
case ReportPosition.Top:
case ReportPosition.Bottom:
return (TextAlignmentOptions)514;
case ReportPosition.Left:
case ReportPosition.TopLeft:
case ReportPosition.BottomLeft:
return (TextAlignmentOptions)513;
case ReportPosition.Right:
case ReportPosition.TopRight:
case ReportPosition.BottomRight:
return (TextAlignmentOptions)516;
default:
return (TextAlignmentOptions)513;
}
}
private static void SetFont(TextMeshProUGUI textMesh, TMP_FontAsset font)
{
//IL_0021: 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_003c: Unknown result type (might be due to invalid IL or missing references)
((TMP_Text)textMesh).font = font;
((TMP_Text)textMesh).fontSize = 20f;
((TMP_Text)textMesh).overflowMode = (TextOverflowModes)0;
((TMP_Text)textMesh).textWrappingMode = (TextWrappingModes)0;
((Graphic)textMesh).color = Color.white;
((TMP_Text)textMesh).outlineWidth = 0.075f;
((TMP_Text)textMesh).outlineColor = Color32.op_Implicit(Color.black);
}
private static void PlaceInPosition(RectTransform rect, ReportPosition pos, Vector2 padding)
{
//IL_00db: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
Vector2 val = default(Vector2);
switch (pos)
{
case ReportPosition.TopLeft:
((Vector2)(ref val))..ctor(0f, 1f);
break;
case ReportPosition.Top:
((Vector2)(ref val))..ctor(0.5f, 1f);
break;
case ReportPosition.TopRight:
((Vector2)(ref val))..ctor(1f, 1f);
break;
case ReportPosition.Left:
((Vector2)(ref val))..ctor(0f, 0.5f);
break;
case ReportPosition.Right:
((Vector2)(ref val))..ctor(1f, 0.5f);
break;
case ReportPosition.BottomLeft:
((Vector2)(ref val))..ctor(0f, 0f);
break;
case ReportPosition.Bottom:
((Vector2)(ref val))..ctor(0.5f, 0f);
break;
case ReportPosition.BottomRight:
((Vector2)(ref val))..ctor(1f, 0f);
break;
default:
((Vector2)(ref val))..ctor(0f, 1f);
break;
}
rect.anchorMin = val;
rect.anchorMax = val;
rect.pivot = val;
rect.anchoredPosition = padding;
}
}
}
namespace ModVerifier.Configuration
{
internal static class VerifierReport
{
private static ConfigEntry<ReportPosition>? _reportPos;
private static ConfigEntry<float>? _reportPaddingLeft;
private static ConfigEntry<float>? _reportPaddingBottom;
public static ReportPosition Position
{
get
{
if (_reportPos == null)
{
Plugin.Logger.LogError((object)"Requested config entry, but no config file was bound.");
throw new InvalidOperationException("requesting config value before any config file was bound");
}
return _reportPos.Value;
}
}
public static float PaddingLeft
{
get
{
if (_reportPaddingLeft == null)
{
Plugin.Logger.LogError((object)"Requested config entry, but no config file was bound.");
throw new InvalidOperationException("requesting config value before any config file was bound");
}
return _reportPaddingLeft.Value;
}
}
public static float PaddingBottom
{
get
{
if (_reportPaddingBottom == null)
{
Plugin.Logger.LogError((object)"Requested config entry, but no config file was bound.");
throw new InvalidOperationException("requesting config value before any config file was bound");
}
return _reportPaddingBottom.Value;
}
}
public static void BindConfig(ConfigFile config)
{
_reportPos = config.Bind<ReportPosition>("VerifierReport", "ReportPosition", ReportPosition.Right, "The position of the mod verifier report.\r\nUse ReportPadding to make sure its not obstructed by other text.");
_reportPaddingLeft = config.Bind<float>("VerifierReport", "ReportMoveRight", -20f, "Moves report right from its position in pixels.\r\nSet to negative values to move left instead.");
_reportPaddingBottom = config.Bind<float>("VerifierReport", "ReportMoveUp", 0f, "Moves report upwards from its position in pixels.\r\nSet to negative values to move downwards instead.");
}
}
}
namespace ModVerifier.Common
{
public class ExceptionNotification : Exception
{
private readonly List<Exception> innerExceptions = new List<Exception>();
public override string Message => base.Message + string.Format(", {0} inner exceptions: {1}", innerExceptions.Count, string.Join(", ", innerExceptions));
public void AddException(Exception exception)
{
innerExceptions.Add(exception);
}
public bool HasErrors()
{
return innerExceptions.Count > 0;
}
}
internal struct ModMetadata
{
public string Name;
public string GUID;
public string Version;
public string SHA256;
public ModMetadata()
{
Name = string.Empty;
GUID = string.Empty;
Version = string.Empty;
SHA256 = string.Empty;
}
}
public enum ReportPosition
{
Top,
Bottom,
Left,
TopLeft,
BottomLeft,
Right,
TopRight,
BottomRight
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}