Decompiled source of WizshBoneTwitchIntegration v1.0.1

plugins\WizshBoneTwitchIntegration.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Sockets;
using System.Net.WebSockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.GUI;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Splatform;
using TMPro;
using TwitchSDK;
using TwitchSDK.GameTaskMethodBuilders;
using TwitchSDK.Interop;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.UI;
using WizshBoneTwitchIntegration.Commands;
using WizshBoneTwitchIntegration.Components;
using WizshBoneTwitchIntegration.Configs;
using WizshBoneTwitchIntegration.Exceptions;
using WizshBoneTwitchIntegration.Extensions;
using WizshBoneTwitchIntegration.Gui;
using WizshBoneTwitchIntegration.Gui.Tabs;
using WizshBoneTwitchIntegration.GuiOld;
using WizshBoneTwitchIntegration.Helpers;
using WizshBoneTwitchIntegration.Models;
using WizshBoneTwitchIntegration.Models.Views;
using WizshBoneTwitchIntegration.TwitchIntegration;
using WizshBoneTwitchIntegration.Types;
using WizshBoneTwitchIntegration.extensions;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("WizshBoneTwitchIntegration")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("WizshBoneTwitchIntegration")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("1.0.1")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.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;
		}
	}
}
[Serializable]
public class ApiCodeTokenResponse
{
	public string access_token;

	public int expires_in;

	public string refresh_token;

	public string[] scope;

	public string token_type;
}
internal class UnityTwitch : TwitchSDKApi
{
	private class UnityPAL : ManagedPAL
	{
		private TaskCompletionSource<string> FileIOBasePathTCS = new TaskCompletionSource<string>();

		private readonly HttpClient m_http = new HttpClient
		{
			Timeout = TimeSpan.FromSeconds(10.0)
		};

		private readonly CancellationTokenSource m_cancel = new CancellationTokenSource();

		private static readonly Encoding Utf8NoBom;

		private readonly Dictionary<int, ClientWebSocket> m_webSockets = new Dictionary<int, ClientWebSocket>();

		private int m_nextWebSocketHandle = 1;

		protected override string HttpUserAgent => "Twitch-Route-66-Unity";

		static UnityPAL()
		{
			Utf8NoBom = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
			TaskScheduler.UnobservedTaskException += delegate(object a, UnobservedTaskExceptionEventArgs exc)
			{
				if (exc.Exception.InnerException.GetType() == typeof(CoreLibraryException))
				{
					Debug.LogWarning((object)("Unhandled Twitch Exception: " + exc.Exception.InnerException));
				}
			};
		}

		public void Start()
		{
			FileIOBasePathTCS.SetResult(Application.persistentDataPath);
		}

		protected override Task Log(LogRequest req)
		{
			switch (req.Level)
			{
			case LogLevel.Warning:
				Debug.LogWarning((object)req.Message);
				break;
			case LogLevel.Error:
				Debug.LogError((object)req.Message);
				break;
			default:
				Debug.Log((object)req.Message);
				break;
			case LogLevel.Debug:
				break;
			}
			return Task.CompletedTask;
		}

		protected override void DisposeManaged()
		{
			m_cancel.Cancel();
			lock (m_webSockets)
			{
				foreach (KeyValuePair<int, ClientWebSocket> webSocket in m_webSockets)
				{
					webSocket.Value.Dispose();
				}
				m_webSockets.Clear();
			}
			base.DisposeManaged();
		}

		protected override async Task<WebRequestResult> WebRequest(WebRequestRequest request)
		{
			HttpRequestMessage val = new HttpRequestMessage
			{
				RequestUri = new Uri(request.Uri)
			};
			bool flag = false;
			switch (request.Method)
			{
			case HttpMethod.Get:
				val.Method = HttpMethod.Get;
				break;
			case HttpMethod.Post:
				val.Method = HttpMethod.Post;
				flag = true;
				break;
			case HttpMethod.Put:
				val.Method = HttpMethod.Put;
				flag = true;
				break;
			case HttpMethod.Patch:
				val.Method = new HttpMethod("PATCH");
				flag = true;
				break;
			case HttpMethod.Delete:
				val.Method = HttpMethod.Delete;
				break;
			default:
				throw new NotImplementedException();
			}
			if (flag)
			{
				val.Content = (HttpContent)new StringContent(request.RequestBody, Encoding.UTF8, request.ContentType);
			}
			if (!string.IsNullOrEmpty(request.ClientId))
			{
				((HttpHeaders)val.Headers).Add("Client-Id", request.ClientId);
			}
			if (!string.IsNullOrEmpty(request.Authorization))
			{
				((HttpHeaders)val.Headers).Add("Authorization", request.Authorization);
			}
			val.Headers.UserAgent.Add(new ProductInfoHeaderValue(HttpUserAgent, "0.2"));
			HttpResponseMessage response = await m_http.SendAsync(val, (HttpCompletionOption)0, m_cancel.Token).ConfigureAwait(continueOnCapturedContext: false);
			try
			{
				string responseBody = await response.Content.ReadAsStringAsync().ConfigureAwait(continueOnCapturedContext: false);
				return new WebRequestResult
				{
					HttpStatus = (int)response.StatusCode,
					ResponseBody = responseBody
				};
			}
			finally
			{
				((IDisposable)response)?.Dispose();
			}
		}

		private ClientWebSocket GetWebSocket(int handle)
		{
			lock (m_webSockets)
			{
				return m_webSockets[handle];
			}
		}

		protected override async Task<int> CreateWebSocket(CreateWebSocketRequest req)
		{
			ClientWebSocket clientWebSocket = new ClientWebSocket();
			int handle;
			lock (m_webSockets)
			{
				handle = m_nextWebSocketHandle++;
				m_webSockets[handle] = clientWebSocket;
			}
			await clientWebSocket.ConnectAsync(new Uri(req.Url), m_cancel.Token).ConfigureAwait(continueOnCapturedContext: false);
			return handle;
		}

		protected override async Task SendWebSocketMessage(SendWebSocketMessageRequest req)
		{
			ClientWebSocket webSocket = GetWebSocket(req.Handle);
			ArraySegment<byte> buffer = new ArraySegment<byte>(Utf8NoBom.GetBytes(req.Message));
			await webSocket.SendAsync(buffer, WebSocketMessageType.Text, endOfMessage: true, m_cancel.Token).ConfigureAwait(continueOnCapturedContext: false);
		}

		protected override async Task<string> RecvWebSocketMessage(RecvWebSocketMessageRequest req)
		{
			ClientWebSocket webSocket = GetWebSocket(req.Handle);
			using MemoryStream stream = new MemoryStream();
			using (CancellationTokenSource timeout = new CancellationTokenSource(TimeSpan.FromSeconds(req.TimeoutSeconds)))
			{
				using CancellationTokenSource linked = CancellationTokenSource.CreateLinkedTokenSource(m_cancel.Token, timeout.Token);
				WebSocketReceiveResult webSocketReceiveResult;
				do
				{
					ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[1024]);
					webSocketReceiveResult = await webSocket.ReceiveAsync(buffer, linked.Token).ConfigureAwait(continueOnCapturedContext: false);
					if (webSocketReceiveResult.MessageType == WebSocketMessageType.Close)
					{
						throw new EndOfStreamException("websocket is closed");
					}
					if (webSocketReceiveResult.MessageType != WebSocketMessageType.Text)
					{
						throw new InvalidOperationException("not receiving text");
					}
					stream.Write(buffer.Array, 0, webSocketReceiveResult.Count);
				}
				while (!webSocketReceiveResult.EndOfMessage);
			}
			return Utf8NoBom.GetString(stream.ToArray());
		}

		protected override async Task CloseWebSocket(CloseWebSocketRequest req)
		{
			ClientWebSocket webSocket = GetWebSocket(req.Handle);
			lock (m_webSockets)
			{
				m_webSockets.Remove(req.Handle);
			}
			await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "normal closure", m_cancel.Token).ConfigureAwait(continueOnCapturedContext: false);
			webSocket.Dispose();
		}

		protected override Task<string> GetFileIOBasePath(CancellationToken _)
		{
			return FileIOBasePathTCS.Task;
		}
	}

	private UnityPAL PAL;

	public UnityTwitch(string clientId, bool useESProxy)
		: base(clientId, useESProxy)
	{
	}

	public void InitializeInternally()
	{
		PAL.Start();
	}

	protected override PlatformAbstractionLayer CreatePAL()
	{
		return PAL = new UnityPAL();
	}
}
public class Twitch : MonoBehaviour
{
	private static object Lock = new object();

	private static Twitch _Twitch;

	private TwitchSDKApi Instance;

	public static TwitchSDKApi API
	{
		get
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			lock (Lock)
			{
				if ((Object)(object)_Twitch != (Object)null && _Twitch.Instance != null)
				{
					return _Twitch.Instance;
				}
				try
				{
					_Twitch = Object.FindObjectOfType<Twitch>();
				}
				catch (object obj) when (((Func<bool>)delegate
				{
					// Could not convert BlockContainer to single expression
					object obj2 = ((obj is UnityException) ? obj : null);
					return obj2 != null && ((Exception)obj2).HResult == -2147467261;
				}).Invoke())
				{
					throw new Exception("The Twitch API can only be initialized on the main thread. Make sure the first invocation of Twitch.API happens in the Unity Main thread (e.g. the Start or Update method, and not a constructor)");
				}
				if ((Object)(object)_Twitch != (Object)null && _Twitch.Instance != null)
				{
					Object.Destroy((Object)(object)((Component)_Twitch).gameObject);
				}
				if ((Object)(object)_Twitch == (Object)null)
				{
					GameObject val = new GameObject();
					_Twitch = val.AddComponent<Twitch>();
					_Twitch.CreateInstance();
					((Object)val).name = "TwitchApi (Singleton)";
					Object.DontDestroyOnLoad((Object)val);
				}
				return _Twitch.Instance;
			}
		}
	}

	private void CreateInstance()
	{
		TwitchSDKSettings instance = TwitchSDKSettings.Instance;
		if (instance.ClientId == "Go to dev.twitch.tv to get a client-id")
		{
			Debug.LogError((object)"Twitch: No OAuth ClientId set. Please open the Twitch settings at Twitch->Edit Settings.");
		}
		Instance = new UnityTwitch(instance.ClientId, instance.UseEventSubProxy);
		((UnityTwitch)Instance).InitializeInternally();
	}

	private void OnApplicationQuit()
	{
		if (Instance != null)
		{
			Debug.Log((object)"OnApplicationQuit Twitch API");
			Instance.Dispose();
			Instance = null;
		}
	}

	private void OnDestroy()
	{
		if (Instance != null)
		{
			Debug.Log((object)"OnDestroy Twitch API");
			Instance.Dispose();
			Instance = null;
		}
	}
}
internal class TwitchSDKSettings : ScriptableObject
{
	public const string InitialClientId = "Go to dev.twitch.tv to get a client-id";

	public const string SettingsPath = "Project/TwitchSDKSettings";

	[SerializeField]
	public string ClientId = "8i260qk16tmvumfssr2h4klu99frjb";

	[SerializeField]
	public bool UseEventSubProxy;

	private static TwitchSDKSettings _Instance;

	public static TwitchSDKSettings Instance
	{
		get
		{
			_Instance = NullableInstance;
			if ((Object)(object)_Instance == (Object)null)
			{
				_Instance = ScriptableObject.CreateInstance<TwitchSDKSettings>();
			}
			return _Instance;
		}
	}

	public static TwitchSDKSettings NullableInstance
	{
		get
		{
			if ((Object)(object)_Instance == (Object)null)
			{
				_Instance = Resources.Load("TwitchSDKSettings") as TwitchSDKSettings;
			}
			return _Instance;
		}
	}
}
namespace ModularMagic_Utilities.Helpers
{
	internal class GUIHelper
	{
		public static GameObject CreateSliderField(Transform parent, Vector2 anchorMin, Vector2 anchorMax, Vector2 position, float minValue, float maxValue, float defaultValue, bool wholeNumbers, float width = 0f, float height = 0f)
		{
			//IL_0005: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = DefaultControls.CreateSlider(GUIManager.Instance.ValheimControlResources);
			obj.transform.SetParent(parent, false);
			Slider component = obj.GetComponent<Slider>();
			GUIManager.Instance.ApplySliderStyle(component);
			component.minValue = minValue;
			component.maxValue = maxValue;
			component.value = defaultValue;
			component.wholeNumbers = wholeNumbers;
			Transform transform = obj.transform;
			Transform obj2 = ((transform is RectTransform) ? transform : null);
			((RectTransform)obj2).anchoredPosition = position;
			((RectTransform)obj2).anchorMin = anchorMin;
			((RectTransform)obj2).anchorMax = anchorMax;
			return obj;
		}

