Decompiled source of QuotaQueen v0.2.1

plugins/dev.mamallama.quotaqueen.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using QuotaQueen.Configuration;
using QuotaQueen.Patches;
using QuotaQueen.QuotaStrategies;
using UnityEngine.SceneManagement;
using YAPYAP;

[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("dev.mamallama.quotaqueen")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.1.0")]
[assembly: AssemblyInformationalVersion("0.2.1+147a4579e4dbc890f2766d60c930ed940709dd6b")]
[assembly: AssemblyProduct("dev.mamallama.quotaqueen")]
[assembly: AssemblyTitle("QuotaQueen")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.1.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 QuotaQueen
{
	[BepInPlugin("dev.mamallama.quotaqueen", "QuotaQueen", "0.2.1")]
	public class QuotaQueenPlugin : BaseUnityPlugin
	{
		private bool MainMenuSeen;

		public const string Id = "dev.mamallama.quotaqueen";

		internal static ManualLogSource Log { get; private set; }

		internal static QuotaQueenConfig QueenConfig { get; private set; }

		public static string Name => "QuotaQueen";

		public static string Version => "0.2.1";

		private void Awake()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"Quota Queen startup");
			SceneManager.sceneLoaded += OnSceneChange;
			Harmony val = new Harmony("dev.mamallama.quotaqueen");
			val.PatchAll(typeof(GameManagerPatches));
			Log.LogMessage((object)$"Applied {val.GetPatchedMethods().Count()} patches");
			QuotaStrategyManager.RegisterStrategy("QuotaQueen", "VeryEasy", new QuotaStrategy(QuotaStrategyEasy.GetEasyQuota));
			QuotaStrategyManager.RegisterStrategy("QuotaQueen", "ConfigurableQuota", new QuotaStrategy(QuotaStrategyConfigurable.GetQuota));
			QuotaStrategyConfigurable.EarlyBind();
		}

		private void OnSceneChange(Scene arg0, LoadSceneMode arg1)
		{
			if (!MainMenuSeen && ((Scene)(ref arg0)).name.Equals("menu", StringComparison.OrdinalIgnoreCase))
			{
				FreshenConfig();
				MainMenuSeen = true;
			}
		}

		internal void FreshenConfig()
		{
			if (QueenConfig == null)
			{
				try
				{
					QueenConfig = QuotaQueenConfig.BindConfig(((BaseUnityPlugin)this).Info.Metadata);
					Log.LogMessage((object)$"QuotaQueen Configuration loaded\n\n{QueenConfig}");
				}
				catch (Exception ex)
				{
					Log.LogError((object)("Failed to bind config file!\n\n" + ex.StackTrace + "\n\n" + ex.Message));
				}
			}
		}
	}
}
namespace QuotaQueen.QuotaStrategies
{
	public readonly struct GameSnapshot
	{
		public readonly bool QuotaJustEnded;

		public readonly bool RequestedSpecificQuota;

		public readonly int RequestedQuotaNo;

		public readonly int QuotasCompleted;

		public readonly int PlayersInSession;

		public readonly int CurrentQuotaGoal;

		public readonly float QuotaMultiplier;

		public int EffectiveQuotaCount
		{
			get
			{
				if (RequestedSpecificQuota)
				{
					return RequestedQuotaNo;
				}
				if (!QuotaJustEnded)
				{
					return QuotasCompleted;
				}
				return QuotasCompleted + 1;
			}
		}

		public GameSnapshot(GameManager instance, bool quotaEnded = false, bool specific = false, int which = 0)
		{
			QuotaJustEnded = quotaEnded;
			RequestedSpecificQuota = specific;
			RequestedQuotaNo = which;
			QuotasCompleted = instance.quotaSessionsCompleted;
			PlayersInSession = instance.playersByActorId.Keys.Count;
			CurrentQuotaGoal = instance.currentQuotaScoreGoal;
			QuotaMultiplier = instance.sessionQuotaMultiplier;
		}

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder("GameState:\n");
			stringBuilder.AppendLine($"  Just Ended:         {QuotaJustEnded}");
			stringBuilder.AppendLine($"  Completed:          {QuotasCompleted}");
			stringBuilder.AppendLine($"  Players:            {PlayersInSession}");
			stringBuilder.AppendLine($"  Current Goal:       {CurrentQuotaGoal}");
			stringBuilder.AppendLine($"  Multiplier:         {QuotaMultiplier}");
			stringBuilder.AppendLine($"  Effective Quotas:   {EffectiveQuotaCount}");
			return stringBuilder.ToString();
		}
	}
	public class QuotaStrategy
	{
		public readonly UpdateQuotaDelegate ExecuteStrategy;

		public QuotaStrategy(UpdateQuotaDelegate strategy)
		{
			ExecuteStrategy = strategy;
			base..ctor();
		}
	}
	internal static class QuotaStrategyConfigurable
	{
		private static readonly ConfigEntry<int> BaseQuota;

		private static readonly ConfigEntry<int> QuotaGrowth;

		static QuotaStrategyConfigurable()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			ConfigFile val = new ConfigFile(Path.Combine(Paths.ConfigPath, "QuotaQueen.ConfigurableQuota.cfg"), true);
			BaseQuota = val.Bind<int>("ConfigurableQuota", "BaseQuota", 900, "The base quota amount at the start of the game");
			QuotaGrowth = val.Bind<int>("ConfigurableQuota", "QuotaGrowth", 900, "The amount the quota increases each time a new quota is created");
		}

		internal static void EarlyBind()
		{
			QuotaQueenPlugin.Log.LogMessage((object)"Binding config for QuotaStrategyConfigurable");
		}

		internal static int GetQuota(GameSnapshot gameState)
		{
			return BaseQuota.Value + QuotaGrowth.Value * gameState.EffectiveQuotaCount;
		}
	}
	internal static class QuotaStrategyEasy
	{
		internal static int GetEasyQuota(GameSnapshot gameState)
		{
			return 300 + 300 * gameState.EffectiveQuotaCount;
		}
	}
	public static class QuotaStrategyManager
	{
		public const string DefaultStrategyGUID = "YAPYAP.Default";

		private static readonly Dictionary<string, QuotaStrategy> _quotaStrategies = new Dictionary<string, QuotaStrategy>();

		private static bool Locked = false;

		public static string[] StrategyKeys
		{
			get
			{
				string text = "YAPYAP.Default";
				Dictionary<string, QuotaStrategy>.KeyCollection keys = _quotaStrategies.Keys;
				int num = 0;
				string[] array = new string[1 + keys.Count];
				array[num] = text;
				num++;
				foreach (string item in keys)
				{
					array[num] = item;
					num++;
				}
				return array;
			}
		}

		internal static void Lock()
		{
			Locked = true;
		}

		public static void RegisterStrategy(string ownerGUID, string strategyName, QuotaStrategy strategy)
		{
			string text = ownerGUID + "." + strategyName;
			if (Locked)
			{
				QuotaQueenPlugin.Log.LogWarning((object)("Discarding strategy " + text + ", registration is too late. Registration must occur before a game is loaded"));
				return;
			}
			if (_quotaStrategies.ContainsKey(text))
			{
				QuotaQueenPlugin.Log.LogWarning((object)(text + " already exists in strategy dictionary, overwriting"));
			}
			_quotaStrategies[text] = strategy;
		}

		internal static bool TryExecuteStrategy(string which, GameSnapshot context, out int nextQuota)
		{
			nextQuota = 0;
			if (!_quotaStrategies.TryGetValue(which, out QuotaStrategy value))
			{
				return false;
			}
			nextQuota = value.ExecuteStrategy(context);
			return true;
		}
	}
	public delegate int UpdateQuotaDelegate(GameSnapshot gameState);
}
namespace QuotaQueen.Patches
{
	internal static class GameManagerPatches
	{
		[HarmonyPatch(typeof(GameManager), "OnStartServer")]
		[HarmonyPostfix]
		private static void GameStartPatch(GameManager __instance)
		{
			if (((NetworkBehaviour)__instance).isServer)
			{
				QuotaQueenConfig queenConfig = QuotaQueenPlugin.QueenConfig;
				QuotaQueenPlugin.Log.LogInfo((object)"Configuring this round's details for the host");
				__instance.baseRoundDuration = queenConfig.RoundDuration.Value;
				__instance.roundsToQuota = queenConfig.QuotaDays.Value;
				__instance.baseGoldReward = queenConfig.GoldReward.Value;
				__instance.deathPenaltyPercentageBased = queenConfig.UsePCTPenalty.Value;
				__instance.deathPenaltyFlat = queenConfig.DeathPenaltyFlat.Value;
				__instance.deathPenaltyPercent = queenConfig.DeathPenaltyPCT.Value;
				RunInitialQuotaCalc(__instance);
			}
			else
			{
				QuotaQueenPlugin.Log.LogWarning((object)"OnStartServer as client, shutting down for this round");
			}
		}

		[HarmonyPatch(typeof(GameManager), "GetNextQuotaScoreGoal")]
		[HarmonyPostfix]
		private static void GetNextQuotaScoreGoalPatch(GameManager __instance, ref int __result)
		{
			string value = QuotaQueenPlugin.QueenConfig.QuotaStrategy.Value;
			QuotaQueenPlugin.Log.LogMessage((object)("Using " + value + " for this round's quota calculation"));
			if (!(value == "YAPYAP.Default"))
			{
				if (QuotaStrategyManager.TryExecuteStrategy(value, new GameSnapshot(__instance, quotaEnded: true), out var nextQuota))
				{
					__result = nextQuota;
				}
				else
				{
					QuotaQueenPlugin.Log.LogError((object)"Failed to execute strategy, using default instead");
				}
			}
		}

		[HarmonyPatch(typeof(GameManager), "GetQuotaForSession")]
		[HarmonyPostfix]
		private static void GetQuotaForSessionPatch(GameManager __instance, int sessionIndex, ref int __result)
		{
			string value = QuotaQueenPlugin.QueenConfig.QuotaStrategy.Value;
			QuotaQueenPlugin.Log.LogMessage((object)("Using " + value + " for session quota"));
			if (!(value == "YAPYAP.Default"))
			{
				if (QuotaStrategyManager.TryExecuteStrategy(value, new GameSnapshot(__instance, quotaEnded: false, specific: true, sessionIndex), out var nextQuota))
				{
					__result = nextQuota;
				}
				else
				{
					QuotaQueenPlugin.Log.LogError((object)"Failed to execute strategy, using default instead");
				}
			}
		}