		public static GameObject CreateToggle(Transform parent, Vector2 anchorMin, Vector2 anchorMax, Vector2 position, float width = 0f, float height = 0f)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GUIManager.Instance.CreateToggle(parent, width, height);
			RectTransform component = ((Component)obj.GetComponent<Toggle>()).GetComponent<RectTransform>();
			component.anchoredPosition = position;
			component.anchorMin = anchorMin;
			component.anchorMax = anchorMax;
			return obj;
		}
	}
}
namespace WizshBoneTwitchIntegration
{
	[BepInPlugin("DeathWizsh.WizshBoneTwitchIntegration", "WizshBoneTwitchIntegration", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	internal class WizshBoneTwitchIntegration : BaseUnityPlugin
	{
		public const string PluginGUID = "DeathWizsh.WizshBoneTwitchIntegration";

		public const string PluginName = "WizshBoneTwitchIntegration";

		public const string PluginVersion = "1.0.1";

		public static WizshBoneTwitchIntegration Instance;

		private static readonly Harmony harmony = new Harmony("DeathWizsh.WizshBoneTwitchIntegration");

		private AssetBundle assetBundle;

		public CustomPrefabs prefabs = new CustomPrefabs();

		public CustomMaterials materials = new CustomMaterials();

		public CustomStatusEffects effects = new CustomStatusEffects();

		public CustomSprites sprites = new CustomSprites();

		public CustomEffectLists effectLists = new CustomEffectLists();

		private ButtonConfig wizshBoneWindowButton;

		private ButtonConfig quickTestRedeemButton;

		public static bool useRedeemCommand = false;

		public static readonly string HumanoidGroupNoDamageStructure = "WBTI_HumanoidGroupNoDamageStructure";

		public static readonly string HumanoidGroupSpawnEnemy = "WBTI_HumanoidGroupSpawnEnemy";

		public static readonly string HumanoidGroupSpawnFriendly = "WBTI_HumanoidGroupSpawnFriendly";

		public static readonly string customConfigPath = "BepInEx/config/WizshBoneTwitchIntegration";

		public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization();

		public static string bannedPath => ConfigPathHelper.GetEffectiveRoot() + "/banned.txt";

		public static string viewersPath => ConfigPathHelper.GetEffectiveRoot() + "/viewers.yaml";

		public static string newsSeenPath => ConfigPathHelper.GetEffectiveRoot() + "/newsSeen.yaml";

		public void Awake()
		{
			Instance = this;
			InitAssetBundle();
			PluginConfig.Init();
			ProfileSyncHelper.Init();
			InitStatusEffects();
			InitInputs();
			InitCommands();
			harmony.PatchAll(Assembly.GetExecutingAssembly());
			PrefabManager.OnVanillaPrefabsAvailable += InitExtraConfigFiles;
			PrefabManager.OnVanillaPrefabsAvailable += SetupPieces;
			PrefabManager.OnVanillaPrefabsAvailable += AddEffectLists;
			PrefabManager.OnPrefabsRegistered += AddPersistentComponents;
			PrefabManager.OnPrefabsRegistered += RedeemPrefabCatalog.BuildPrefabCatalogs;
			ItemManager.OnItemsRegistered += LogStatusEffects;
		}

		public void Update()
		{
			HandleNewUIWindowInput();
			HandleQuickTestRedeemInput();
		}

		private void HandleNewUIWindowInput()
		{
			//IL_008a: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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)
			try
			{
				if (ZInput.instance == null || wizshBoneWindowButton == null || !Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					return;
				}
				WizshBoneGUI component = ((Component)Game.instance).gameObject.GetComponent<WizshBoneGUI>();
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				bool isVisible = component.IsVisible;
				KeyboardShortcut value;
				if (IsVanillaHideUiCombo())
				{
					if (isVisible)
					{
						value = PluginConfig.configWizshBoneWindow.Value;
						if (Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey))
						{
							component.CloseShell();
						}
					}
					return;
				}
				bool num;
				if (!isVisible)
				{
					num = ZInput.GetButtonDown(wizshBoneWindowButton.Name);
				}
				else
				{
					value = PluginConfig.configWizshBoneWindow.Value;
					num = ((KeyboardShortcut)(ref value)).IsDown();
				}
				if (num)
				{
					if (isVisible)
					{
						component.CloseShell();
					}
					else
					{
						component.ShowShell();
					}
				}
			}
			catch (Exception arg)
			{
				Logger.LogWarning((object)$"[WBTI] Could not show new WizshBone UI: {arg}");
			}
		}

		private static bool IsVanillaHideUiCombo()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Invalid comparison between Unknown and I4
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Invalid comparison between Unknown and I4
			KeyboardShortcut value = PluginConfig.configWizshBoneWindow.Value;
			if ((int)((KeyboardShortcut)(ref value)).MainKey != 284)
			{
				return false;
			}
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if ((int)modifier == 306 || (int)modifier == 305)
				{
					return false;
				}
			}
			if (!Input.GetKey((KeyCode)306))
			{
				return Input.GetKey((KeyCode)305);
			}
			return true;
		}

		private void HandleQuickTestRedeemInput()
		{
			try
			{
				if (ZInput.instance != null && quickTestRedeemButton != null && Object.op_Implicit((Object)(object)Player.m_localPlayer) && ZInput.GetButtonDown(quickTestRedeemButton.Name))
				{
					TwitchCustomRewards component = ((Component)Game.instance).gameObject.GetComponent<TwitchCustomRewards>();
					if (string.IsNullOrEmpty(component.m_quickTestRedeem))
					{
						Logger.LogWarning((object)"[WBTI] No quick test redeem set. Use WBTISetQuickRedeem <title> first.");
					}
					else
					{
						UseRedeemCommand.FireRedeem(component.m_quickTestRedeem);
					}
				}
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Could not fire quick test redeem: " + ex));
			}
		}

		private void LogStatusEffects()
		{
			ItemManager.OnItemsRegistered -= LogStatusEffects;
		}