		private static void RunInitialQuotaCalc(GameManager __instance)
		{
			string value = QuotaQueenPlugin.QueenConfig.QuotaStrategy.Value;
			QuotaQueenPlugin.Log.LogMessage((object)("Using " + value + " for initial/restore quota"));
			if (!(value == "YAPYAP.Default"))
			{
				if (QuotaStrategyManager.TryExecuteStrategy(value, new GameSnapshot(__instance), out var nextQuota))
				{
					__instance.NetworkcurrentQuotaScoreGoal = nextQuota;
				}
				else
				{
					QuotaQueenPlugin.Log.LogError((object)"Failed to execute strategy, using default instead");
				}
			}
		}
	}
}
namespace QuotaQueen.Configuration
{
	internal class QuotaQueenConfig
	{
		internal ConfigFile Cfg;

		internal ConfigEntry<int> RoundDuration;

		internal ConfigEntry<int> QuotaDays;

		internal ConfigEntry<int> GoldReward;

		internal ConfigEntry<string> QuotaStrategy;

		internal ConfigEntry<bool> UsePCTPenalty;

		internal ConfigEntry<int> DeathPenaltyFlat;

		internal ConfigEntry<float> DeathPenaltyPCT;

		internal QuotaQueenConfig(ConfigFile cfg)
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			Cfg = cfg;
			RoundDuration = cfg.Bind<int>("Round Settings", "RoundDuration", 720, "The length of each day in seconds");
			QuotaDays = cfg.Bind<int>("Quota Settings", "QuotaDays", 3, "The number of days per quota");
			GoldReward = cfg.Bind<int>("Quota Settings", "GoldReward", 25, "How much gold is given for completing a quota.\nNote: More gold is rewarded for exceeding the quota, this is the minimum for meeting any quota");
			QuotaStrategy = cfg.Bind<string>("Quota Settings", "QuotaStrategy", "YAPYAP.Default", new ConfigDescription("This controls the way the game generates each new quota", (AcceptableValueBase)(object)new AcceptableValueList<string>(QuotaStrategyManager.StrategyKeys), Array.Empty<object>()));
			QuotaStrategyManager.Lock();
			UsePCTPenalty = cfg.Bind<bool>("Death Settings", "UsePCTPenalty", true, "If this flag is disabled then the flat death penalty will be subbed in for the default percentage based penalty");
			DeathPenaltyFlat = cfg.Bind<int>("Death Settings", "DeathPenaltyFlat", 100, "If the death penalty is set to flat mode this much score will be removed per dead player at the end of the round");
			DeathPenaltyPCT = cfg.Bind<float>("Death Settings", "DeathPenaltyPCT", 0.1f, "If the death penalty is set to flat mode this percentage of the total score will be removed per dead player");
		}