		private void SetupPieces()
		{
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Expected O, but got Unknown
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Expected O, but got Unknown
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Expected O, but got Unknown
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			prefabs.ChestIron.AddComponent<TwitchSurpriseChest>();
			((Component)prefabs.ChestIron.transform.Find("chest_top")).gameObject.AddComponent<TwitchSurpriseChestInteract>();
			prefabs.ChestGold.AddComponent<TwitchSurpriseChest>();
			((Component)prefabs.ChestGold.transform.Find("chest_top")).gameObject.AddComponent<TwitchSurpriseChestInteract>();
			((Component)prefabs.GuardStone.transform.Find("safezone")).gameObject.AddComponent<TwitchSafeZone>();
			((Component)prefabs.GuardStone.transform.Find("controls")).gameObject.AddComponent<TwitchSafeZoneControls>();
			prefabs.EnvZone.AddComponent<TwitchPersistentDestruction>();
			prefabs.TimeStopZone.AddComponent<TwitchPersistentDestruction>();
			prefabs.TimeStopZone.AddComponent<TwitchTimeStopZone>();
			prefabs.TerrainEdit.AddComponent<TwitchTerrainReset>();
			prefabs.Windmill = PrefabManager.Instance.CreateClonedPrefab("Windmill_WBTI", "windmill");
			Windmill component = prefabs.Windmill.GetComponent<Windmill>();
			Smelter component2 = prefabs.Windmill.GetComponent<Smelter>();
			prefabs.Windmill.AddComponent<TwitchWindmillPersistentData>().ConfigurePrefab(component);
			Object.DestroyImmediate((Object)(object)component);
			if ((Object)(object)component2 != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component2);
			}
			PrefabManager.Instance.AddPrefab(new CustomPrefab(prefabs.Windmill, true));
			PieceConfig val = new PieceConfig();
			val.Enabled = true;
			val.Name = "Twitchy Ward";
			val.Description = "A ward against mysterious and twitchy forces!";
			val.PieceTable = PieceTables.Hammer;
			val.Category = PieceCategories.Misc;
			val.Requirements = RecipeHelper.GetAsRequirementConfigArray(ProfileSettingsHelper.Current.wardRecipe, null, null);
			PieceManager.Instance.AddPiece(new CustomPiece(prefabs.GuardStone, true, val));
			GameObject prefab = PrefabManager.Instance.GetPrefab("piece_shieldgenerator");
			prefab.AddComponent<Demister>();
			ParticleSystemForceField obj = prefab.AddComponent<ParticleSystemForceField>();
			obj.gravity = MinMaxCurve.op_Implicit(-0.08f);
			obj.endRange = 30f;
			obj.multiplyDragByParticleSize = false;
			obj.multiplyDragByParticleVelocity = false;
			obj.rotationAttraction = MinMaxCurve.op_Implicit(1f);
			obj.vectorFieldAttraction = MinMaxCurve.op_Implicit(1f);
			obj.vectorFieldSpeed = MinMaxCurve.op_Implicit(1f);
			PrefabManager.OnVanillaPrefabsAvailable -= SetupPieces;
		}

		private void AddPersistentComponents()
		{
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			foreach (string prefabName in ZNetScene.instance.GetPrefabNames())
			{
				GameObject prefab = PrefabManager.Instance.GetPrefab(prefabName);
				Humanoid component = prefab.GetComponent<Humanoid>();
				MonsterAI component2 = prefab.GetComponent<MonsterAI>();
				prefab.AddComponent<TwitchBasePersistentData>();
				if (!((Object)(object)component != (Object)null) || !((Object)(object)component2 != (Object)null))
				{
					continue;
				}
				Transform val = prefab.transform.Find("Visual");
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				LevelEffects component3 = ((Component)val).gameObject.GetComponent<LevelEffects>();
				if (!((Object)(object)component3 == (Object)null))
				{
					LevelSetup item = component3.m_levelSetups[1];
					for (int i = 0; i < 8; i++)
					{
						component3.m_levelSetups.Add(item);
					}
				}
			}
			string[] array = new string[3] { "Vendor_BlackForest", "Hildir_camp", "BogWitch_Camp" };
			foreach (string text in array)
			{
				Transform val2 = PrefabManager.Instance.GetPrefab(text).transform.Find("ForceField");
				if ((Object)(object)val2 == (Object)null)
				{
					Logger.LogError((object)"Could not find force field to add safezone!");
					continue;
				}
				((Component)val2).gameObject.layer = 14;
				CapsuleCollider obj = ((Component)val2).gameObject.AddComponent<CapsuleCollider>();
				obj.radius = 0.5f;
				obj.height = 200f;
				((Collider)obj).isTrigger = true;
				((Collider)obj).includeLayers = LayerMask.op_Implicit(LayerMask.GetMask(new string[1] { "piece" }));
				((Component)val2).gameObject.AddComponent<Demister>();
				ParticleSystemForceField obj2 = ((Component)val2).gameObject.AddComponent<ParticleSystemForceField>();
				obj2.gravity = MinMaxCurve.op_Implicit(-0.08f);
				obj2.endRange = 15f;
				obj2.multiplyDragByParticleSize = false;
				obj2.multiplyDragByParticleVelocity = false;
				obj2.rotationAttraction = MinMaxCurve.op_Implicit(1f);
				obj2.vectorFieldAttraction = MinMaxCurve.op_Implicit(1f);
				obj2.vectorFieldSpeed = MinMaxCurve.op_Implicit(1f);
				((Component)val2).gameObject.AddComponent<TwitchSafeZone>();
			}
			PrefabManager.OnPrefabsRegistered -= AddPersistentComponents;
		}

		private void AddEffectLists()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Expected O, but got Unknown
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Expected O, but got Unknown
			EffectData val = new EffectData();
			val.m_enabled = true;
			val.m_prefab = PrefabManager.Instance.GetPrefab("vfx_corpse_destruction_small");
			val.m_variant = -1;
			List<EffectData> list = new List<EffectData>();
			list.Add(val);
			effectLists.SpawnEffectSmall.m_effectPrefabs = list.ToArray();
			EffectData val2 = new EffectData();
			val2.m_enabled = true;
			val2.m_prefab = PrefabManager.Instance.GetPrefab("vfx_corpse_destruction_medium");
			val2.m_variant = -1;
			List<EffectData> list2 = new List<EffectData>();
			list2.Add(val2);
			effectLists.SpawnEffectMedium.m_effectPrefabs = list2.ToArray();
			EffectData val3 = new EffectData();
			val3.m_enabled = true;
			val3.m_prefab = PrefabManager.Instance.GetPrefab("vfx_corpse_destruction_large");
			val3.m_variant = -1;
			List<EffectData> list3 = new List<EffectData>();
			list3.Add(val3);
			effectLists.SpawnEffectLarge.m_effectPrefabs = list3.ToArray();
			EffectData val4 = new EffectData();
			val4.m_enabled = true;
			val4.m_prefab = PrefabManager.Instance.GetPrefab("vfx_Place_wood_pole");
			val4.m_variant = -1;
			EffectData val5 = new EffectData();
			val5.m_enabled = true;
			val5.m_prefab = PrefabManager.Instance.GetPrefab("sfx_cooking_station_take");
			val5.m_variant = -1;
			List<EffectData> list4 = new List<EffectData>();
			list4.Add(val4);
			list4.Add(val5);
			effectLists.SpawnItemEffect.m_effectPrefabs = list4.ToArray();
			EffectData val6 = new EffectData();
			val6.m_enabled = true;
			val6.m_prefab = PrefabManager.Instance.GetPrefab("fx_HildirChest_Unlock");
			val6.m_variant = 0;
			List<EffectData> list5 = new List<EffectData>();
			list5.Add(val6);
			effectLists.ChestOpenEffect.m_effectPrefabs = list5.ToArray();
			PrefabManager.OnVanillaPrefabsAvailable -= AddEffectLists;
		}

		private void InitExtraConfigFiles()
		{
			ExtraConfigHelper.InitExtraConfigs();
			ExtraConfigHelper.ReadRedeemsConfig();
			ProfileSettingsHelper.Reload();
		}

		private void InitStatusEffects()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Expected O, but got Unknown
			ItemManager.Instance.AddStatusEffect(new CustomStatusEffect((StatusEffect)(object)effects.Burning, true));
			ItemManager.Instance.AddStatusEffect(new CustomStatusEffect(effects.Freezing, true));
			ItemManager.Instance.AddStatusEffect(new CustomStatusEffect(effects.Poison, true));
			ItemManager.Instance.AddStatusEffect(new CustomStatusEffect(effects.NoFallDamage, true));
			effects.PlayerScale = ScriptableObject.CreateInstance<SE_PlayerScale>();
			((Object)effects.PlayerScale).name = "PlayerScale";
			((StatusEffect)effects.PlayerScale).m_name = "PlayerScale";
			((StatusEffect)effects.PlayerScale).m_icon = sprites.MiniMeSprite;
			((StatusEffect)effects.PlayerScale).m_ttl = 180f;
			ItemManager.Instance.AddStatusEffect(new CustomStatusEffect((StatusEffect)(object)effects.PlayerScale, false));
		}

		private void InitInputs()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//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)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			try
			{
				wizshBoneWindowButton = new ButtonConfig
				{
					Name = "WizshBone Window",
					ShortcutConfig = PluginConfig.configWizshBoneWindow
				};
				InputManager.Instance.AddButton("DeathWizsh.WizshBoneTwitchIntegration", wizshBoneWindowButton);
				quickTestRedeemButton = new ButtonConfig
				{
					Name = "WBTI Quick Test Redeem",
					ShortcutConfig = PluginConfig.configQuickTestRedeemKey
				};
				InputManager.Instance.AddButton("DeathWizsh.WizshBoneTwitchIntegration", quickTestRedeemButton);
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Could not initialise inputs: " + ex));
			}
		}

		private void InitCommands()
		{
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new RemoveChestsCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new RemoveCreaturesCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new RemoveMistCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new RemoveTrapsCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new RemoveDoorsCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new RemoveWindmillsCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new RemoveLogsCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new RemoveBoatsCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new UsersBanList());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new UserBanCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new UserUnbanCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new ClearBossKeysCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new OpenConfigFolderCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new ReloadRedeemsCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new ReloadViewersCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new SetAliasCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new SetQuickRedeemCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new TestCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new TestWeatherCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new UseRedeemCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new ScanCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new ClaimCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new UnclaimCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new TestProfilesCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new TestRedeemsCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new TestSettingsCommand());
		}

		private void InitAssetBundle()
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Expected O, but got Unknown
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Expected O, but got Unknown
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Expected O, but got Unknown
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Expected O, but got Unknown
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Expected O, but got Unknown
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Expected O, but got Unknown
			assetBundle = AssetUtils.LoadAssetBundleFromResources("wbti_dw");
			prefabs.DetectFish = assetBundle.LoadAsset<GameObject>("Detect_Fish_WBTI");
			prefabs.FishRainScript = assetBundle.LoadAsset<GameObject>("spawn_fish_WBTI");
			PrefabManager.Instance.AddPrefab(new CustomPrefab(prefabs.FishRainScript, true));
			prefabs.Flashbang = assetBundle.LoadAsset<GameObject>("Flashbang_WBTI");
			PrefabManager.Instance.AddPrefab(new CustomPrefab(prefabs.Flashbang, true));
			prefabs.GuardStone = assetBundle.LoadAsset<GameObject>("WBTI_guard_stone");
			prefabs.TerrainEdit = assetBundle.LoadAsset<GameObject>("TerrainEdit_WBTI");
			PrefabManager.Instance.AddPrefab(new CustomPrefab(prefabs.TerrainEdit, true));
			prefabs.NeckBeard = assetBundle.LoadAsset<GameObject>("FeoTheHistorian_WBTI");
			PrefabManager.Instance.AddPrefab(new CustomPrefab(prefabs.NeckBeard, true));
			prefabs.ChestIron = assetBundle.LoadAsset<GameObject>("ChestIron_WBTI");
			PrefabManager.Instance.AddPrefab(new CustomPrefab(prefabs.ChestIron, true));
			prefabs.ChestGold = assetBundle.LoadAsset<GameObject>("ChestGold_WBTI");
			PrefabManager.Instance.AddPrefab(new CustomPrefab(prefabs.ChestGold, true));
			prefabs.EnvZone = assetBundle.LoadAsset<GameObject>("EnvZone_WBTI");
			PrefabManager.Instance.AddPrefab(new CustomPrefab(prefabs.EnvZone, true));
			prefabs.TimeStopZone = assetBundle.LoadAsset<GameObject>("TimeStopZone_WBTI");
			PrefabManager.Instance.AddPrefab(new CustomPrefab(prefabs.TimeStopZone, true));
			effects.Burning = assetBundle.LoadAsset<SE_Stats>("Burning_WBTI");
			effects.Freezing = assetBundle.LoadAsset<StatusEffect>("Freezing_WBTI");
			effects.Poison = assetBundle.LoadAsset<StatusEffect>("Poison_WBTI");
			effects.NoFallDamage = assetBundle.LoadAsset<StatusEffect>("NoFallDamage_WBTI");
			sprites.MiniMeSprite = assetBundle.LoadAsset<Sprite>("MiniMeSprite_WBTI");
			sprites.BigMeSprite = assetBundle.LoadAsset<Sprite>("BigMeSprite_WBTI");
			materials.RecolorAbomination = assetBundle.LoadAsset<Material>("Abomination_recolor_WBTI");
			materials.RecolorBat = assetBundle.LoadAsset<Material>("Bat_recolor_WBTI");
			materials.RecolorBjorn = assetBundle.LoadAsset<Material>("Bjorn_recolor_WBTI");
			materials.RecolorBjornZebra = assetBundle.LoadAsset<Material>("Bjorn_recolor_zebra_WBTI");
			materials.RecolorBlob = assetBundle.LoadAsset<Material>("Blob_recolor_WBTI");
			materials.RecolorBlobSlime = assetBundle.LoadAsset<Material>("BlobSlime_recolor_WBTI");
			materials.RecolorBoar = assetBundle.LoadAsset<Material>("Boar_recolor_WBTI");
			materials.RecolorBoarTusk = assetBundle.LoadAsset<Material>("BoarTusk_recolor_WBTI");
			materials.RecolorCultist = assetBundle.LoadAsset<Material>("Cultist_recolor_WBTI");
			materials.RecolorCultistCape = assetBundle.LoadAsset<Material>("CultistCape_recolor_WBTI");
			materials.RecolorDeathsquito = assetBundle.LoadAsset<Material>("Deathsquito_recolor_WBTI");
			materials.RecolorDeer = assetBundle.LoadAsset<Material>("Deer_recolor_WBTI");
			materials.RecolorDeerAntlers = assetBundle.LoadAsset<Material>("Deer_antlers_recolor_WBTI");
			materials.RecolorDraugr = assetBundle.LoadAsset<Material>("Draugr_recolor_WBTI");
			materials.RecolorDraugrFem = assetBundle.LoadAsset<Material>("Draugr_Ranged_recolor_WBTI");
			materials.RecolorDraugrElite = assetBundle.LoadAsset<Material>("Draugr_Elite_recolor_WBTI");
			materials.RecolorFenring = assetBundle.LoadAsset<Material>("Fenring_recolor_WBTI");
			materials.RecolorFuling = assetBundle.LoadAsset<Material>("Fuling_recolor_WBTI");
			materials.RecolorFulingArmor = assetBundle.LoadAsset<Material>("Fuling_armor_recolor_WBTI");
			materials.RecolorFulingBrute = assetBundle.LoadAsset<Material>("FulingBrute_recolor_WBTI");
			materials.RecolorFulingShaman = assetBundle.LoadAsset<Material>("FulingShaman_recolor_WBTI");
			materials.RecolorFulingShamanCape = assetBundle.LoadAsset<Material>("FulingShaman_cape_recolor_WBTI");
			materials.RecolorGhost = assetBundle.LoadAsset<Material>("Ghost_recolor_WBTI");
			materials.RecolorGjall = assetBundle.LoadAsset<Material>("Gjall_recolor_WBTI");
			materials.RecolorGreydwarf = assetBundle.LoadAsset<Material>("Greydwarf_recolor_WBTI");
			materials.RecolorGreydwarfShaman = assetBundle.LoadAsset<Material>("Greydwarf_Shaman_recolor_WBTI");
			materials.RecolorGreydwarfRootsword = assetBundle.LoadAsset<Material>("RootSword_recolor_WBTI");
			materials.RecolorHatchling = assetBundle.LoadAsset<Material>("Hatchling_recolor_WBTI");
			materials.RecolorLeech = assetBundle.LoadAsset<Material>("Leech_recolor_WBTI");
			materials.RecolorLox = assetBundle.LoadAsset<Material>("Lox_recolor_WBTI");
			materials.RecolorNeck = assetBundle.LoadAsset<Material>("Neck_recolor_WBTI");
			materials.RecolorSeeker = assetBundle.LoadAsset<Material>("Seeker_recolor_WBTI");
			materials.RecolorSeekerBrute = assetBundle.LoadAsset<Material>("SeekerBrute_recolor_WBTI");
			materials.RecolorSeekerBrood = assetBundle.LoadAsset<Material>("SeekerBrood_recolor_WBTI");
			materials.RecolorSerpent = assetBundle.LoadAsset<Material>("Serpent_recolor_WBTI");
			materials.RecolorSkeleton = assetBundle.LoadAsset<Material>("Skeleton_recolor_WBTI");
			materials.RecolorStoneGolem = assetBundle.LoadAsset<Material>("StoneGolem_recolor_WBTI");
			materials.RecolorStoneGolemClubs = assetBundle.LoadAsset<Material>("StoneGolemClubs_recolor_WBTI");
			materials.RecolorSurtling = assetBundle.LoadAsset<Material>("Surtling_recolor_WBTI");
			materials.RecolorTick = assetBundle.LoadAsset<Material>("Tick_recolor_WBTI");
			materials.RecolorTroll = assetBundle.LoadAsset<Material>("Troll_recolor_WBTI");
			materials.RecolorUlv = assetBundle.LoadAsset<Material>("Ulv_recolor_WBTI");
			materials.RecolorVile = assetBundle.LoadAsset<Material>("Vile_recolor_WBTI");
			materials.RecolorWolf = assetBundle.LoadAsset<Material>("Wolf_recolor_WBTI");
			materials.RecolorWraith = assetBundle.LoadAsset<Material>("Wraith_recolor_WBTI");
			materials.RecolorWraithZebra = assetBundle.LoadAsset<Material>("Wraith_recolor_zebra_WBTI");
		}
	}
}
namespace WizshBoneTwitchIntegration.Types
{
	internal class ChestType
	{
		public static string Gold => "Gold";

		public static string Iron => "Iron";
	}
	internal class DetonateType
	{
		public static string Creature => "Creature";

		public static string CreatureSpawned => "CreatureSpawned";

		public static string Fish => "Fish";

		public static string ItemType => "ItemType";

		public static string Piece => "Piece";
	}
	internal class DungeonType
	{
		public static string BurialChamber => "Crypt";

		public static string FrostCave => "Caves";

		public static string HowlingCavern => "CavesHildir";

		public static string InfestedMine => "InfectedMine";

		public static string SmoulderingTomb => "CryptHildir";

		public static string SunkenCrypt => "SunkenCrypt";

		public static string Queen => "Queen";
	}
	internal class ExceptionType
	{
		public static string Error => "Error";

		public static string Warning => "Warning";
	}
	internal class GlobalKeyType
	{
		public static string DefeatedNothing => "DefeatedNothing";

		public static string DefeatedNoBoss => "DefeatedNoBoss";

		public static string DefeatedEikthyr => "defeated_eikthyr";

		public static string DefeatedElder => "defeated_gdking";

		public static string DefeatedBonemass => "defeated_bonemass";

		public static string DefeatedModer => "defeated_dragon";

		public static string DefeatedYagluth => "defeated_goblinking";

		public static string DefeatedQueen => "defeated_queen";

		public static string DefeatedFader => "defeated_fader";

		public static string KilledBat => "killedBat";

		public static string KilledTroll => "killedtroll";

		public static string killedSurtling => "killed_surtling";
	}
	internal enum RecipeUpdateType
	{
		ENABLE,
		RECIPE,
		CRAFTINGSTATION,
		MINREQUIREDSTATIONLEVEL,
		MINREQUIREDREPAIRLEVEL
	}
	internal class RedeemColorType
	{
		public static string Purple = "#451663";

		public static string Brown => "#734624";

		public static string Green => "#395c32";

		public static string LightGreen => "#74bd66";

		public static string Grey => "#8c8c8c";

		public static string Pink => "#bb33ff";

		public static string Red => "#eb3434";

		public static string TrollBlue => "#4e8ebf";

		public static string Silver => "#b8d3e6";

		public static string Yellow => "#ebc034";
	}
	internal class RedeemType
	{
		public static readonly HashSet<string> SpawnAbilityFamily = new HashSet<string> { SpawnAbility, Door, Windmill, Smite, Rain, Meteor, Trap, Root, LogRain, BoatRain };

		public static string Detonate => "Detonate";

		public static string Flashbang => "Flashbang";

		public static string SpawnCreature => "SpawnCreature";

		public static string Mist => "Mist";

		public static string SpawnAbility => "SpawnAbility";

		public static string StatusEffect => "StatusEffect";

		public static string SurpriseChest => "SurpriseChest";

		public static string TerrainEdit => "TerrainEdit";

		public static string Undefined => "Undefined";

		public static string TimeStop => "TimeStop";

		public static string Weather => "Weather";

		public static string Door => "Door";

		public static string Windmill => "Windmill";

		public static string Smite => "Smite";

		public static string Rain => "Rain";

		public static string Meteor => "Meteor";

		public static string Trap => "Trap";

		public static string Root => "Root";

		public static string LogRain => "LogRain";

		public static string BoatRain => "BoatRain";
	}
	internal class SpawnAbilityTargetType
	{
		public static string ClosestEnemy => "ClosestEnemy";

		public static string RandomEnemy => "RandomEnemy";

		public static string Caster => "Caster";

		public static string Position => "Position";

		public static string RandomPathfindablePosition => "RandomPathfindablePosition";

		public static TargetType? ConvertToTargetType(string value)
		{
			return value switch
			{
				"ClosestEnemy" => (TargetType)0, 
				"RandomEnemy" => (TargetType)1, 
				"Caster" => (TargetType)2, 
				"Position" => (TargetType)3, 
				"RandomPathfindablePosition" => (TargetType)4, 
				_ => null, 
			};
		}
	}
	internal class SpawnPositionType
	{
		public static string InFrontOfPlayer => "InFrontOfPlayer";

		public static string OnPlayer => "OnPlayer";

		public static string Random => "Random";

		public static string RandomBehind => "RandomBehind";

		public static string RandomFlying => "RandomFlying";

		public static string Undefined => "Undefined";

		public static string WorldPosition => "WorldPosition";
	}
	internal class StatusEffectType
	{
		public static string PlayerShrink => "PlayerShrink";

		public static string PlayerGrow => "PlayerGrow";

		public static string Burning => ((Object)WizshBoneTwitchIntegration.Instance.effects.Burning).name;

		public static string Encumbered => "Encumbered";

		public static string Freezing => ((Object)WizshBoneTwitchIntegration.Instance.effects.Freezing).name;

		public static string Poison => ((Object)WizshBoneTwitchIntegration.Instance.effects.Poison).name;

		public static string Puke => "Puke";

		public static string Tarred => "Tared";

		public static string Wet => "Wet";

		public static string BeltStrength => "BeltStrength";

		public static string Demister => "Demister";

		public static string DvergrDamage => "SE_Dvergr_buff";

		public static string DvergrHeal => "SE_Dvergr_heal";

		public static string GoblinShamanShield => "GoblinShaman_shield";

		public static string GP_Bonemass => "GP_Bonemass";

		public static string GP_Eikthyr => "GP_Eikthyr";

		public static string GP_Fader => "GP_Fader";

		public static string GP_Moder => "GP_Moder";

		public static string GP_Queen => "GP_Queen";

		public static string GP_TheElder => "GP_TheElder";

		public static string GP_Yagluth => "GP_Yagluth";

		public static string Rested => "Rested";

		public static string SlowFall => "SlowFall";

		public static string StaffShield => "Staff_shield";

		public static string WindRun => "WindRun";

		public static string Wishbone => "Wishbone";

		public static string AntiSting => "Potion_BugRepellent";

		public static string BarlyWine => "Potion_barleywine";

		public static string BrewOfAnimalWispers => "Potion_tamer";

		public static string Bzerker => "Potion_bzerker";

		public static string FrostResist => "Potion_frostresist";

		public static string LightFoot => "Potion_LightFoot";

		public static string LovePotion => "Potion_TrollPheromones";

		public static string PoisonResist => "Potion_poisonresist";

		public static string Ratatosk => "Potion_hasty";

		public static string TrollStrength => "Potion_strength";

		public static string Vananidir => "Potion_swimmer";

		public static string EitrMinor => "Potion_eitr_minor";

		public static string EitrLingering => "Potion_eitr_lingering";

		public static string HealingMinor => "Potion_health_minor";

		public static string HealingMedium => "Potion_health_medium";

		public static string HealingMajor => "Potion_health_major";

		public static string HealingLingering => "Potion_health_lingering";

		public static string StaminaMinor => "Potion_stamina_minor";

		public static string StaminaMedium => "Potion_stamina_medium";

		public static string StaminaLingering => "Potion_stamina_lingering";
	}
	internal class TwitchAnnounceType
	{
		public static string Blue => "/announceblue";

		public static string Green => "/announcegreen";

		public static string Orange => "/announceorange";

		public static string None => "";

		public static string Purple => "/announcepurple";

		public static string Red => "/announce";
	}
	internal class TwitchStatusType
	{
		public static string LoggedIn => "LoggedIn";

		public static string LoggedOut => "LoggedOut";

		public static string WaitingForCode => "WaitingForCode";
	}
	internal class ValheimCreatureType
	{
		public static string Abomination => "Abomination";

		public static string Asksvin => "Asksvin";

		public static string Bat => "Bat";

		public static string Bjorn => "Bjorn";

		public static string Blob => "Blob";

		public static string BlobElite => "BlobElite";

		public static string BlobLava => "BlobLava";

		public static string BlobTar => "BlobTar";

		public static string Boar => "Boar";

		public static string BonemawSerpent => "BonemawSerpent";

		public static string Bonemass => "Bonemass";

		public static string Charred_Archer => "Charred_Archer";

		public static string Charred_Mage => "Charred_Mage";

		public static string Charred_Melee => "Charred_Melee";

		public static string Charred_Twitcher => "Charred_Twitcher";

		public static string Charred_Twitcher_Summoned => "Charred_Twitcher_Summoned";

		public static string Deathsquito => "Deathsquito";

		public static string Draugr => "Draugr";

		public static string Draugr_Elite => "Draugr_Elite";

		public static string Draugr_Ranged => "Draugr_Ranged";

		public static string Dverger => "Dverger";

		public static string DvergerMage => "DvergerMage";

		public static string Eikthyr => "Eikthyr";

		public static string Fader => "Fader";

		public static string FallenValkyrie => "FallenValkyrie";

		public static string Fenring => "Fenring";

		public static string Fenring_Cultist => "Fenring_Cultist";

		public static string Ghost => "Ghost";

		public static string Gjall => "Gjall";

		public static string Greydwarf => "Greydwarf";

		public static string Greydwarf_Elite => "Greydwarf_Elite";

		public static string Greydwarf_Shaman => "Greydwarf_Shaman";

		public static string Greyling => "Greyling";

		public static string Goblin => "Goblin";

		public static string GoblinBrute => "GoblinBrute";

		public static string GoblinShaman => "GoblinShaman";

		public static string Hatchling => "Hatchling";

		public static string Leech => "Leech";

		public static string LordReto => "Charred_Melee_Dyrnwyn";

		public static string Lox => "Lox";

		public static string Moder => "Dragon";

		public static string Morgen => "Morgen";

		public static string Neck => "Neck";

		public static string Queen => "SeekerQueen";

		public static string Seeker => "Seeker";

		public static string SeekerBrood => "SeekerBrood";

		public static string SeekerBrute => "SeekerBrute";

		public static string Serpent => "Serpent";

		public static string Skeleton => "Skeleton";

		public static string Skeleton_Poison => "Skeleton_Poison";

		public static string Skugg => "piece_Charred_Balista";

		public static string StoneGolem => "StoneGolem";

		public static string Surtling => "Surtling";

		public static string TheElder => "gd_king";

		public static string Tick => "Tick";

		public static string Troll => "Troll";

		public static string Ulv => "Ulv";

		public static string Unbjorn => "Unbjorn";

		public static string Volture => "Volture";

		public static string Wolf => "Wolf";

		public static string Wraith => "Wraith";

		public static string Yagluth => "GoblinKing";

		public static string Bat_Swamp => "Bat_Swamp";

		public static string Bjorn_spiritcaller => "Bjorn_spiritcaller";

		public static string Boar_spiritcaller => "Boar_spiritcaller";

		public static string Moose_spiritcaller => "Moose_spiritcaller";

		public static string Wolf_spiritcaller => "Wolf_spiritcaller";

		public static string DvergerMageFire => "DvergerMageFire";

		public static string DvergerMageIce => "DvergerMageIce";

		public static string DvergerMageSupport => "DvergerMageSupport";

		public static string DvergerAshlands => "DvergerAshlands";

		public static string GoblinArcher => "GoblinArcher";

		public static string Skeleton_Hildir => "Skeleton_Hildir";

		public static string Skeleton_Hildir_nochest => "Skeleton_Hildir_nochest";

		public static string GoblinShaman_Hildir => "GoblinShaman_Hildir";

		public static string GoblinShaman_Hildir_nochest => "GoblinShaman_Hildir_nochest";

		public static string GoblinBrute_Hildir => "GoblinBrute_Hildir";

		public static string GoblinBruteBros => "GoblinBruteBros";

		public static string GoblinBruteBros_nochest => "GoblinBruteBros_nochest";

		public static string Fenring_Cultist_Hildir => "Fenring_Cultist_Hildir";

		public static string Fenring_Cultist_Hildir_nochest => "Fenring_Cultist_Hildir_nochest";

		public static string Hen => "Hen";

		public static string Moose => "Moose";

		public static string Barka => "Barka";

		public static string BogWitchKvastur => "BogWitchKvastur";