		internal static QuotaQueenConfig BindConfig(BepInPlugin owner)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			ConfigFile cfg = new ConfigFile(Path.Combine(Paths.ConfigPath, "QuotaQueen.cfg"), true, owner);
			return new QuotaQueenConfig(cfg);
		}

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("Quota Queen Config:");
			stringBuilder.AppendLine("--Round Configs--");
			stringBuilder.AppendLine($"  Round Duration:    {RoundDuration.Value}");
			stringBuilder.AppendLine("--Quota Configs--");
			stringBuilder.AppendLine($"  Quota Days:        {QuotaDays.Value}");
			stringBuilder.AppendLine($"  Quota Reward:      {GoldReward.Value}");
			stringBuilder.AppendLine("  Quota Strategy:    " + QuotaStrategy.Value);
			stringBuilder.AppendLine("--Death Configs--");
			stringBuilder.AppendLine($"  Using PCT Penalty: {UsePCTPenalty.Value}");
			stringBuilder.AppendLine($"  Percent Penalty:   {DeathPenaltyPCT.Value:P1}");
			stringBuilder.AppendLine($"  Flat Penalty:      {DeathPenaltyFlat.Value}");
			return stringBuilder.ToString();
		}
	}
}
namespace System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ConstantExpectedAttribute : Attribute
	{
		public object? Min { get; set; }

		public object? Max { get; set; }
	}
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ExperimentalAttribute : Attribute
	{
		public string DiagnosticId { get; }

		public string? UrlFormat { get; set; }

		public ExperimentalAttribute(string diagnosticId)
		{
			DiagnosticId = diagnosticId;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	internal sealed class MemberNotNullAttribute : Attribute
	{
		public string[] Members { get; }

		public MemberNotNullAttribute(string member)
		{
			Members = new string[1] { member };
		}

		public MemberNotNullAttribute(params string[] members)
		{
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	internal sealed class MemberNotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public string[] Members { get; }

		public MemberNotNullWhenAttribute(bool returnValue, string member)
		{
			ReturnValue = returnValue;
			Members = new string[1] { member };
		}

		public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
		{
			ReturnValue = returnValue;
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SetsRequiredMembersAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class StringSyntaxAttribute : Attribute
	{
		public const string CompositeFormat = "CompositeFormat";

		public const string DateOnlyFormat = "DateOnlyFormat";

		public const string DateTimeFormat = "DateTimeFormat";

		public const string EnumFormat = "EnumFormat";

		public const string GuidFormat = "GuidFormat";

		public const string Json = "Json";

		public const string NumericFormat = "NumericFormat";

		public const string Regex = "Regex";

		public const string TimeOnlyFormat = "TimeOnlyFormat";

		public const string TimeSpanFormat = "TimeSpanFormat";

		public const string Uri = "Uri";

		public const string Xml = "Xml";

		public string Syntax { get; }

		public object?[] Arguments { get; }

		public StringSyntaxAttribute(string syntax)
		{
			Syntax = syntax;
			Arguments = new object[0];
		}

		public StringSyntaxAttribute(string syntax, params object?[] arguments)
		{
			Syntax = syntax;
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class UnscopedRefAttribute : Attribute
	{
	}
}
namespace System.Runtime.Versioning
{
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresPreviewFeaturesAttribute : Attribute
	{
		public string? Message { get; }

		public string? Url { get; set; }

		public RequiresPreviewFeaturesAttribute()
		{
		}

		public RequiresPreviewFeaturesAttribute(string? message)
		{
			Message = message;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CallerArgumentExpressionAttribute : Attribute
	{
		public string ParameterName { get; }

		public CallerArgumentExpressionAttribute(string parameterName)
		{
			ParameterName = parameterName;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CollectionBuilderAttribute : Attribute
	{
		public Type BuilderType { get; }

		public string MethodName { get; }

		public CollectionBuilderAttribute(Type builderType, string methodName)
		{
			BuilderType = builderType;
			MethodName = methodName;
		}
	}
	[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CompilerFeatureRequiredAttribute : Attribute
	{
		public const string RefStructs = "RefStructs";

		public const string RequiredMembers = "RequiredMembers";

		public string FeatureName { get; }

		public bool IsOptional { get; set; }

		public CompilerFeatureRequiredAttribute(string featureName)
		{
			FeatureName = featureName;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute
	{
		public string[] Arguments { get; }

		public InterpolatedStringHandlerArgumentAttribute(string argument)
		{
			Arguments = new string[1] { argument };
		}

		public InterpolatedStringHandlerArgumentAttribute(params string[] arguments)
		{
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerAttribute : Attribute
	{
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal static class IsExternalInit
	{
	}
	[AttributeUsage(AttributeTargets.Method, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ModuleInitializerAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class OverloadResolutionPriorityAttribute : Attribute
	{
		public int Priority { get; }

		public OverloadResolutionPriorityAttribute(int priority)
		{
			Priority = priority;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ParamCollectionAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiredMemberAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresLocationAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SkipLocalsInitAttribute : Attribute
	{
	}
}