		public static string FeoTheHistorian => "FeoTheHistorian_WBTI";

		public static string TentaRoot => "TentaRoot";

		public static string TentaRoot_wild => "TentaRoot_wild";

		public static string Tendril => "Tendril";

		public static string Tendril_back => "Tendril_back";

		public static string SummonedRoot => "staff_greenroots_tentaroot";

		public static string Aspect_Bonemass => "Aspect_Bonemass";

		public static string Aspect_Eikthyr => "Aspect_Eikthyr";

		public static string Aspect_Elder => "Aspect_Elder";

		public static string Aspect_Fader => "Aspect_Fader";

		public static string Aspect_Moder => "Aspect_Moder";

		public static string Aspect_SeekerQueen => "Aspect_SeekerQueen";

		public static string Aspect_TentaRoot => "Aspect_TentaRoot";

		public static string Aspect_Yagluth => "Aspect_Yagluth";

		public static string FallenWarrior => "FallenWarrior";

		public static string Mistile => "Mistile";

		public static string Writhan => "Writhan";

		public static string Frysling => "Frysling";

		public static string FrostWisp => "FrostWisp";

		public static string Elaking => "Elaking";

		public static string ElakingLantern => "ElakingLantern";

		public static string ElakingMole => "ElakingMole";

		public static string FrozenKing => "FrozenKing";

		public static string FrozenKing_p2 => "FrozenKing_p2";

		public static string FrozenKing_p3 => "FrozenKing_p3";

		public static string TrollFrost => "TrollFrost";

		public static string JotunWarrior => "JotunWarrior";

		public static string JotunWarriorDualWield => "JotunWarriorDualWield";

		public static string JotunWitch => "JotunWitch";

		public static string DvergerDeepNorth => "DvergerDeepNorth";

		public static string GoblinDeepNorth => "GoblinDeepNorth";

		public static string BlobFrost => "BlobFrost";

		public static string BlobMork => "BlobMork";

		public static string BlobMorkMini => "BlobMorkMini";

		public static string Ghost_old => "Ghost_old";

		public static string Ghost_Void => "Ghost_Void";
	}
}
namespace WizshBoneTwitchIntegration.Models
{
	internal class CustomEffectLists
	{
		public EffectList ChestOpenEffect = new EffectList();

		public EffectList SpawnItemEffect = new EffectList();

		public EffectList SpawnEffectSmall = new EffectList();

		public EffectList SpawnEffectMedium = new EffectList();

		public EffectList SpawnEffectLarge = new EffectList();

		public EffectList SpawnEffectBig = new EffectList();
	}
	internal class CustomMaterials
	{
		public Material RecolorAbomination;

		public Material RecolorBat;

		public Material RecolorBjorn;

		public Material RecolorBjornZebra;

		public Material RecolorBlob;

		public Material RecolorBlobSlime;

		public Material RecolorBoar;

		public Material RecolorBoarTusk;

		public Material RecolorCultist;

		public Material RecolorCultistCape;

		public Material RecolorDeathsquito;

		public Material RecolorDeer;

		public Material RecolorDeerAntlers;

		public Material RecolorDraugr;

		public Material RecolorDraugrFem;

		public Material RecolorDraugrElite;

		public Material RecolorFenring;

		public Material RecolorFuling;

		public Material RecolorFulingArmor;

		public Material RecolorFulingBrute;

		public Material RecolorFulingShaman;

		public Material RecolorFulingShamanCape;

		public Material RecolorGhost;

		public Material RecolorGjall;

		public Material RecolorGreydwarf;

		public Material RecolorGreydwarfShaman;

		public Material RecolorGreydwarfRootsword;

		public Material RecolorHatchling;

		public Material RecolorLeech;

		public Material RecolorLox;

		public Material RecolorNeck;

		public Material RecolorSeeker;

		public Material RecolorSeekerBrute;

		public Material RecolorSeekerBrood;

		public Material RecolorSerpent;

		public Material RecolorSkeleton;

		public Material RecolorStoneGolem;

		public Material RecolorStoneGolemClubs;

		public Material RecolorSurtling;

		public Material RecolorTick;

		public Material RecolorTroll;

		public Material RecolorWolf;

		public Material RecolorUlv;

		public Material RecolorVile;

		public Material RecolorWraith;

		public Material RecolorWraithZebra;
	}
	internal class CustomPrefabs
	{
		public GameObject DetectFish;

		public GameObject FishRainScript;

		public GameObject Flashbang;

		public GameObject Windmill;

		public GameObject GuardStone;

		public GameObject TerrainEdit;

		public GameObject NeckBeard;

		public GameObject ChestIron;

		public GameObject ChestGold;

		public GameObject EnvZone;

		public GameObject TimeStopZone;
	}
	internal class CustomSprites
	{
		public Sprite MiniMeSprite;

		public Sprite BigMeSprite;
	}
	internal class CustomStatusEffects
	{
		public SE_Stats Burning;

		public StatusEffect Freezing;

		public StatusEffect Poison;

		public StatusEffect NoFallDamage;

		public SE_PlayerScale PlayerScale;
	}
	internal abstract class CloneableData
	{
		public T Clone<T>() where T : CloneableData, new()
		{
			T val = new T();
			FieldInfo[] fields = GetType().GetFields(BindingFlags.Instance | BindingFlags.Public);
			foreach (FieldInfo fieldInfo in fields)
			{
				fieldInfo.SetValue(val, fieldInfo.GetValue(this));
			}
			return val;
		}

		public T DeepClone<T>() where T : CloneableData, new()
		{
			T val = new T();
			FieldInfo[] fields = GetType().GetFields(BindingFlags.Instance | BindingFlags.Public);
			foreach (FieldInfo fieldInfo in fields)
			{
				object value = fieldInfo.GetValue(this);
				if (value is CloneableData nested)
				{
					fieldInfo.SetValue(val, DeepCloneValue(nested, fieldInfo.FieldType));
				}
				else if (value is IList list)
				{
					fieldInfo.SetValue(val, DeepCloneList(list, fieldInfo.FieldType));
				}
				else
				{
					fieldInfo.SetValue(val, value);
				}
			}
			return val;
		}

		private static object DeepCloneValue(CloneableData nested, Type type)
		{
			return typeof(CloneableData).GetMethod("DeepClone").MakeGenericMethod(type).Invoke(nested, null);
		}

		private static IList DeepCloneList(IList list, Type listType)
		{
			IList list2 = (IList)Activator.CreateInstance(listType);
			foreach (object item in list)
			{
				if (item is CloneableData nested)
				{
					list2.Add(DeepCloneValue(nested, item.GetType()));
				}
				else
				{
					list2.Add(item);
				}
			}
			return list2;
		}
	}
	internal class CreatureData : CloneableData
	{
		public string announceMessage;

		public bool aggravatable;

		public bool allowDrops;

		public int amount = 1;

		public bool commandable;

		[EditorLabel("Creature color")]
		[EditorTooltip("Overrides the creature's color in hex format (e.g. #ffffff for white). Leave blank for default.")]
		[ColorPicker]
		public string color;

		public float damageScale;

		public bool friendly;

		public string globalKeyAdd = "";

		public string globalKeyRemove = "";

		public string group;

		public float healthScale;

		public bool isBoss;

		public int level = 1;

		public float maxHealth;

		public int maxSpawned;

		public bool mistVision = true;

		public string name;

		[CreaturePrefabNameDropdown]
		public string prefabName;

		public bool facePlayer;

		public string position = SpawnPositionType.Random;

		public PositionOffsetData positionOffset = new PositionOffsetData();

		public float positionRadius = 10f;

		public bool random;

		public bool rename = true;

		public float talkInterval;

		public string talkMessage;

		public bool talks;

		public float size = 1f;

		public float speedMultiplier = 1f;

		[EditorLabel("Idle sound interval")]
		[EditorTooltip("Overrides the interval (seconds) between the creature's idle sound effect (e.g. a Fuling's laugh), and makes it always play instead of the default ~50% chance. Leave at 0 to use the creature's default behavior.")]
		public float idleSoundInterval;

		[EditorHidden]
		public bool allowDamageStructures = true;

		[EditorHidden]
		public string bossEvent = "";

		[EditorHidden]
		public bool isHallucination;

		[EditorHidden]
		public int index;

		[EditorHidden]
		public bool talkInteract;

		[EditorHidden]
		public bool forceColor;

		[EditorHidden]
		public bool alwaysFollowOwner;

		[EditorHidden]
		public bool fullyPassive;
	}
	internal class CreatureGroupData : CloneableData
	{
		[EditorLabel("Group Name")]
		[EditorTooltip("Unique identifier referenced by SpawnCreature redeem entries via their 'group' field.")]
		public string group;

		[EditorLabel("Creatures")]
		[EditorTooltip("Creatures belonging to this group.")]
		public List<CreatureData> list = new List<CreatureData>();
	}
	internal class DamageData : CloneableData
	{
		[EditorLabel("Blunt damage")]
		public float? blunt;

		[EditorLabel("Chop damage")]
		[EditorTooltip("This damage is only applied to trees and structures.")]
		public float? chop;

		[EditorHidden]
		public float? damage;

		[EditorLabel("Fire damage")]
		public float? fire;

		[EditorLabel("Frost damage")]
		public float? frost;

		[EditorLabel("Lightning damage")]
		public float? lightning;

		[EditorLabel("Pickaxe damage")]
		[EditorTooltip("This damage is only applied to minable objects, like stone, ore etc. (StoneGolem too)")]
		public float? pickaxe;

		[EditorLabel("Pierce damage")]
		public float? pierce;

		[EditorLabel("Poison damage")]
		public float? poison;

		[EditorLabel("Slash damage")]
		public float? slash;

		[EditorLabel("Spirit damage")]
		[EditorTooltip("This damage is only applied to undead")]
		public float? spirit;

		[EditorLabel("Based on max health and armor")]
		[EditorTooltip("If enabled, the damage will be calculated based on the player's max health and armor. Does require one of the damage(s) to be set!")]
		public bool basedOnMaxHealthAndArmor;

		[EditorLabel("Armor percentage")]
		[EditorTooltip("Percentage of the player's armor to use for damage calculation. Only if 'Based on max health and armor' is enabled.")]
		public float armorPercentage = 0.8f;

		[EditorLabel("Max health percentage")]
		[EditorTooltip("Percentage of the player's max health to use for damage calculation. Only if 'Based on max health and armor' is enabled.")]
		public float maxHealthPercentage = 0.45f;

		[EditorLabel("Damage ships")]
		public bool damageShips;

		[EditorLabel("Damage structures")]
		public bool damageStructures = true;

		[EditorLabel("Damage bosses")]
		public bool damageBosses;
	}
	internal class DetonateData : CloneableData
	{
		[EditorLabel("Announce message")]
		[EditorTooltip("A custom message to announce that a detonation is about to occur. {{user}} will be replaced with the player's name.")]
		public string announceMessage;

		[EditorLabel("Radius")]
		[EditorTooltip("The radius around the player it will search for objects to detonate, in meters.")]
		public float radius = 20f;

		[EditorLabel("Type")]
		[EditorTooltip("The type of objects to detonate.")]
		[DropdownOptions(new string[] { "Creature", "CreatureSpawned", "Fish", "Piece" })]
		public string type = DetonateType.Fish;

		[EditorLabel("Values")]
		[EditorTooltip("The object to detonate must contain this value in its name, if contains \"Fish\" then (Fish1, Fish2, Fish13) will detonate.")]
		public List<string> values = new List<string> { "Fish" };

		[EditorLabel("Damage settings")]
		[EditorTooltip("Custom damage setting for the explosion.")]
		public DamageData damageData = new DamageData
		{
			basedOnMaxHealthAndArmor = true,
			blunt = 70f,
			chop = 160f,
			fire = 30f,
			pickaxe = 160f
		};

		[EditorLabel("Damage terrain")]
		[EditorTooltip("Whether the explosion is allowed to dig/scorch terrain. Disabling this avoids the heightmap edit, which helps performance on large detonations.")]
		public bool damageTerrain = true;
	}
	internal class FlashBangData : CloneableData
	{
		[EditorLabel("Delay")]
		[EditorTooltip("Delay before the flash happens in seconds.")]
		public float delay = 0.5f;

		[EditorLabel("Flash color")]
		[EditorTooltip("The color of the flash in hex format (e.g. #ffffff for white).")]
		[ColorPicker]
		public string flashColor = "#ffffff";

		[EditorLabel("Flash Duration")]
		[EditorTooltip("The duration of the full flash effect in seconds.")]
		public float flashDuration = 2f;

		[EditorLabel("Fade out duration")]
		[EditorTooltip("The duration of the flash fading out in seconds.")]
		public float flashEndDuration = 5.8f;

		[EditorLabel("Fade in duration")]
		[EditorTooltip("The duration of the flash fading in seconds.")]
		public float flashStartDuration;

		[EditorLabel("Sound volume")]
		[EditorTooltip("The volume of the flash sound effect, ranging from 0.0 (silent) to 1.0 (full volume).")]
		public float soundVolume = 0.7f;
	}
	internal class ItemData : CloneableData
	{
		public string prefabName;

		public int stackSize = 1;

		public int quality = 1;
	}
	internal class MistData : CloneableData
	{
		[EditorLabel("Announce message")]
		[EditorTooltip("A custom message to announce that a mist is about to occur. {{user}} will be replaced with the player's name.")]
		public string announceMessage;

		[EditorLabel("Duration")]
		[EditorTooltip("The duration of the mist in seconds (0 = indefinite).")]
		public int duration = 60;

		[EditorLabel("Height")]
		[EditorTooltip("The height of the mist in meters.")]
		public float height = 15f;

		[EditorLabel("Radius")]
		[EditorTooltip("The radius of the mist in meters.")]
		public float radius = 60f;
	}
	internal class ModData
	{
		public int version;

		public List<RedeemData> redeems;

		public List<CreatureGroupData> creatureGroups;

		public ProfileSettingsData settings;
	}
	internal class NewsData
	{
		public int version;

		public string title;

		public List<NewsSection> sections;
	}
	internal class NewsSection
	{
		public string heading;

		public string body;
	}
	internal class PositionOffsetData : CloneableData
	{
		public float x;

		public float y;

		public float z;

		public Vector3 ToVector()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(x, y, z);
		}
	}
	internal class ProfileSettingsData
	{
		public bool chattingEnabled = true;

		public string chattingBlackList = "Nightbot, StreamElements";

		public int chattingClaimDuration = 300;

		public float chattingCullingRange = 50f;

		public float chattingInterval = 30f;

		public float chattingRadius = 60f;

		public int chattingMaxTalkers = 5;

		public bool chattingClaimFreeForAll;

		public bool creaturesSameFaction;

		public float creaturesMaxAmount = 100f;

		public float creaturesMaxRadius = 100f;

		public bool creaturesScaling = true;

		public float creaturesDamageScale = 0.15f;

		public float creaturesHealthScale = 0.15f;

		public float creaturesFollowRadius = 30f;

		public bool indestructibleBoats;

		public bool indestructibleChests;

		public bool indestructiblePortals;

		public bool indestructibleVegetables;

		public bool enableRedeemsOnLogin = true;

		public bool autoResolveRedeems = true;

		public string redeemTitlePrefix = "WBTI";

		public int redeemsDiscountPercent;

		public string wardRecipe = "FineWood:5, GreydwarfEye:5, SurtlingCore:1";

		public bool wardBurnCreatures;

		public bool wardPushCreatures = true;

		public float wardPushForce = 2000f;

		public bool safezoneTraders = true;

		public bool safezoneBoats;

		public HudPosition hudPosition;

		public float hudOffsetX;

		public float hudOffsetY;
	}
	internal class RecolorCreatureData
	{
		public bool isSurtling;

		public bool disable;

		public bool enable;

		public bool emissive;

		public float emissiveMultiplier = 2f;

		public bool isLight;

		public bool isParticle;

		public bool isGear;

		public Material material;

		public int materialIndex;

		public float particleAlpha = 0.2f;

		public string transformPath;

		public Material zebraMaterial;

		public RecolorCreatureData()
		{
		}

		public RecolorCreatureData(string transformPath)
		{
			this.transformPath = transformPath;
		}
	}
	internal class RedeemData : CloneableData
	{
		[EditorLabel("Title")]
		[EditorTooltip("The title of the redeem shown in Twitch.")]
		[InputPrefix("WBTI")]
		public string title = "";

		[EditorLabel("Description")]
		[EditorTooltip("The description of the redeem shown when selected in Twitch.")]
		public string description = "";

		[EditorLabel("Point cost")]
		[EditorTooltip("The number of points required to redeem this.")]
		public int points;

		[EditorLabel("Background color")]
		[EditorTooltip("The background color of the redeem shown in Twitch.")]
		[ColorPicker]
		public string backgroundColor = "#a970ff";

		[EditorLabel("Cooldown")]
		[EditorTooltip("Cooldown of the redeem in seconds.")]
		public int cooldown;

		[EditorHidden]
		public string cooldownUnit = "seconds";

		[EditorHidden]
		public int maxPerStream;

		[EditorHidden]
		public int maxPerUserPerStream;

		[EditorLabel("Add condition")]
		[EditorTooltip("The global key that will enable this redeem.")]
		[GlobalKeyDropdown]
		public string globalKeyAdd = "";

		[EditorLabel("Remove condition")]
		[EditorTooltip("The global key that will disable this redeem.")]
		[GlobalKeyDropdown]
		public string globalKeyRemove = "";

		[EditorLabel("Ignore safezone")]
		[EditorTooltip("Whether to ignore the safezone for this redeem.")]
		public bool ignoreWard;

		[EditorLabel("User input")]
		[EditorTooltip("Whether this redeem requires input.")]
		public bool userInput;

		[EditorHidden]
		public string type = RedeemType.Undefined;

		[EditorHidden]
		public bool enabled = true;

		[EditorHidden]
		public SurpriseChestData chestData = new SurpriseChestData();

		[EditorHidden]
		public SpawnCreatureData creatureData = new SpawnCreatureData();

		[EditorHidden]
		public DetonateData detonateData = new DetonateData();

		[EditorHidden]
		public FlashBangData flashbangData = new FlashBangData();

		[EditorHidden]
		public MistData mistData = new MistData();

		[EditorHidden]
		public TerrainEditData terrainEditData = new TerrainEditData();

		[EditorHidden]
		public SpawnAbilityData spawnAbilityData = new SpawnAbilityData();

		[EditorHidden]
		public StatusEffectData statusEffectData = new StatusEffectData();

		[EditorHidden]
		public TimeStopData timeStopData = new TimeStopData();

		[EditorHidden]
		public WeatherData weatherData = new WeatherData();

		private static readonly Dictionary<string, string> TypeToDataField = new Dictionary<string, string>
		{
			{
				RedeemType.Detonate,
				"detonateData"
			},
			{
				RedeemType.Flashbang,
				"flashbangData"
			},
			{
				RedeemType.Mist,
				"mistData"
			},
			{
				RedeemType.SpawnCreature,
				"creatureData"
			},
			{
				RedeemType.SpawnAbility,
				"spawnAbilityData"
			},
			{
				RedeemType.Door,
				"spawnAbilityData"
			},
			{
				RedeemType.Windmill,
				"spawnAbilityData"
			},
			{
				RedeemType.Smite,
				"spawnAbilityData"
			},
			{
				RedeemType.Rain,
				"spawnAbilityData"
			},
			{
				RedeemType.Meteor,
				"spawnAbilityData"
			},
			{
				RedeemType.Trap,
				"spawnAbilityData"
			},
			{
				RedeemType.Root,
				"spawnAbilityData"
			},
			{
				RedeemType.LogRain,
				"spawnAbilityData"
			},
			{
				RedeemType.BoatRain,
				"spawnAbilityData"
			},
			{
				RedeemType.SurpriseChest,
				"chestData"
			},
			{
				RedeemType.StatusEffect,
				"statusEffectData"
			},
			{
				RedeemType.TerrainEdit,
				"terrainEditData"
			},
			{
				RedeemType.TimeStop,
				"timeStopData"
			},
			{
				RedeemType.Weather,
				"weatherData"
			}
		};

		private static readonly HashSet<string> AllDataFields = new HashSet<string> { "chestData", "creatureData", "detonateData", "flashbangData", "mistData", "terrainEditData", "spawnAbilityData", "statusEffectData", "timeStopData", "weatherData" };

		public Dictionary<string, object> ToDictionary()
		{
			object obj = new RedeemData();
			Dictionary<string, object> dictionary = new Dictionary<string, object>();
			TypeToDataField.TryGetValue(type, out var value);
			FieldInfo[] fields = GetType().GetFields(BindingFlags.Instance | BindingFlags.Public);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (AllDataFields.Contains(fieldInfo.Name))
				{
					if (!(fieldInfo.Name != value) && fieldInfo.GetValue(this) is CloneableData data)
					{
						Dictionary<string, object> dictionary2 = MinimalDictionary(data);
						if (dictionary2.Count > 0)
						{
							dictionary[fieldInfo.Name] = dictionary2;
						}
					}
				}
				else
				{
					object value2 = fieldInfo.GetValue(this);
					if (value2 != null && !IsEqual(value2, fieldInfo.GetValue(obj)))
					{
						dictionary[fieldInfo.Name] = value2;
					}
				}
			}
			return dictionary;
		}

		internal static Dictionary<string, object> MinimalDictionary(CloneableData data)
		{
			object obj = Activator.CreateInstance(data.GetType());
			Dictionary<string, object> dictionary = new Dictionary<string, object>();
			FieldInfo[] fields = data.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public);
			foreach (FieldInfo fieldInfo in fields)
			{
				object value = fieldInfo.GetValue(data);
				if (value == null)
				{
					continue;
				}
				if (value is CloneableData data2)
				{
					Dictionary<string, object> dictionary2 = MinimalDictionary(data2);
					if (dictionary2.Count > 0)
					{
						dictionary[fieldInfo.Name] = dictionary2;
					}
				}
				else if (value is IList list)
				{
					if (IsEqual(value, fieldInfo.GetValue(obj)))
					{
						continue;
					}
					bool flag = false;
					foreach (object item in list)
					{
						if (item is CloneableData)
						{
							flag = true;
							break;
						}
					}
					if (flag)
					{
						List<object> list2 = new List<object>();
						foreach (object item2 in list)
						{
							list2.Add((item2 is CloneableData data3) ? MinimalDictionary(data3) : item2);
						}
						dictionary[fieldInfo.Name] = list2;
					}
					else
					{
						dictionary[fieldInfo.Name] = value;
					}
				}
				else if (!IsEqual(value, fieldInfo.GetValue(obj)))
				{
					dictionary[fieldInfo.Name] = value;
				}
			}
			return dictionary;
		}

		private static bool IsEqual(object a, object b)
		{
			if (a == null && b == null)
			{
				return true;
			}
			if (a == null || b == null)
			{
				return false;
			}
			if (a is IList list && b is IList list2)
			{
				if (list.Count != list2.Count)
				{
					return false;
				}
				for (int i = 0; i < list.Count; i++)
				{
					if (!object.Equals(list[i], list2[i]))
					{
						return false;
					}
				}
				return true;
			}
			return a.Equals(b);
		}

		public DamageData GetDamageData()
		{
			if (RedeemType.SpawnAbilityFamily.Contains(type))
			{
				return spawnAbilityData?.damage;
			}
			if (type == RedeemType.Detonate)
			{
				return detonateData?.damageData;
			}
			return null;
		}
	}
	internal class SpawnAbilityData : CloneableData
	{
		public float? accuracy;

		public bool allowDrops = true;

		public string announceMessage;

		public bool breakOnDestroy;

		public DamageData damage;

		public float? dropVelocity = 0f;

		public int duration;

		public float doorInterval;

		public float windmillRotationSpeed;

		public float? groundOffset;

		public float? initialSpawnDelay;

		public bool isBiomeList;

		public float? maxTargetRange;

		public int? maxToSpawn;

		public int? maxSpawned;

		public bool noSpawnEffect;

		public int? minToSpawn;

		public bool isOwner = true;

		public string prefabName;

		public bool randomRotation = true;

		public bool snapToterrain;

		public int batchSize = 1;

		public float? spawnDelay;

		public float? spawnRadius;

		public List<string> spawns = new List<string>();

		public string targetType = SpawnAbilityTargetType.Caster;

		public float? velocity;

		public float? velocityMax;

		[EditorHidden]
		public bool? randomDirection;

		[EditorHidden]
		public float? randomAngleMax;

		[EditorHidden]
		public float? randomAngleMin;

		[EditorHidden]
		public bool? randomYRotation;
	}
	internal class SpawnAbilitySpawnData : CloneableData
	{
		public List<CreatureData> creatureData;

		public ItemData itemData;
	}
	internal class SpawnCreatureData : CloneableData
	{
		[EditorLabel("Random")]
		[EditorTooltip("If enabled, a random creature from the list will be spawned.")]
		public bool random;

		[EditorLabel("Creatures")]
		[EditorTooltip("List of creatures to spawn.")]
		public List<CreatureData> list = new List<CreatureData>();
	}
	internal class StatusEffectData : CloneableData
	{
		[EditorLabel("Random")]
		[EditorTooltip("Whether a random status effect is picked from the list (if there is only 1 this has no effect)")]
		public bool random;

		[EditorLabel("Status Effects")]
		[EditorTooltip("The list of status effects to apply or to pick randomly from.")]
		public List<StatusEffectEntry> list = new List<StatusEffectEntry>();
	}
	internal class StatusEffectEntry : CloneableData
	{
		[EditorLabel("Name")]
		[EditorTooltip("The name of the status effect.")]
		[StatusEffectNameDropdown]
		[OnValueChanged("OnNameChanged")]
		public string name;

		[EditorLabel("Duration")]
		[EditorTooltip("The duration of the status effect in seconds. Set to -1 for default duration, 0 for infinite duration.")]
		public float duration = -1f;

		[EditorLabel("Persists through death")]
		[EditorTooltip("Whether the status effect should persist through death. If true, the status effect will not be removed when the player dies.")]
		public bool persistsThroughDeath;

		[EditorLabel("Renew")]
		[EditorTooltip("Whether to renew the status effect if it is already active. If true, the duration will be reset to the original duration when the status effect is applied again.")]
		public bool renew;

		[EditorVisibleWhen("name", new string[] { "PlayerShrink", "PlayerGrow" })]
		public SE_PlayerScaleData playerScale = new SE_PlayerScaleData();

		public void OnNameChanged()
		{
			float num = FieldUIBuilder.LookupStatusEffectTTL(name);
			duration = num;
		}
	}
	internal class SE_PlayerScaleData : CloneableData
	{
		[EditorLabel("Scale Delta")]
		[EditorTooltip("The amount to increase or decrease the player's scale by.")]
		public float scaleDelta = 0.3f;

		[EditorLabel("Scale Min")]
		[EditorTooltip("The minimum scale the player can be reduced to.")]
		public float scaleMin = 0.4f;

		[EditorLabel("Scale Max")]
		[EditorTooltip("The maximum scale the player can be increased to.")]
		public float scaleMax = 4f;

		[EditorLabel("Scale Duration")]
		[EditorTooltip("The duration of the scale animation.")]
		public float scaleDuration = 0.5f;

		[EditorLabel("Speed/Jump Multiplier Delta")]
		[EditorTooltip("The amount to increase or decrease the player's speed/jump multiplier by.")]
		public float speedMultiplierDelta = 0.125f;

		[EditorLabel("Speed/Jump Multiplier Min")]
		[EditorTooltip("The minimum speed/jump multiplier the player can be reduced to.")]
		public float speedMultiplierMin = 0.75f;

		[EditorLabel("Speed/Jump Multiplier Max")]
		[EditorTooltip("The maximum speed/jump multiplier the player can be increased to.")]
		public float speedMultiplierMax = 2.25f;
	}
	internal class SurpriseChestData : CloneableData
	{
		public int amount = 1;

		public string announceMessage;

		public bool facePlayer = true;

		public float force = 200f;

		[EditorHidden]
		public bool interact = true;

		public List<SurpriseChestSpawnData> items = new List<SurpriseChestSpawnData>();

		[EditorHidden]
		public int mimicChance;

		[EditorHidden]
		public string position = SpawnPositionType.Random;

		[EditorHidden]
		public PositionOffsetData positionOffset = new PositionOffsetData();

		public bool random = true;

		public string redeemTitle;

		public float spawnDelay = 0.7f;

		public string type = ChestType.Iron;

		public int yeetChance;
	}
	internal class SurpriseChestSpawnData : CloneableData
	{
		public List<CreatureData> creatureData;

		public ItemData itemData;

		public float weight = 1f;
	}
	internal class TerrainEditData : CloneableData
	{
		[EditorLabel("Announce message")]
		[EditorTooltip("A custom message to announce that a terrain edit is about to occur. {{user}} will be replaced with the player's name.")]
		public string announceMessage;

		[EditorLabel("Level Terrain")]
		[EditorTooltip("Whether to level the terrain.")]
		public bool level;

		[EditorLabel("Level Offset")]
		[EditorTooltip("The offset for the terrain leveling.")]
		public float levelOffset;

		[EditorLabel("Level Radius")]
		[EditorTooltip("The radius of the terrain leveling.")]
		public float levelRadius;

		[EditorLabel("Level Square")]
		[EditorTooltip("Whether to level the terrain in a square shape.")]
		public bool levelSquare;

		[EditorLabel("Raise Terrain")]
		[EditorTooltip("Whether to raise the terrain.")]
		public bool raise = true;

		[EditorLabel("Raise Delta")]
		[EditorTooltip("How much the terrain is raised, negative values to dig down.")]
		public float raiseDelta = -6f;

		[EditorLabel("Raise Power")]
		[EditorTooltip("The power of the terrain raise.")]
		public float raisePower;

		[EditorLabel("Raise Radius")]
		[EditorTooltip("The radius of the terrain raise.")]
		public float raiseRadius = 8f;

		[EditorLabel("Smooth Terrain")]
		[EditorTooltip("Whether to smooth the terrain after editing.")]
		public bool smooth;

		[EditorLabel("Smooth Radius")]
		[EditorTooltip("The radius of the terrain smoothing.")]
		public float smoothRadius;

		[EditorLabel("Smooth Power")]
		[EditorTooltip("The power of the terrain smoothing.")]
		public float smoothPower;

		[EditorLabel("Paint Clear")]
		[EditorTooltip("Whether to clear the paint after editing.")]
		public bool paintClear;

		[EditorLabel("Paint Height Check")]
		[EditorTooltip("Whether to check the height of the paint after editing.")]
		public bool paintHeightCheck;

		[EditorLabel("Paint Radius")]
		[EditorTooltip("The radius of the paint.")]
		public float paintRadius;

		[EditorLabel("Paint Type")]
		[EditorTooltip("The type of paint to use.")]
		public string paintType = "Dirt";

		[EditorLabel("Duration")]
		[EditorTooltip("How long in seconds before the terrain resets. 0 = permanent.")]
		public float duration;

		[EditorHidden]
		[EditorLabel("Shape")]
		[EditorTooltip("The shape of the terrain edit.")]
		[DropdownOptions(new string[] { "Circle", "Rectangle", "Chevron" })]
		public string shape = "Circle";

		[EditorLabel("Position offset")]
		[EditorTooltip("Where to apply the terrain edit relative to the player.")]
		public PositionOffsetData positionOffset = new PositionOffsetData();

		[EditorLabel("No fall damage")]
		[EditorTooltip("Whether to apply no fall damage to the player during the terrain edit.")]
		public bool noFallDamage = true;
	}
	internal class TimeStopData : CloneableData
	{
		[EditorLabel("Duration")]
		[EditorTooltip("How long the time stop zone stays active, in seconds.")]
		public float duration = 30f;

		[EditorLabel("Freeze enemies")]
		[EditorTooltip("Whether enemies that enter the zone are frozen.")]
		public bool freezeEnemies = true;

		[EditorLabel("Freeze player")]
		[EditorTooltip("Whether the player is also frozen while inside the zone.")]
		public bool freezePlayer;

		[EditorLabel("Freeze projectiles")]
		[EditorTooltip("Whether projectiles and other physics props (logs, debris, etc.) entering the zone are frozen.")]
		public bool freezeProjectiles = true;

		[EditorLabel("Radius")]
		[EditorTooltip("Radius of the time stop zone in meters.")]
		public float radius = 10f;

		[EditorLabel("Announce message")]
		[EditorTooltip("Message shown on screen when triggered. Use {{user}} for the redeemer's name.")]
		public string announceMessage = "";
	}
	internal class ViewerData
	{
		public List<ViewerEntry> viewers;
	}
	internal class ViewerEntry : CloneableData
	{
		[EditorLabel("Viewer Name (lower case only)")]
		public string name;

		[EditorLabel("Creature color")]
		[EditorTooltip("The color of the creature in hex format (e.g. #ffffff for white).")]
		[ColorPicker]
		public string color1 = "#ffffff";

		[EditorHidden]
		public List<string> effects = new List<string>();

		[EditorHidden]
		public Color parsedColor1;

		private static readonly HashSet<string> SkippedFields = new HashSet<string> { "parsedColor1" };

		public void Init()
		{
			ColorUtility.TryParseHtmlString(color1, ref parsedColor1);
		}

		public Dictionary<string, object> ToDictionary()
		{
			object obj = new ViewerEntry();
			Dictionary<string, object> dictionary = new Dictionary<string, object>();
			FieldInfo[] fields = GetType().GetFields(BindingFlags.Instance | BindingFlags.Public);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (!SkippedFields.Contains(fieldInfo.Name))
				{
					object value = fieldInfo.GetValue(this);
					if (fieldInfo.Name == "name")
					{
						dictionary[fieldInfo.Name] = value ?? "";
					}
					else if (value != null && !IsEqual(value, fieldInfo.GetValue(obj)))
					{
						dictionary[fieldInfo.Name] = value;
					}
				}
			}
			return dictionary;
		}

		private static bool IsEqual(object a, object b)
		{
			if (a == null && b == null)
			{
				return true;
			}
			if (a == null || b == null)
			{
				return false;
			}
			if (a is IList list && b is IList list2)
			{
				if (list.Count != list2.Count)
				{
					return false;
				}
				for (int i = 0; i < list.Count; i++)
				{
					if (!object.Equals(list[i], list2[i]))
					{
						return false;
					}
				}
				return true;
			}
			return a.Equals(b);
		}
	}
	internal class WeatherData : CloneableData
	{
		[EditorLabel("Announce message")]
		[EditorTooltip("A custom message to announce that a weather event is about to occur. {{user}} will be replaced with the player's name.")]
		public string announceMessage;

		[EditorLabel("Duration")]
		[EditorTooltip("The duration of the weather event in seconds (0 = indefinite).")]
		public int duration = 60;

		[EditorLabel("Force")]
		[EditorTooltip("Whether to force the weather event to occur.")]
		public bool force;

		[EditorLabel("Height")]
		[EditorTooltip("The height of the weather event in meters.")]
		public float height = 50f;

		[EditorLabel("Radius")]
		[EditorTooltip("The radius of the weather event in meters.")]
		public float radius = 200f;

		[EditorLabel("Weathers")]
		[EditorTooltip("A list of weather types that can occur during this event.")]
		public List<string> items = new List<string>();
	}
	internal class SpawnOptions
	{
		public CreatureData creatureData;

		public CustomRewardEvent customReward;

		public bool ignoreWard;

		public Transform transform;

		public SpawnOptions(CreatureData creatureData, Transform transform, CustomRewardEvent customReward = null, bool ignoreWard = false)
		{
			this.creatureData = creatureData;
			this.customReward = customReward;
			this.ignoreWard = ignoreWard;
			this.transform = transform;
		}
	}
	internal class UpdateRecipeOptions
	{
		public string? name;

		public bool? enable;

		public string? craftingStation;

		public string? requirements;

		public int? requiredStationLevel;

		public RecipeUpdateType updateType = RecipeUpdateType.RECIPE;

		public string? upgradeRequirements;

		public int? upgradeMultiplier;
	}
	internal class PlayerSnapshot
	{
		public float jumpForce;

		public float jumpForceForward;

		public float acceleration;

		public float crouchSpeed;

		public float runSpeed;

		public float speed;

		public float walkSpeed;

		public float swimAcceleration;

		public float swimDepth;

		public float swimSpeed;

		public float maxCarryWeight;

		public PlayerSnapshot(Player player)
		{
			Create(player);
		}

		public void Create(Player player)
		{
			jumpForce = ((Character)player).m_jumpForce;
			jumpForceForward = ((Character)player).m_jumpForceForward;
			acceleration = ((Character)player).m_acceleration;
			crouchSpeed = ((Character)player).m_crouchSpeed;
			runSpeed = ((Character)player).m_runSpeed;
			speed = ((Character)player).m_speed;
			walkSpeed = ((Character)player).m_walkSpeed;
			swimAcceleration = ((Character)player).m_swimAcceleration;
			swimDepth = ((Character)player).m_swimDepth;
			swimSpeed = ((Character)player).m_swimSpeed;
			maxCarryWeight = player.m_maxCarryWeight;
		}

		public void Apply(Player player)
		{
			((Character)player).m_jumpForce = jumpForce;
			((Character)player).m_jumpForceForward = jumpForceForward;
			((Character)player).m_acceleration = acceleration;
			((Character)player).m_crouchSpeed = crouchSpeed;
			((Character)player).m_runSpeed = runSpeed;
			((Character)player).m_speed = speed;
			((Character)player).m_walkSpeed = walkSpeed;
			((Character)player).m_swimAcceleration = swimAcceleration;
			((Character)player).m_swimDepth = swimDepth;
			((Character)player).m_swimSpeed = swimSpeed;
			player.m_maxCarryWeight = maxCarryWeight;
		}
	}
	internal class TwitchChatMessage
	{
		public string userName;

		public bool hasBeenBroadcasted;

		public string message;

		public DateTime timestamp;

		public TwitchChatMessage(string userName, string message)
		{
			this.userName = userName;
			this.message = message;
			timestamp = DateTime.Now;
		}
	}
	internal class TwitchCreatureAssignment
	{
		public GameObject creature;

		public int duration;

		public string userName;

		public DateTime claimedAt = DateTime.Now;

		public TwitchCreatureAssignment(string userName, GameObject creature, int duration)
		{
			this.creature = creature;
			this.duration = duration;
			this.userName = userName;
		}
	}
	internal class TwitchUserInfo
	{
		public string broadcasterType;

		public string displayName;
	}
	internal class ValheimCreature
	{
		public float tier;

		public EffectList spawnEffects;

		public ValheimCreature(float tier, EffectList spawnEffects)
		{
			this.spawnEffects = spawnEffects;
			this.tier = tier;
		}
	}
}
namespace WizshBoneTwitchIntegration.Models.Views
{
	internal sealed class CreatureSimpleView
	{
		[EditorLabel("Prefab name")]
		[EditorTooltip("The creature prefab to spawn (e.g. Neck, Greyling, Boar).")]
		[CreaturePrefabNameDropdown]
		public BoundField<string> prefabName;

		[EditorLabel("Amount")]
		[EditorTooltip("Number of of this creature to spawn.")]
		public BoundField<int> amount;

		[EditorLabel("Level")]
		[EditorTooltip("Star level (1 = no star, 10 is max).")]
		public BoundField<int> level;

		[EditorLabel("Size")]
		[EditorTooltip("Scale multiplier applied to the spawned creature.")]
		public BoundField<float> size;

		[EditorLabel("Speed multiplier")]
		[EditorTooltip("Movement speed multiplier applied to the spawned creature (1 = normal speed).")]
		public BoundField<float> speedMultiplier;

		[EditorLabel("Friendly")]
		public BoundField<bool> friendly;

		[EditorLabel("Commandable")]
		[EditorTooltip("Requires Friendly to be enabled.")]
		public BoundField<bool> commandable;

		[EditorLabel("Rename")]
		[EditorTooltip("Name of the creature, if left blank it will use the redeemer name")]
		public BoundField<bool> rename;

		[EditorLabel("Creature color")]
		[EditorTooltip("Overrides the creature's color in hex format (e.g. #ffffff for white). Leave blank for default.")]
		[ColorPicker]
		public BoundField<string> color;

		[EditorLabel("Announce message")]
		[EditorTooltip("Optional chat message announced when this redeem triggers.")]
		public BoundField<string> announceMessage;

		public CreatureSimpleView(CreatureData real)
		{
			prefabName = new BoundField<string>(() => real.prefabName, delegate(string v)
			{
				real.prefabName = v;
			});
			amount = new BoundField<int>(() => real.amount, delegate(int v)
			{
				real.amount = v;
			});
			level = new BoundField<int>(() => real.level, delegate(int v)
			{
				real.level = v;
			});
			size = new BoundField<float>(() => real.size, delegate(float v)
			{
				real.size = v;
			});
			speedMultiplier = new BoundField<float>(() => real.speedMultiplier, delegate(float v)
			{
				real.speedMultiplier = v;
			});
			friendly = new BoundField<bool>(() => real.friendly, delegate(bool v)
			{
				real.friendly = v;
			});
			commandable = new BoundField<bool>(() => real.commandable, delegate(bool v)
			{
				real.commandable = v;
			});
			rename = new BoundField<bool>(() => real.rename, delegate(bool v)
			{
				real.rename = v;
			});
			color = new BoundField<string>(() => real.color, delegate(string v)
			{
				real.color = v;
			});
			announceMessage = new BoundField<string>(() => real.announceMessage, delegate(string v)
			{
				real.announceMessage = v;
			});
		}
	}
	internal sealed class DoorView
	{
		[EditorLabel("Door prefab")]
		[EditorTooltip("Which door prefab gets spawned.")]
		[DoorPrefabNameDropdown]
		public BoundField<string> doorPrefab;

		[EditorLabel("Door interval")]
		[EditorTooltip("Interval in seconds at which spawned doors toggle open/closed (0 = disabled).")]
		public BoundField<float> doorInterval;

		[EditorLabel("Duration")]
		[EditorTooltip("How long the effect lasts, in seconds (0 = indefinite).")]
		public BoundField<int> duration;

		[EditorLabel("Min to spawn")]
		public BoundField<int?> minToSpawn;

		[EditorLabel("Max to spawn")]
		public BoundField<int?> maxToSpawn;

		[EditorLabel("Spawn radius")]
		public BoundField<float?> spawnRadius;

		[EditorLabel("Spawn delay")]
		[EditorTooltip("Delay in seconds before each door is spawned.")]
		public BoundField<float?> spawnDelay;

		[EditorLabel("Ground offset")]
		[EditorTooltip("Vertical offset from the ground at which the prefab spawn.")]
		public BoundField<float?> groundOffset;

		[EditorLabel("Allow drops")]
		[EditorTooltip("Whether the spawned prefabs can drop items when destroyed.")]
		public BoundField<bool> allowDrops;

		[EditorLabel("Announce message")]
		[EditorTooltip("Optional chat message announced when this redeem triggers.")]
		public BoundField<string> announceMessage;

		public DoorView(SpawnAbilityData real)
		{
			doorPrefab = new BoundField<string>(() => (real.spawns == null || real.spawns.Count <= 0) ? null : real.spawns[0], delegate(string v)
			{
				real.spawns = (string.IsNullOrEmpty(v) ? new List<string>() : new List<string> { v });
			});
			doorInterval = new BoundField<float>(() => real.doorInterval, delegate(float v)
			{
				real.doorInterval = v;
			});
			duration = new BoundField<int>(() => real.duration, delegate(int v)
			{
				real.duration = v;
			});
			minToSpawn = new BoundField<int?>(() => real.minToSpawn, delegate(int? v)
			{
				real.minToSpawn = v;
			});
			maxToSpawn = new BoundField<int?>(() => real.maxToSpawn, delegate(int? v)
			{
				real.maxToSpawn = v;
			});
			spawnRadius = new BoundField<float?>(() => real.spawnRadius, delegate(float? v)
			{
				real.spawnRadius = v;
			});
			spawnDelay = new BoundField<float?>(() => real.spawnDelay, delegate(float? v)
			{
				real.spawnDelay = v;
			});
			groundOffset = new BoundField<float?>(() => real.groundOffset, delegate(float? v)
			{
				real.groundOffset = v;
			});
			allowDrops = new BoundField<bool>(() => real.allowDrops, delegate(bool v)
			{
				real.allowDrops = v;
			});
			announceMessage = new BoundField<string>(() => real.announceMessage, delegate(string v)
			{
				real.announceMessage = v;
			});
		}
	}
	internal sealed class LogRainView
	{
		[EditorLabel("Announce message")]
		[EditorTooltip("Optional chat message announced when this redeem triggers.")]
		public BoundField<string> announceMessage;

		[EditorLabel("Duration")]
		[EditorTooltip("How long the effect lasts, in seconds (0 = indefinite).")]
		public BoundField<int> duration;

		[EditorLabel("Ground offset")]
		[EditorTooltip("Vertical offset from the ground at which the prefab spawn.")]
		public BoundField<float?> groundOffset;

		[EditorLabel("Min to spawn")]
		public BoundField<int?> minToSpawn;

		[EditorLabel("Max to spawn")]
		public BoundField<int?> maxToSpawn;

		[EditorLabel("Spawn radius")]
		public BoundField<float?> spawnRadius;

		[EditorLabel("Spawn delay")]
		[EditorTooltip("Delay in seconds between each log falling.")]
		public BoundField<float?> spawnDelay;

		[EditorLabel("Accuracy")]
		[EditorTooltip("Accuracy of the spawned prefabs.")]
		public BoundField<float?> accuracy;

		[EditorLabel("Allow drops")]
		[EditorTooltip("Whether the spawned prefabs can drop items when destroyed.")]
		public BoundField<bool> allowDrops;

		[EditorLabel("Logs")]
		[EditorTooltip("Log prefabs this redeem rains. Pick 'Biome specific' to replace this list with the 8 default per-biome logs and switch to biome-based selection.")]
		[LogPrefabNameDropdown]
		[OnValueChanged("OnBiomeSpecificSelected")]
		public List<string> spawns;

		public DamageData damage;

		private readonly SpawnAbilityData m_real;

		private static readonly string[] DefaultBiomeLogs = new string[8] { "beech_log_half", "PineTree_log_half", "SwampTree1_log", "FirTree_log_half", "Birch_log_half", "yggashoot_log_half", "AshlandsTreeLogHalf2", "Oak_log_half" };

		public LogRainView(SpawnAbilityData real)
		{
			m_real = real;
			duration = new BoundField<int>(() => real.duration, delegate(int v)
			{
				real.duration = v;
			});
			minToSpawn = new BoundField<int?>(() => real.minToSpawn, delegate(int? v)
			{
				real.minToSpawn = v;
			});
			maxToSpawn = new BoundField<int?>(() => real.maxToSpawn, delegate(int? v)
			{
				real.maxToSpawn = v;
			});
			spawnRadius = new BoundField<float?>(() => real.spawnRadius, delegate(float? v)
			{
				real.spawnRadius = v;
			});
			spawnDelay = new BoundField<float?>(() => real.spawnDelay, delegate(float? v)
			{
				real.spawnDelay = v;
			});
			accuracy = new BoundField<float?>(() => real.accuracy, delegate(float? v)
			{
				real.accuracy = v;
			});
			groundOffset = new BoundField<float?>(() => real.groundOffset, delegate(float? v)
			{
				real.groundOffset = v;
			});
			allowDrops = new BoundField<bool>(() => real.allowDrops, delegate(bool v)
			{
				real.allowDrops = v;
			});
			announceMessage = new BoundField<string>(() => real.announceMessage, delegate(string v)
			{
				real.announceMessage = v;
			});
			spawns = real.spawns ?? (real.spawns = new List<string>());
			damage = real.damage ?? (real.damage = new DamageData());
		}

		public void OnBiomeSpecificSelected()
		{
			m_real.isBiomeList = true;
			m_real.spawns.Clear();
			m_real.spawns.AddRange(DefaultBiomeLogs);
		}
	}
	internal sealed class MeteorView
	{
		[EditorLabel("Duration")]
		[EditorTooltip("How long the effect lasts, in seconds (0 = indefinite).")]
		public BoundField<int> duration;

		[EditorLabel("Min to spawn")]
		public BoundField<int?> minToSpawn;

		[EditorLabel("Max to spawn")]
		public BoundField<int?> maxToSpawn;

		[EditorLabel("Spawn radius")]
		public BoundField<float?> spawnRadius;

		[EditorLabel("Spawn delay")]
		[EditorTooltip("Delay in seconds between each meteor falling.")]
		public BoundField<float?> spawnDelay;

		[EditorLabel("Accuracy")]
		[EditorTooltip("Accuracy of the spawned prefabs.")]
		public BoundField<float?> accuracy;

		[EditorLabel("Ground offset")]
		[EditorTooltip("Vertical offset