Decompiled source of ClanWars v1.0.94

ClanWars.dll

Decompiled 16 hours ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ClanWars.Client;
using ClanWars.I18n;
using ClanWars.Model;
using ClanWars.Moshpits;
using ClanWars.Net;
using ClanWars.Patches;
using ClanWars.Relics;
using ClanWars.Server;
using ClanWars.Util;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.UI;
using Valheim.SettingsGui;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ClanWars")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.94.0")]
[assembly: AssemblyInformationalVersion("1.0.94+7ea7855e0d0b8ad17a4080f67b7b15f239c5fc64")]
[assembly: AssemblyProduct("ClanWars")]
[assembly: AssemblyTitle("ClanWars")]
[assembly: AssemblyVersion("1.0.94.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ClanWars
{
	public static class BattleTable
	{
		public const string PrefabName = "piece_cartographytable";

		public const string ChestName = "ClanWagerChest";

		public const int WagerCols = 6;

		public const int WagerRow = 0;

		public const int WinningsRow = 1;

		private const int WagerRows = 2;

		public const int WagerSlots = 12;

		private const float ChestWidth = 0.55f;

		private static bool _ready;

		public static bool Is(GameObject go)
		{
			if ((Object)(object)go == (Object)null)
			{
				return false;
			}
			if (((Object)go).name == "ClanWagerChest")
			{
				return true;
			}
			return Utils.GetPrefabName(go) == "piece_cartographytable";
		}

		public static Container ChestOf(GameObject table)
		{
			if (!((Object)(object)table != (Object)null))
			{
				return null;
			}
			return table.GetComponentInChildren<Container>(true);
		}

		public static void Setup()
		{
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			if (_ready)
			{
				return;
			}
			ZNetScene instance = ZNetScene.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			GameObject prefab = instance.GetPrefab("piece_cartographytable");
			if ((Object)(object)prefab == (Object)null)
			{
				return;
			}
			try
			{
				GameObject prefab2 = instance.GetPrefab("piece_chest_wood");
				Container val = (((Object)(object)prefab2 != (Object)null) ? prefab2.GetComponent<Container>() : null);
				GameObject val2 = Stand(prefab, prefab2);
				Container component = prefab.GetComponent<Container>();
				if ((Object)(object)component != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)component);
				}
				Container val3 = val2.GetComponent<Container>() ?? val2.AddComponent<Container>();
				val3.m_rootObjectOverride = prefab.GetComponent<ZNetView>();
				val3.m_name = "Clan wager";
				val3.m_width = 6;
				val3.m_height = 2;
				val3.m_privacy = (PrivacySetting)2;
				val3.m_checkGuardStone = true;
				val3.m_autoDestroyEmpty = false;
				val3.m_defaultItems = new DropTable();
				if ((Object)(object)val != (Object)null)
				{
					val3.m_openEffects = val.m_openEffects;
					val3.m_closeEffects = val.m_closeEffects;
					val3.m_bkg = val.m_bkg;
				}
				_ready = true;
				Log.Info("Cartography table: wager chest of " + 12 + " slots added.");
			}
			catch (Exception ex)
			{
				Log.Error("Could not give the cartography table its wager chest: " + ex);
			}
		}

		public static void Forget()
		{
			_ready = false;
		}

		private static GameObject Stand(GameObject table, GameObject chestPrefab)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			Transform val = table.transform.Find("ClanWagerChest");
			if ((Object)(object)val != (Object)null)
			{
				return ((Component)val).gameObject;
			}
			Bounds b = MeshBounds(table.transform, table.transform);
			GameObject val2 = new GameObject("ClanWagerChest");
			val2.transform.SetParent(table.transform, false);
			val2.layer = table.layer;
			GameObject val3 = Look(chestPrefab, val2.transform);
			Bounds b2 = (Bounds)(((Object)(object)val3 != (Object)null) ? MeshBounds(val3.transform, val2.transform) : new Bounds(Vector3.zero, Vector3.one * 0.5f));
			float num = ((((Bounds)(ref b2)).size.x > 0.01f) ? (0.55f / ((Bounds)(ref b2)).size.x) : 0.5f);
			if ((Object)(object)val3 != (Object)null)
			{
				val3.transform.localScale = Vector3.one * num;
			}
			Vector3 val4 = ((Bounds)(ref b2)).size * num;
			float num2 = Mathf.Clamp(((Bounds)(ref b)).min.x - val4.x * 0.5f - 0.05f, -4f, -0.45f);
			val2.transform.localPosition = new Vector3(num2, 0f, Mathf.Clamp(((Bounds)(ref b)).center.z, -1f, 1f));
			Log.Info("Wager chest: table " + Say(b) + ", chest " + Say(b2) + " at " + num.ToString("0.00") + ", stood at " + Say(val2.transform.localPosition) + ".");
			BoxCollider obj = val2.AddComponent<BoxCollider>();
			obj.center = new Vector3(0f, val4.y * 0.5f, 0f);
			obj.size = val4 * 1.05f;
			return val2;
		}

		private static GameObject Look(GameObject chestPrefab, Transform under)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)chestPrefab == (Object)null)
			{
				return null;
			}
			bool activeSelf = chestPrefab.activeSelf;
			chestPrefab.SetActive(false);
			GameObject val;
			try
			{
				val = Object.Instantiate<GameObject>(chestPrefab, under, false);
			}
			finally
			{
				chestPrefab.SetActive(activeSelf);
			}
			((Object)val).name = "look";
			val.transform.localPosition = Vector3.zero;
			val.transform.localRotation = Quaternion.identity;
			Component[] componentsInChildren = val.GetComponentsInChildren<Component>(true);
			foreach (Component val2 in componentsInChildren)
			{
				if (!((Object)(object)val2 == (Object)null) && !(val2 is Transform) && !(val2 is MeshFilter) && !(val2 is Renderer) && !(val2 is LODGroup))
				{
					try
					{
						Object.DestroyImmediate((Object)(object)val2);
					}
					catch (Exception ex)
					{
						Log.Debug("A chest part would not come off: " + ex.Message);
					}
				}
			}
			Transform[] componentsInChildren2 = val.GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				((Component)componentsInChildren2[i]).gameObject.layer = ((Component)under).gameObject.layer;
			}
			val.SetActive(true);
			return val;
		}

		private static string Say(Bounds b)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			return Say(((Bounds)(ref b)).min) + ".." + Say(((Bounds)(ref b)).max);
		}

		private static string Say(Vector3 v)
		{
			return "(" + v.x.ToString("0.00") + " " + v.y.ToString("0.00") + " " + v.z.ToString("0.00") + ")";
		}

		private static Bounds MeshBounds(Transform of, Transform inSpaceOf)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: 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_00c0: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			Bounds result = default(Bounds);
			((Bounds)(ref result))..ctor(Vector3.zero, Vector3.zero);
			MeshFilter[] componentsInChildren = ((Component)of).GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val in componentsInChildren)
			{
				Mesh sharedMesh = val.sharedMesh;
				if ((Object)(object)sharedMesh == (Object)null)
				{
					continue;
				}
				Bounds bounds = sharedMesh.bounds;
				for (int j = 0; j < 8; j++)
				{
					Vector3 val2 = ((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3(((j & 1) == 0) ? (-1f) : 1f, ((j & 2) == 0) ? (-1f) : 1f, ((j & 4) == 0) ? (-1f) : 1f));
					Vector3 val3 = inSpaceOf.InverseTransformPoint(((Component)val).transform.TransformPoint(val2));
					if (!flag)
					{
						((Bounds)(ref result))..ctor(val3, Vector3.zero);
						flag = true;
					}
					else
					{
						((Bounds)(ref result)).Encapsulate(val3);
					}
				}
			}
			if (!flag)
			{
				return new Bounds(Vector3.zero, Vector3.one * 0.5f);
			}
			return result;
		}

		public static bool OpenWagerChest(GameObject table, Humanoid user)
		{
			Container val = ChestOf(table);
			if ((Object)(object)val == (Object)null || (Object)(object)user == (Object)null)
			{
				return false;
			}
			ClanUI.Hide();
			return val.Interact(user, false, false);
		}

		public static void Update()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ClanUI.IsVisible)
			{
				return;
			}
			KeyboardShortcut value = ModConfig.BattleTableHotkey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown() && (!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !TextInput.IsVisible() && !Menu.IsVisible() && !StoreGui.IsVisible() && !InventoryGui.IsVisible())
			{
				GameObject hoverObject = ((Humanoid)localPlayer).GetHoverObject();
				MapTable val = (((Object)(object)hoverObject != (Object)null) ? hoverObject.GetComponentInParent<MapTable>() : null);
				if (!((Object)(object)val == (Object)null) && MayArrange(((Component)val).gameObject))
				{
					ClanUI.OpenClanBattles(((Component)val).gameObject);
				}
			}
		}

		public unsafe static string KeyName()
		{
			//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)
			try
			{
				KeyboardShortcut value = ModConfig.BattleTableHotkey.Value;
				return ((int)((KeyboardShortcut)(ref value)).MainKey == 0) ? "unbound" : ((object)(*(KeyboardShortcut*)(&value))/*cast due to .constrained prefix*/).ToString();
			}
			catch
			{
				return "unbound";
			}
		}

		public static bool MayArrange(GameObject table)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			ClanClient instance = ClanClient.Instance;
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)table == (Object)null || (Object)(object)localPlayer == (Object)null || !instance.Rules.clanBattlesEnabled)
			{
				return false;
			}
			if (string.IsNullOrEmpty(instance.State.clanId))
			{
				return false;
			}
			return instance.ClanHolding(table.transform.position) == instance.State.clanId;
		}
	}
	[HarmonyPatch(typeof(Switch), "GetHoverText")]
	public static class Switch_GetHoverText_BattleTable
	{
		private static void Postfix(Switch __instance, ref string __result)
		{
			MapTable componentInParent = ((Component)__instance).GetComponentInParent<MapTable>();
			if (!((Object)(object)componentInParent == (Object)null) && BattleTable.MayArrange(((Component)componentInParent).gameObject))
			{
				__result = __result + "\n[<color=yellow><b>" + BattleTable.KeyName() + "</b></color>] Clan battles";
			}
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	public static class ZNetScene_Awake_BattleTable
	{
		private static void Postfix()
		{
			BattleTable.Setup();
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	public static class ObjectDB_Awake_BattleTable
	{
		private static void Postfix()
		{
			BattleTable.Setup();
		}
	}
	public static class ClanArt
	{
		private const string Prefix = "ClanWars.Art/";

		private static Dictionary<string, string> _resources;

		private static readonly Dictionary<string, Texture2D> Textures = new Dictionary<string, Texture2D>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, Sprite> Sprites = new Dictionary<string, Sprite>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, Mesh> Meshes = new Dictionary<string, Mesh>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, string[]> MeshMaterials = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, Material> Materials = new Dictionary<string, Material>(StringComparer.OrdinalIgnoreCase);

		private static readonly HashSet<string> Missing = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private static Sprite _plain;

		public static bool HasGraphics => (int)SystemInfo.graphicsDeviceType != 4;

		public static Sprite Pin(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return null;
			}
			return LoadSprite("mappins/" + name + ".png") ?? LoadSprite("mappins/cw_pin_fallback.png") ?? Plain();
		}

		public static Sprite RelicIcon(string key)
		{
			return LoadSprite("relics/" + key + "/icon.png");
		}

		public static Sprite LoadSprite(string path)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			if (Sprites.TryGetValue(path, out var value))
			{
				return value;
			}
			Texture2D val = Texture(path, repeat: false);
			value = (((Object)(object)val != (Object)null) ? Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f) : null);
			if ((Object)(object)value != (Object)null)
			{
				((Object)value).name = Path.GetFileNameWithoutExtension(path);
			}
			Sprites[path] = value;
			return value;
		}

		private static Sprite Plain()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: 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)
			if ((Object)(object)_plain != (Object)null)
			{
				return _plain;
			}
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false)
			{
				wrapMode = (TextureWrapMode)1
			};
			Color32[] array = (Color32[])(object)new Color32[4096];
			float num = 31.5f;
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					float num2 = Mathf.Sqrt(((float)j - num) * ((float)j - num) + ((float)i - num) * ((float)i - num)) / num;
					array[i * 64 + j] = ((num2 > 1f) ? new Color32((byte)0, (byte)0, (byte)0, (byte)0) : ((num2 > 0.8f) ? new Color32((byte)30, (byte)22, (byte)15, byte.MaxValue) : new Color32((byte)234, (byte)226, (byte)208, byte.MaxValue)));
				}
			}
			val.SetPixels32(array);
			val.Apply();
			_plain = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f));
			return _plain;
		}

		public static Texture2D Texture(string path, bool repeat)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			if (Textures.TryGetValue(path, out var value))
			{
				return value;
			}
			value = null;
			if (HasGraphics)
			{
				byte[] array = Read(path);
				if (array != null)
				{
					Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true)
					{
						name = path,
						wrapMode = (TextureWrapMode)(!repeat),
						filterMode = (FilterMode)2,
						anisoLevel = 2
					};
					if (ImageConversion.LoadImage(val, array, false))
					{
						value = val;
					}
					else
					{
						Object.Destroy((Object)(object)val);
					}
				}
				if ((Object)(object)value == (Object)null)
				{
					Report(path);
				}
			}
			Textures[path] = value;
			return value;
		}

		public static Material Material(string name)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			if (Materials.TryGetValue(name, out var value))
			{
				return value;
			}
			value = null;
			if (HasGraphics)
			{
				Shader val = Shader.Find("Legacy Shaders/Diffuse") ?? Shader.Find("Standard") ?? Shader.Find("Sprites/Default");
				if ((Object)(object)val != (Object)null)
				{
					value = new Material(val)
					{
						name = "CW_" + name
					};
					Texture2D val2 = Texture("materials/" + name + ".png", repeat: true);
					if ((Object)(object)val2 != (Object)null)
					{
						value.mainTexture = (Texture)(object)val2;
					}
				}
			}
			Materials[name] = value;
			return value;
		}

		public static Mesh Model(string path, out string[] materials)
		{
			if (Meshes.TryGetValue(path, out var value))
			{
				MeshMaterials.TryGetValue(path, out materials);
				return value;
			}
			value = null;
			materials = null;
			byte[] array = Read(path);
			if (array != null)
			{
				try
				{
					value = ParseObj(Path.GetFileNameWithoutExtension(path), Encoding.UTF8.GetString(array), out materials);
				}
				catch (Exception ex)
				{
					Log.Warn("Clan Wars art " + path + " could not be read: " + ex.Message);
				}
			}
			if ((Object)(object)value == (Object)null)
			{
				Report(path);
			}
			Meshes[path] = value;
			MeshMaterials[path] = materials;
			return value;
		}

		public static GameObject Build(string path, string name, Transform parent, int layer)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			string[] materials;
			Mesh val = Model(path, out materials);
			if ((Object)(object)val == (Object)null || !HasGraphics)
			{
				return null;
			}
			GameObject val2 = new GameObject(name);
			val2.layer = layer;
			val2.transform.SetParent(parent, false);
			val2.AddComponent<MeshFilter>().sharedMesh = val;
			MeshRenderer val3 = val2.AddComponent<MeshRenderer>();
			Material[] array = (Material[])(object)new Material[(materials == null) ? 1 : materials.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = Material((materials != null) ? materials[i] : "iron");
			}
			((Renderer)val3).sharedMaterials = array;
			((Renderer)val3).shadowCastingMode = (ShadowCastingMode)1;
			((Renderer)val3).receiveShadows = true;
			return val2;
		}

		private static Mesh ParseObj(string name, string text, out string[] materials)
		{
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Expected O, but got Unknown
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			List<Vector3> list = new List<Vector3>();
			List<Vector2> list2 = new List<Vector2>();
			List<Vector3> list3 = new List<Vector3>();
			List<Vector2> list4 = new List<Vector2>();
			Dictionary<long, int> dictionary = new Dictionary<long, int>();
			List<List<int>> list5 = new List<List<int>>();
			List<string> list6 = new List<string>();
			List<int> list7 = null;
			CultureInfo invariantCulture = CultureInfo.InvariantCulture;
			string[] array = text.Split('\n');
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim();
				if (text2.Length == 0 || text2[0] == '#')
				{
					continue;
				}
				string[] array2 = text2.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
				switch (array2[0])
				{
				case "v":
					list.Add(new Vector3(float.Parse(array2[1], invariantCulture), float.Parse(array2[2], invariantCulture), float.Parse(array2[3], invariantCulture)));
					break;
				case "vt":
					list2.Add(new Vector2(float.Parse(array2[1], invariantCulture), float.Parse(array2[2], invariantCulture)));
					break;
				case "usemtl":
					list7 = new List<int>();
					list5.Add(list7);
					list6.Add((array2.Length > 1) ? array2[1] : "iron");
					break;
				case "f":
				{
					if (list7 == null)
					{
						list7 = new List<int>();
						list5.Add(list7);
						list6.Add("iron");
					}
					int[] array3 = new int[array2.Length - 1];
					for (int j = 1; j < array2.Length; j++)
					{
						string[] array4 = array2[j].Split('/');
						int num = int.Parse(array4[0], invariantCulture) - 1;
						int num2 = ((array4.Length > 1 && array4[1].Length > 0) ? (int.Parse(array4[1], invariantCulture) - 1) : (-1));
						long key = ((long)num << 32) | (uint)(num2 + 1);
						if (!dictionary.TryGetValue(key, out var value))
						{
							value = list3.Count;
							list3.Add(list[num]);
							list4.Add((num2 >= 0) ? list2[num2] : Vector2.zero);
							dictionary[key] = value;
						}
						array3[j - 1] = value;
					}
					for (int k = 1; k + 1 < array3.Length; k++)
					{
						list7.Add(array3[0]);
						list7.Add(array3[k]);
						list7.Add(array3[k + 1]);
					}
					break;
				}
				}
			}
			Mesh val = new Mesh
			{
				name = name
			};
			if (list3.Count > 65000)
			{
				val.indexFormat = (IndexFormat)1;
			}
			val.SetVertices(list3);
			val.SetUVs(0, list4);
			val.subMeshCount = list5.Count;
			for (int l = 0; l < list5.Count; l++)
			{
				val.SetTriangles(list5[l], l);
			}
			val.RecalculateNormals();
			val.RecalculateBounds();
			materials = list6.ToArray();
			return val;
		}

		private static byte[] Read(string path)
		{
			if (_resources == null)
			{
				_resources = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
				string[] manifestResourceNames = Assembly.GetExecutingAssembly().GetManifestResourceNames();
				foreach (string text in manifestResourceNames)
				{
					string text2 = text.Replace('\\', '/');
					if (text2.StartsWith("ClanWars.Art/", StringComparison.OrdinalIgnoreCase))
					{
						_resources[text2.Substring("ClanWars.Art/".Length)] = text;
					}
				}
			}
			if (!_resources.TryGetValue(path, out var value))
			{
				return null;
			}
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(value);
			if (stream == null)
			{
				return null;
			}
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			return memoryStream.ToArray();
		}

		private static void Report(string path)
		{
			if (Missing.Add(path))
			{
				Log.Warn("Clan Wars art missing: " + path + " - a plain stand-in is used.");
			}
		}

		public static void Shutdown()
		{
			foreach (Sprite value in Sprites.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)value);
				}
			}
			Sprites.Clear();
			if ((Object)(object)_plain != (Object)null)
			{
				Texture2D texture = _plain.texture;
				Object.Destroy((Object)(object)_plain);
				if ((Object)(object)texture != (Object)null)
				{
					Object.Destroy((Object)(object)texture);
				}
				_plain = null;
			}
			foreach (Material value2 in Materials.Values)
			{
				if ((Object)(object)value2 != (Object)null)
				{
					Object.Destroy((Object)(object)value2);
				}
			}
			Materials.Clear();
			foreach (Mesh value3 in Meshes.Values)
			{
				if ((Object)(object)value3 != (Object)null)
				{
					Object.Destroy((Object)(object)value3);
				}
			}
			Meshes.Clear();
			MeshMaterials.Clear();
			foreach (Texture2D value4 in Textures.Values)
			{
				if ((Object)(object)value4 != (Object)null)
				{
					Object.Destroy((Object)(object)value4);
				}
			}
			Textures.Clear();
			Missing.Clear();
			_resources = null;
		}
	}
	public static class ClanOutpostFlag
	{
		public const string PrefabName = "ClanOutpostFlag";

		public const string DisplayName = "Clan Outpost Flag";

		public static readonly int Hash = StringExtensionMethods.GetStableHashCode("ClanOutpostFlag");

		private const float PoleHeight = 2.8f;

		private const float BannerTop = 0.88f;

		private const float BannerHeight = 0.45f;

		private const float ClothStrength = 1f;

		private static readonly FieldInfo NamedPrefabs = AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs");

		private static readonly MethodInfo LearnPieces = AccessTools.Method(typeof(Player), "UpdateKnownRecipesList", (Type[])null, (Type[])null);

		private static readonly string[] Poles = new string[6] { "SpearElderbark", "SpearBronze", "SpearFlint", "SpearChitin", "SpearCarapace", "SpearWolfFang" };

		private static readonly string[] Banners = new string[11]
		{
			"piece_banner01", "piece_banner02", "piece_banner03", "piece_banner11", "piece_banner04", "piece_banner05", "piece_banner06", "piece_banner07", "piece_banner08", "piece_banner09",
			"piece_banner10"
		};

		private static readonly string[] OwnPoleParts = new string[5] { "pole", "stick", "stang", "rod", "wood" };

		private static GameObject _holder;

		private static GameObject _prefab;

		private static readonly HashSet<Material> OwnedMaterials = new HashSet<Material>();

		private static ZNetScene _attemptedScene;

		private static ZNetScene _availableScene;

		private static bool _registrationCollision;

		private static bool _setupFailed;

		internal static bool IsAvailable
		{
			get
			{
				ZNetScene instance = ZNetScene.instance;
				if ((Object)(object)instance != (Object)null && _availableScene == instance && !_setupFailed)
				{
					return !_registrationCollision;
				}
				return false;
			}
		}

		internal static bool HasRegistrationCollision
		{
			get
			{
				ZNetScene instance = ZNetScene.instance;
				if ((Object)(object)instance != (Object)null && _attemptedScene == instance)
				{
					return _registrationCollision;
				}
				return false;
			}
		}

		public static bool Is(GameObject go)
		{
			if (IsAvailable && (Object)(object)go != (Object)null)
			{
				return Utils.GetPrefabName(go) == "ClanOutpostFlag";
			}
			return false;
		}

		public static void Setup()
		{
			ZNetScene instance = ZNetScene.instance;
			if ((Object)(object)instance == (Object)null || (_attemptedScene == instance && (_registrationCollision || _setupFailed)))
			{
				return;
			}
			bool flag = (Object)(object)_prefab != (Object)null;
			try
			{
				if (_attemptedScene != instance)
				{
					_attemptedScene = instance;
					_availableScene = null;
					_registrationCollision = false;
					_setupFailed = false;
				}
				if (FindCollision(instance, Hash, _prefab, out var foreign))
				{
					ReportCollision(foreign);
					_registrationCollision = true;
					UnregisterFrom(instance, _prefab);
					RemoveFromHammer(ObjectDB.instance, _prefab);
					return;
				}
				if ((Object)(object)_prefab == (Object)null)
				{
					Create(instance);
				}
				if ((Object)(object)_prefab == (Object)null)
				{
					_setupFailed = true;
					return;
				}
				if (!RegisterWith(instance))
				{
					UnregisterFrom(instance, _prefab);
					RemoveFromHammer(ObjectDB.instance, _prefab);
					return;
				}
				_availableScene = instance;
				ObjectDB instance2 = ObjectDB.instance;
				if ((Object)(object)instance2 != (Object)null && instance2.m_items != null && instance2.m_items.Count > 0)
				{
					MakeFree();
					AddToHammer(instance2);
					if ((Object)(object)Player.m_localPlayer != (Object)null)
					{
						Teach(Player.m_localPlayer);
					}
				}
			}
			catch (Exception ex)
			{
				try
				{
					UnregisterFrom(instance, _prefab);
				}
				catch (Exception ex2)
				{
					Log.Error(ex2.ToString());
				}
				try
				{
					RemoveFromHammer(ObjectDB.instance, _prefab);
				}
				catch (Exception ex3)
				{
					Log.Error(ex3.ToString());
				}
				if (!flag)
				{
					try
					{
						Shutdown();
					}
					catch (Exception ex4)
					{
						Log.Error(ex4.ToString());
					}
				}
				_attemptedScene = instance;
				_availableScene = null;
				_registrationCollision = false;
				_setupFailed = true;
				Log.Error("Could not set up the Clan Outpost Flag: " + ex);
			}
		}

		private static void Create(ZNetScene scene)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			GameObject prefab = scene.GetPrefab("guard_stone");
			if ((Object)(object)prefab == (Object)null)
			{
				Log.Warn("The vanilla Ward (guard_stone) was not found; the Clan Outpost Flag cannot be made.");
				return;
			}
			_holder = new GameObject("ClanWars_OutpostPrefabs");
			_holder.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)_holder);
			_prefab = Object.Instantiate<GameObject>(prefab, _holder.transform);
			((Object)_prefab).name = "ClanOutpostFlag";
			float num = Mathf.Max(1f, ModConfig.ClanOutpostFlagTerritoryClaim.Value);
			PrivateArea component = _prefab.GetComponent<PrivateArea>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_name = "Clan Outpost Flag";
				component.m_enabledByDefault = true;
				component.m_radius = num;
				if ((Object)(object)component.m_areaMarker != (Object)null)
				{
					component.m_areaMarker.m_radius = num;
					if (ClanWard.VanillaRadius > 0f)
					{
						component.m_areaMarker.m_nrOfSegments = Mathf.Clamp(Mathf.RoundToInt((float)component.m_areaMarker.m_nrOfSegments * num / ClanWard.VanillaRadius), 8, 400);
					}
				}
			}
			HideWard(_prefab);
			GameObject val = Raise(scene, _prefab);
			Piece component2 = _prefab.GetComponent<Piece>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.m_name = "Clan Outpost Flag";
				component2.m_description = "Claims a small camp for your clan, away from its Clan Ward. Only your clan may build inside it, and only so much.";
				component2.m_craftingStation = null;
				component2.m_enabled = true;
				Piece val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Piece>() : null);
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2.m_icon != (Object)null)
				{
					component2.m_icon = val2.m_icon;
				}
			}
			_prefab.AddComponent<WardColour>().Strength = 1f;
			Log.Info("Clan Outpost Flag prefab created.");
		}

		private static void HideWard(GameObject root)
		{
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (!((Object)(object)((Component)val).GetComponentInParent<CircleProjector>() != (Object)null))
				{
					val.enabled = false;
				}
			}
		}

		private static GameObject Raise(ZNetScene scene, GameObject root)
		{
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			string found;
			GameObject val = First(scene, Poles, out found);
			float num = 2.8f;
			if ((Object)(object)val != (Object)null)
			{
				Transform val2 = Borrow(val, root.transform, "Pole");
				if ((Object)(object)val2 != (Object)null)
				{
					num = Stand(root.transform, val2, 2.8f);
				}
			}
			string found2;
			GameObject val3 = First(scene, Banners, out found2);
			if ((Object)(object)val3 != (Object)null)
			{
				Transform val4 = Borrow(val3, root.transform, "Banner");
				if ((Object)(object)val4 != (Object)null)
				{
					DropOwnPole(val4);
					Bleach(val4);
					float num2 = Stand(root.transform, val4, num * 0.45f);
					val4.localPosition += new Vector3(0f, num * 0.88f - num2, 0f);
				}
			}
			Log.Info("Clan Outpost Flag: pole = " + (found ?? "none") + ", banner = " + (found2 ?? "none") + ".");
			return val3;
		}

		private static GameObject First(ZNetScene scene, string[] names, out string found)
		{
			foreach (string text in names)
			{
				GameObject prefab = scene.GetPrefab(text);
				if (!((Object)(object)prefab == (Object)null))
				{
					found = text;
					return prefab;
				}
			}
			found = null;
			return null;
		}

		private static Transform Borrow(GameObject source, Transform parent, string name)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			Transform val = source.transform.Find("attach") ?? source.transform;
			GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, parent);
			((Object)val2).name = name;
			val2.transform.localPosition = Vector3.zero;
			val2.transform.localRotation = Quaternion.identity;
			val2.transform.localScale = val.localScale;
			for (int i = 0; i < 2; i++)
			{
				Component[] componentsInChildren = val2.GetComponentsInChildren<Component>(true);
				foreach (Component val3 in componentsInChildren)
				{
					if (!((Object)(object)val3 == (Object)null) && !(val3 is Transform) && !(val3 is MeshFilter) && !(val3 is MeshRenderer) && !(val3 is SkinnedMeshRenderer) && !(val3 is LODGroup))
					{
						try
						{
							Object.DestroyImmediate((Object)(object)val3);
						}
						catch
						{
						}
					}
				}
			}
			Renderer[] componentsInChildren2 = val2.GetComponentsInChildren<Renderer>(true);
			for (int j = 0; j < componentsInChildren2.Length; j++)
			{
				componentsInChildren2[j].enabled = true;
			}
			return val2.transform;
		}

		private static void Bleach(Transform cloth)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected O, but got Unknown
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			if ((int)SystemInfo.graphicsDeviceType == 4)
			{
				return;
			}
			Renderer[] componentsInChildren = ((Component)cloth).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				Material[] sharedMaterials = val.sharedMaterials;
				if (sharedMaterials == null)
				{
					continue;
				}
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					Material val2 = sharedMaterials[j];
					if ((Object)(object)val2 == (Object)null || !val2.HasProperty("_MainTex"))
					{
						continue;
					}
					Texture2D val3 = ClanStyle.Drain(val2.GetTexture("_MainTex"), 1f, brighten: true);
					if (!((Object)(object)val3 == (Object)null))
					{
						Material val4 = new Material(val2);
						OwnedMaterials.Add(val4);
						((Object)val4).name = ((Object)val2).name + " (Clan)";
						val4.SetTexture("_MainTex", (Texture)(object)val3);
						if (val4.HasProperty("_Color"))
						{
							val4.SetColor("_Color", Color.white);
						}
						sharedMaterials[j] = val4;
					}
				}
				val.sharedMaterials = sharedMaterials;
			}
		}

		private static void DropOwnPole(Transform cloth)
		{
			Renderer[] componentsInChildren = ((Component)cloth).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				string text = ((Object)val).name.ToLowerInvariant();
				string[] ownPoleParts = OwnPoleParts;
				foreach (string value in ownPoleParts)
				{
					if (text.IndexOf(value, StringComparison.Ordinal) >= 0)
					{
						val.enabled = false;
						break;
					}
				}
			}
		}

		private static float Stand(Transform space, Transform model, float metres)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			Bounds val = Measure(model, model);
			if (((Bounds)(ref val)).size == Vector3.zero)
			{
				return metres;
			}
			Vector3 size = ((Bounds)(ref val)).size;
			model.localRotation = ((size.z >= size.x && size.z >= size.y) ? Quaternion.Euler(-90f, 0f, 0f) : ((size.x >= size.y) ? Quaternion.Euler(0f, 0f, -90f) : Quaternion.identity));
			Bounds val2 = Measure(space, model);
			if (((Bounds)(ref val2)).size.y > 0.001f)
			{
				model.localScale *= Mathf.Clamp(metres / ((Bounds)(ref val2)).size.y, 0.02f, 50f);
				val2 = Measure(space, model);
			}
			model.localPosition -= new Vector3(0f, ((Bounds)(ref val2)).min.y, 0f);
			return ((Bounds)(ref val2)).size.y;
		}

		private static Bounds Measure(Transform space, Transform model)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			bool any = false;
			Bounds total = default(Bounds);
			MeshFilter[] componentsInChildren = ((Component)model).GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val in componentsInChildren)
			{
				MeshRenderer component = ((Component)val).GetComponent<MeshRenderer>();
				if (!((Object)(object)val.sharedMesh == (Object)null) && !((Object)(object)component == (Object)null) && ((Renderer)component).enabled)
				{
					Add(space, ((Component)val).transform, val.sharedMesh.bounds, ref total, ref any);
				}
			}
			SkinnedMeshRenderer[] componentsInChildren2 = ((Component)model).GetComponentsInChildren<SkinnedMeshRenderer>(true);
			foreach (SkinnedMeshRenderer val2 in componentsInChildren2)
			{
				if (!((Object)(object)val2.sharedMesh == (Object)null) && ((Renderer)val2).enabled)
				{
					Add(space, ((Component)val2).transform, val2.sharedMesh.bounds, ref total, ref any);
				}
			}
			if (!any)
			{
				return default(Bounds);
			}
			return total;
		}

		private static void Add(Transform space, Transform of, Bounds local, ref Bounds total, ref bool any)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_0051: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			Matrix4x4 val = space.worldToLocalMatrix * of.localToWorldMatrix;
			Vector3 center = ((Bounds)(ref local)).center;
			Vector3 extents = ((Bounds)(ref local)).extents;
			for (int i = 0; i < 8; i++)
			{
				Vector3 val2 = ((Matrix4x4)(ref val)).MultiplyPoint3x4(new Vector3(center.x + (((i & 1) == 0) ? (0f - extents.x) : extents.x), center.y + (((i & 2) == 0) ? (0f - extents.y) : extents.y), center.z + (((i & 4) == 0) ? (0f - extents.z) : extents.z)));
				if (!any)
				{
					total = new Bounds(val2, Vector3.zero);
					any = true;
				}
				else
				{
					((Bounds)(ref total)).Encapsulate(val2);
				}
			}
		}

		private static bool RegisterWith(ZNetScene scene)
		{
			if (FindCollision(scene, Hash, _prefab, out var foreign))
			{
				ReportCollision(foreign);
				_registrationCollision = true;
				return false;
			}
			if (!(NamedPrefabs?.GetValue(scene) is Dictionary<int, GameObject> dictionary))
			{
				throw new InvalidOperationException("ZNetScene.m_namedPrefabs is unavailable.");
			}
			bool flag = false;
			bool flag2 = false;
			try
			{
				if (!scene.m_prefabs.Contains(_prefab))
				{
					scene.m_prefabs.Add(_prefab);
					flag = true;
				}
				if (!dictionary.TryGetValue(Hash, out var value) || (Object)(object)value == (Object)null)
				{
					dictionary[Hash] = _prefab;
					flag2 = true;
				}
				return true;
			}
			catch
			{
				if (flag2 && dictionary.TryGetValue(Hash, out var value2) && value2 == _prefab)
				{
					dictionary.Remove(Hash);
				}
				if (flag)
				{
					scene.m_prefabs.Remove(_prefab);
				}
				throw;
			}
		}

		private static bool FindCollision(ZNetScene scene, int hash, GameObject owned, out GameObject foreign)
		{
			foreign = null;
			if (NamedPrefabs?.GetValue(scene) is Dictionary<int, GameObject> dictionary && dictionary.TryGetValue(hash, out var value) && (Object)(object)value != (Object)null && value != owned)
			{
				foreign = value;
				return true;
			}
			foreach (GameObject prefab in scene.m_prefabs)
			{
				if (!((Object)(object)prefab == (Object)null) && prefab != owned && StringExtensionMethods.GetStableHashCode(((Object)prefab).name) == hash)
				{
					foreign = prefab;
					return true;
				}
			}
			return false;
		}

		private static void ReportCollision(GameObject foreign)
		{
			Log.Error("Prefab registration collision: feature='Clan Outpost Flag', prefab='ClanOutpostFlag', hash=" + Hash + ", foreign='" + (((Object)(object)foreign != (Object)null) ? ((Object)foreign).name : "<destroyed>") + "'. Clan Outpost Flag is disabled for this world.");
		}

		private static void UnregisterFrom(ZNetScene scene, GameObject prefab)
		{
			if (!((Object)(object)scene == (Object)null) && !((Object)(object)prefab == (Object)null))
			{
				scene.m_prefabs.Remove(prefab);
				if (NamedPrefabs?.GetValue(scene) is Dictionary<int, GameObject> dictionary && dictionary.TryGetValue(Hash, out var value) && value == prefab)
				{
					dictionary.Remove(Hash);
				}
			}
		}

		private static void RemoveFromHammer(ObjectDB db, GameObject prefab)
		{
			if (!((Object)(object)db == (Object)null) && !((Object)(object)prefab == (Object)null))
			{
				GameObject itemPrefab = db.GetItemPrefab("Hammer");
				PieceTable val = ((!((Object)(object)itemPrefab != (Object)null)) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_buildPieces);
				if ((Object)(object)val != (Object)null)
				{
					val.m_pieces.Remove(prefab);
				}
			}
		}

		public static void Shutdown()
		{
			GameObject prefab = _prefab;
			UnregisterFrom(ZNetScene.instance, prefab);
			RemoveFromHammer(ObjectDB.instance, prefab);
			if ((Object)(object)_holder != (Object)null)
			{
				Object.Destroy((Object)(object)_holder);
			}
			_holder = null;
			_prefab = null;
			_attemptedScene = null;
			_availableScene = null;
			_registrationCollision = false;
			_setupFailed = false;
			foreach (Material ownedMaterial in OwnedMaterials)
			{
				if ((Object)(object)ownedMaterial != (Object)null)
				{
					Object.Destroy((Object)(object)ownedMaterial);
				}
			}
			OwnedMaterials.Clear();
		}

		private static void AddToHammer(ObjectDB db)
		{
			GameObject itemPrefab = db.GetItemPrefab("Hammer");
			PieceTable val = ((!((Object)(object)itemPrefab != (Object)null)) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_buildPieces);
			if ((Object)(object)val == (Object)null)
			{
				Log.Warn("The Hammer's build table was not found; the Clan Outpost Flag is not in the build menu.");
			}
			else if (!val.m_pieces.Contains(_prefab))
			{
				val.m_pieces.Add(_prefab);
			}
		}

		private static void MakeFree()
		{
			Piece component = _prefab.GetComponent<Piece>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_resources = (Requirement[])(object)new Requirement[0];
			}
		}

		public static void Teach(Player player)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)_prefab == (Object)null || LearnPieces == null)
			{
				return;
			}
			try
			{
				LearnPieces.Invoke(player, null);
			}
			catch (Exception ex)
			{
				Log.Debug("Could not teach the Clan Outpost Flag: " + ex.Message);
			}
		}

		public static string SpawnRefusal(float metres)
		{
			return "A Clan Outpost must be at least " + Mathf.RoundToInt(metres) + " m from the world spawn, every boss altar and every trader.";
		}

		public static bool SpacingLooksOk(Vector3 at, out string why)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			why = null;
			ClanClient instance = ClanClient.Instance;
			ClanStateView state = instance.State;
			SyncConfig rules = instance.Rules;
			float outpostFriendlyWardDistance = rules.outpostFriendlyWardDistance;
			float outpostEnemyWardDistance = rules.outpostEnemyWardDistance;
			float num = Mathf.Max(1f, rules.outpostRadius) * 2f;
			float num2 = Mathf.Max(0f, rules.spawnOutpostDistance);
			if (num2 > 0f)
			{
				bool flag = rules.spawnKnown && Flat(rules.spawnX, rules.spawnZ, at) < num2;
				foreach (SyncPoint item in state.keepAway)
				{
					flag |= Flat(item.x, item.z, at) < num2;
				}
				if (flag)
				{
					why = SpawnRefusal(num2);
					return false;
				}
			}
			float num3 = Mathf.Max(1f, rules.outpostRadius) + MoshpitBattles.ShieldReach;
			foreach (SyncMoshpit item2 in instance.AllMoshpits())
			{
				if (Flat(item2.x, item2.z, at) < num3)
				{
					why = "A Clan Outpost must be at least " + Mathf.RoundToInt(num3) + " m from a moshpit, so its ground stays clear of the moshpit's shield.";
					return false;
				}
			}
			foreach (UiWard ownWard in state.ownWards)
			{
				if (Flat(ownWard.x, ownWard.z, at) < outpostFriendlyWardDistance)
				{
					why = "A Clan Outpost must be at least " + Mathf.RoundToInt(outpostFriendlyWardDistance) + " m from your clan's own Clan Wards.";
					return false;
				}
			}
			foreach (SyncClaim claim in state.claims)
			{
				if (claim.clanId != state.clanId && Flat(claim.x, claim.z, at) < outpostEnemyWardDistance)
				{
					why = "A Clan Outpost must be at least " + Mathf.RoundToInt(outpostEnemyWardDistance) + " m from another clan's Clan Ward.";
					return false;
				}
			}
			foreach (UiRaidTarget raidTarget in state.raidTargets)
			{
				float num4 = (raidTarget.onOutpost ? num : outpostEnemyWardDistance);
				if (!(Flat(raidTarget.x, raidTarget.z, at) >= num4))
				{
					why = (raidTarget.onOutpost ? ("Another Clan Outpost is too close. Camps must be at least " + Mathf.RoundToInt(num) + " m apart.") : ("A Clan Outpost must be at least " + Mathf.RoundToInt(outpostEnemyWardDistance) + " m from another clan's Clan Ward."));
					return false;
				}
			}
			foreach (SyncOutpost outpost in state.outposts)
			{
				if (Flat(outpost.x, outpost.z, at) < num)
				{
					why = "Another Clan Outpost is too close. Camps must be at least " + Mathf.RoundToInt(num) + " m apart.";
					return false;
				}
			}
			int num5 = state.ownWards.Count * Mathf.Max(0, rules.outpostsPerWard);
			int num6 = 0;
			foreach (SyncOutpost outpost2 in state.outposts)
			{
				if (outpost2.clanId == state.clanId)
				{
					num6++;
				}
			}
			if (num6 >= num5)
			{
				why = ((num5 == 0) ? "Your clan holds no Clan Ward. Raise one before you camp away from home." : ("Your clan already holds " + num5 + " Clan Outposts - " + Mathf.Max(0, rules.outpostsPerWard) + " for every Clan Ward it keeps."));
				return false;
			}
			return true;
		}

		private static float Flat(float x, float z, Vector3 at)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			float num = x - at.x;
			float num2 = z - at.z;
			return Mathf.Sqrt(num * num + num2 * num2);
		}

		public static string HoverText(PrivateArea area)
		{
			//IL_000c: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			ClanClient instance = ClanClient.Instance;
			Vector3 position = ((Component)area).transform.position;
			SyncOutpost syncOutpost = null;
			foreach (SyncOutpost outpost in instance.State.outposts)
			{
				float num = outpost.x - position.x;
				float num2 = outpost.z - position.z;
				if (num * num + num2 * num2 < 4f)
				{
					syncOutpost = outpost;
					break;
				}
			}
			string text = LocalizationRuntime.Render("Clan Outpost Flag");
			SyncClan syncClan = ((syncOutpost != null) ? instance.ClanById(syncOutpost.clanId) : null);
			if (syncClan == null)
			{
				return text + "\n" + LocalizationRuntime.Render("<color=#9A8C74>Claims no land</color>");
			}
			SyncClan syncClan2 = instance.MyClan();
			string value = ((syncClan2 != null && syncClan2.id == syncClan.id) ? "#7CFC00" : ((syncClan2 != null && syncClan2.allies.Contains(syncClan.id)) ? "#7FD8FF" : "#FF6060"));
			string text2 = text + (string.IsNullOrEmpty(syncOutpost.name) ? "" : (" - " + syncOutpost.name)) + "\n" + LocalizationRuntime.FormatText("ui.hover.owner_literal", "Owner: <color={colour}>[{clan_tag}] {clan_name}</color>", new Dictionary<string, string>
			{
				["colour"] = value,
				["clan_tag"] = syncClan.tag,
				["clan_name"] = syncClan.name
			});
			if (syncClan2 != null && syncClan2.id == syncClan.id)
			{
				text2 = text2 + "\n" + LocalizationRuntime.FormatText("ui.hover.built_literal", "Built: {pieces} / {limit}", new Dictionary<string, string>
				{
					["pieces"] = syncOutpost.pieces.ToString(CultureInfo.InvariantCulture),
					["limit"] = instance.Rules.outpostPieceLimit.ToString(CultureInfo.InvariantCulture)
				});
			}
			return text2;
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	public static class ZNetScene_Awake_OutpostFlag
	{
		private static void Postfix()
		{
			ClanOutpostFlag.Setup();
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	public static class ObjectDB_Awake_OutpostFlag
	{
		private static void Postfix()
		{
			ClanOutpostFlag.Setup();
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
	public static class ObjectDB_CopyOtherDB_OutpostFlag
	{
		private static void Postfix()
		{
			ClanOutpostFlag.Setup();
		}
	}
	[HarmonyPatch(typeof(PrivateArea), "Awake")]
	public static class PrivateArea_Awake_OutpostFlag
	{
		private static void Postfix(PrivateArea __instance)
		{
			if (ClanOutpostFlag.Is(((Component)__instance).gameObject))
			{
				float radius = (__instance.m_radius = Mathf.Max(1f, ClanClient.Instance.Rules.outpostRadius));
				if ((Object)(object)__instance.m_areaMarker != (Object)null)
				{
					__instance.m_areaMarker.m_radius = radius;
				}
				ClanWard.Adopt(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(PrivateArea), "GetHoverText")]
	public static class PrivateArea_GetHoverText_OutpostFlag
	{
		private static void Postfix(PrivateArea __instance, ref string __result)
		{
			if (ClanOutpostFlag.Is(((Component)__instance).gameObject))
			{
				__result = ClanOutpostFlag.HoverText(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(PrivateArea), "Interact")]
	public static class PrivateArea_Interact_OutpostFlag
	{
		private static bool Prefix(PrivateArea __instance, ref bool __result)
		{
			if (!ClanOutpostFlag.Is(((Component)__instance).gameObject))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(Player), "TryPlacePiece")]
	public static class Player_TryPlacePiece_OutpostFlag
	{
		private static bool Prefix(Player __instance, Piece piece, ref bool __result)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)piece == (Object)null || !ClanOutpostFlag.Is(((Component)piece).gameObject))
			{
				return true;
			}
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return true;
			}
			string text = null;
			string why;
			if (ClanClient.Instance.MyClan() == null)
			{
				text = "Join a clan to raise a Clan Outpost Flag";
			}
			else if (!ClanOutpostFlag.SpacingLooksOk(BuildTerritory.PlacementPoint(__instance, piece), out why))
			{
				text = why;
			}
			if (text == null)
			{
				return true;
			}
			Compat.ShowCenterMessage(text);
			__result = false;
			return false;
		}
	}
	public static class ClanWard
	{
		public const string PrefabName = "ClanWard";

		public const string DisplayName = "Clan Ward";

		public const string FeatherStoreName = "Clan Ward Feathers";

		public const int FeatherSlots = 5;

		public static readonly int Hash = StringExtensionMethods.GetStableHashCode("ClanWard");

		private static readonly Color Blue = new Color(0.16f, 0.4f, 0.88f, 1f);

		private const float Scale = 2f;

		private const float HealthFactor = 2f;

		private static readonly FieldInfo NamedPrefabs = AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs");

		private static readonly MethodInfo LearnPieces = AccessTools.Method(typeof(Player), "UpdateKnownRecipesList", (Type[])null, (Type[])null);

		public static float VanillaRadius = 32f;

		private static float _flashRadius;

		private static readonly MethodInfo CloneM = typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo AllAreas = AccessTools.Field(typeof(PrivateArea), "m_allAreas");

		private static readonly MethodInfo FlashShieldM = AccessTools.Method(typeof(PrivateArea), "FlashShield", (Type[])null, (Type[])null);

		public static readonly List<PrivateArea> Areas = new List<PrivateArea>();

		private static GameObject _holder;

		private static GameObject _prefab;

		private static readonly HashSet<Object> OwnedAssets = new HashSet<Object>();

		private static ZNetScene _attemptedScene;

		private static ZNetScene _availableScene;

		private static bool _registrationCollision;

		private static bool _setupFailed;

		private static readonly FieldInfo GhostF = AccessTools.Field(typeof(Player), "m_placementGhost");

		private static bool _spawnFound;

		private static Vector3 _spawn;

		internal static bool IsAvailable
		{
			get
			{
				ZNetScene instance = ZNetScene.instance;
				if ((Object)(object)instance != (Object)null && _availableScene == instance && !_setupFailed)
				{
					return !_registrationCollision;
				}
				return false;
			}
		}

		internal static bool HasRegistrationCollision
		{
			get
			{
				ZNetScene instance = ZNetScene.instance;
				if ((Object)(object)instance != (Object)null && _attemptedScene == instance)
				{
					return _registrationCollision;
				}
				return false;
			}
		}

		public static void Adopt(PrivateArea area)
		{
			if (AllAreas?.GetValue(null) is List<PrivateArea> list)
			{
				list.Remove(area);
			}
			if (!Areas.Contains(area))
			{
				Areas.Add(area);
			}
		}

		public static bool Is(GameObject go)
		{
			if (IsAvailable && (Object)(object)go != (Object)null)
			{
				return Utils.GetPrefabName(go) == "ClanWard";
			}
			return false;
		}

		public static void ApplyRadii()
		{
			SyncConfig rules = ClanClient.Instance.Rules;
			foreach (PrivateArea area in Areas)
			{
				if ((Object)(object)area == (Object)null)
				{
					continue;
				}
				float num = (Is(((Component)area).gameObject) ? rules.claimRadius : (ClanOutpostFlag.Is(((Component)area).gameObject) ? rules.outpostRadius : 0f));
				if (!(num <= 0f) && !Mathf.Approximately(area.m_radius, num))
				{
					area.m_radius = num;
					if ((Object)(object)area.m_areaMarker != (Object)null)
					{
						area.m_areaMarker.m_radius = num;
					}
				}
			}
		}

		public static bool SpacingLooksOk(ClanStateView state, out string why)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: 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_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			why = null;
			GameObject val = (GameObject)(((Object)(object)Player.m_localPlayer != (Object)null && GhostF != null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			Vector3 position = val.transform.position;
			SyncConfig rules = ClanClient.Instance.Rules;
			if (rules.spawnKnown && rules.spawnWardDistance > 0f && Flat(rules.spawnX, rules.spawnZ, position) < rules.spawnWardDistance)
			{
				why = SpawnRefusal(rules.spawnWardDistance);
				return false;
			}
			foreach (SyncPoint item in state.keepAway)
			{
				if (rules.spawnWardDistance > 0f && Flat(item.x, item.z, position) < rules.spawnWardDistance)
				{
					why = SpawnRefusal(rules.spawnWardDistance);
					return false;
				}
			}
			float num = Mathf.Max(1f, rules.claimRadius) + MoshpitBattles.ShieldReach;
			foreach (SyncMoshpit item2 in ClanClient.Instance.AllMoshpits())
			{
				if (Flat(item2.x, item2.z, position) < num)
				{
					why = "A Clan Ward must be at least " + Mathf.RoundToInt(num) + " m from a moshpit, so its land stays clear of the moshpit's shield.";
					return false;
				}
			}
			string text = "Another Clan Ward is too close. Friendly Wards must be at least " + Mathf.RoundToInt(rules.friendlyWardDistance) + " m apart.";
			string text2 = "Clan Ward cannot be placed here because another Clan Ward is too close.";
			foreach (UiWard ownWard in state.ownWards)
			{
				if (Flat(ownWard.x, ownWard.z, position) < rules.friendlyWardDistance)
				{
					why = text;
					return false;
				}
			}
			foreach (SyncClaim claim in state.claims)
			{
				if (claim.clanId != state.clanId && Flat(claim.x, claim.z, position) < rules.otherWardDistance)
				{
					why = text2;
					return false;
				}
			}
			foreach (UiRaidTarget raidTarget in state.raidTargets)
			{
				float num2 = (raidTarget.onOutpost ? rules.outpostEnemyWardDistance : rules.otherWardDistance);
				if (!(Flat(raidTarget.x, raidTarget.z, position) >= num2))
				{
					why = (raidTarget.onOutpost ? ("A Clan Ward must be at least " + Mathf.RoundToInt(num2) + " m from another clan's Clan Outpost.") : text2);
					return false;
				}
			}
			foreach (SyncOutpost outpost in state.outposts)
			{
				bool flag = outpost.clanId == state.clanId;
				float num3 = (flag ? rules.outpostFriendlyWardDistance : rules.outpostEnemyWardDistance);
				if (!(Flat(outpost.x, outpost.z, position) >= num3))
				{
					why = "A Clan Ward must be at least " + Mathf.RoundToInt(num3) + " m from " + (flag ? "your own Clan Outposts." : "another clan's Clan Outpost.");
					return false;
				}
			}
			return true;
		}

		public static void Flash(SyncClaim claim)
		{
			if (claim != null)
			{
				FlashAt(claim.x, claim.z, Is);
			}
		}

		public static void Flash(SyncOutpost post)
		{
			if (post != null)
			{
				FlashAt(post.x, post.z, ClanOutpostFlag.Is);
			}
		}

		private static void FlashAt(float x, float z, Func<GameObject, bool> mine)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			if (FlashShieldM == null)
			{
				return;
			}
			foreach (PrivateArea area in Areas)
			{
				if (!((Object)(object)area == (Object)null) && mine(((Component)area).gameObject) && !(Flat(x, z, ((Component)area).transform.position) > 2f))
				{
					FlashShieldM.Invoke(area, new object[1] { false });
					break;
				}
			}
		}

		public static void FlashScaled(PrivateArea area)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)area == (Object)null || area.m_flashEffect == null)
			{
				return;
			}
			GameObject[] array = area.m_flashEffect.Create(((Component)area).transform.position, Quaternion.identity, (Transform)null, 1f, -1, new ZDOID(0L, 0u));
			if (array != null && !(_flashRadius <= 0f) && !(Mathf.Abs(area.m_radius - _flashRadius) < 0.5f))
			{
				GameObject[] array2 = array;
				foreach (GameObject go in array2)
				{
					Enlarge(go, area.m_radius / _flashRadius);
					HearAcross(go, area.m_radius);
				}
			}
		}

		private static EffectList ClaimFlash(EffectList source, float radius)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			float scale = ((VanillaRadius > 0f) ? Mathf.Max(1f, radius / VanillaRadius) : 1f);
			EffectData[] array = (EffectData[])(((object)source.m_effectPrefabs) ?? ((object)new EffectData[0]));
			EffectList val = new EffectList
			{
				m_effectPrefabs = (EffectData[])(object)new EffectData[array.Length]
			};
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i] != null)
				{
					EffectData val2 = (EffectData)CloneM.Invoke(array[i], null);
					if ((Object)(object)val2.m_prefab != (Object)null)
					{
						GameObject val3 = Object.Instantiate<GameObject>(val2.m_prefab, _holder.transform);
						((Object)val3).name = ((Object)val2.m_prefab).name;
						Tint(val3);
						Enlarge(val3, scale);
						HearAcross(val3, radius);
						val2.m_prefab = val3;
					}
					val.m_effectPrefabs[i] = val2;
				}
			}
			return val;
		}

		private static void HearAcross(GameObject go, float radius)
		{
			AudioSource[] componentsInChildren = go.GetComponentsInChildren<AudioSource>(true);
			foreach (AudioSource obj in componentsInChildren)
			{
				obj.rolloffMode = (AudioRolloffMode)1;
				obj.minDistance = radius * 0.5f;
				obj.maxDistance = radius * 1.25f;
			}
		}

		public static bool UnderRaid(Component c)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			ZNetView val = (((Object)(object)c != (Object)null) ? c.GetComponent<ZNetView>() : null);
			if ((Object)(object)val == (Object)null || !val.IsValid() || ClanClient.Instance == null)
			{
				return false;
			}
			ZDOID uid = val.GetZDO().m_uid;
			return ClanClient.Instance.ActiveRaidOnWard(((ZDOID)(ref uid)).UserID, ((ZDOID)(ref uid)).ID) != null;
		}

		private static void Enlarge(GameObject go, float scale)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)go == (Object)null) && !Mathf.Approximately(scale, 1f))
			{
				Transform transform = go.transform;
				transform.localScale *= scale;
				ParticleSystem[] componentsInChildren = go.GetComponentsInChildren<ParticleSystem>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					MainModule main = componentsInChildren[i].main;
					((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)0;
				}
				AudioSource[] componentsInChildren2 = go.GetComponentsInChildren<AudioSource>(true);
				foreach (AudioSource obj in componentsInChildren2)
				{
					obj.minDistance *= scale;
					obj.maxDistance *= scale;
				}
				Light[] componentsInChildren3 = go.GetComponentsInChildren<Light>(true);
				foreach (Light obj2 in componentsInChildren3)
				{
					obj2.range *= scale;
				}
			}
		}

		public static string HoverText(PrivateArea area)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			ClanClient instance = ClanClient.Instance;
			Vector3 at = ((Component)area).transform.position;
			SyncClaim syncClaim = null;
			foreach (SyncClaim claim in instance.State.claims)
			{
				if (Flat(claim.x, claim.z, at) < 2f)
				{
					syncClaim = claim;
					break;
				}
			}
			string text = LocalizationRuntime.Render("Clan Ward");
			SyncClan syncClan = ((syncClaim != null) ? instance.ClanById(syncClaim.clanId) : null);
			if (syncClan == null)
			{
				return text + "\n" + LocalizationRuntime.Render("<color=#9A8C74>Claims no land</color>");
			}
			SyncClan syncClan2 = instance.MyClan();
			string value = ((syncClan2 != null && syncClan2.id == syncClan.id) ? "#7CFC00" : ((syncClan2 != null && syncClan2.allies.Contains(syncClan.id)) ? "#7FD8FF" : "#FF6060"));
			string value2 = string.Join(", ", syncClan.members.Select((SyncMember m) => Names.Caps(m.name)).ToArray());
			UiWard uiWard = instance.State.ownWards.FirstOrDefault((UiWard w) => Flat(w.x, w.z, at) < 2f);
			string text2 = text + ((uiWard != null && !string.IsNullOrEmpty(uiWard.name)) ? (" - " + uiWard.name) : "") + "\n" + LocalizationRuntime.FormatText("ui.hover.owner_literal", "Owner: <color={colour}>[{clan_tag}] {clan_name}</color>", new Dictionary<string, string>
			{
				["colour"] = value,
				["clan_tag"] = syncClan.tag,
				["clan_name"] = syncClan.name
			}) + "\n" + LocalizationRuntime.FormatText("ui.hover.members_literal", "Members: {members}", new Dictionary<string, string> { ["members"] = value2 });
			if (syncClan2 != null && syncClan2.id == syncClan.id)
			{
				text2 = text2 + "\n" + LocalizationRuntime.FormatText("ui.hover.scout_feathers_literal", "[<color=yellow><b>{binding}</b></color>] Feathers for Scout Ravens: {count}", new Dictionary<string, string>
				{
					["binding"] = LocalizationRuntime.LocalizeBindings("$KEY_Use"),
					["count"] = Feathers(area).ToString(CultureInfo.InvariantCulture)
				});
			}
			return text2;
		}

		private static int Feathers(PrivateArea area)
		{
			Container val = (((Object)(object)area != (Object)null) ? ((Component)area).GetComponent<Container>() : null);
			Inventory val2 = (((Object)(object)val != (Object)null) ? val.GetInventory() : null);
			if (val2 == null)
			{
				return 0;
			}
			int num = 0;
			foreach (ItemData allItem in val2.GetAllItems())
			{
				if (IsFeather(allItem))
				{
					num += allItem.m_stack;
				}
			}
			return num;
		}

		public static bool IsFeather(ItemData item)
		{
			if (item == null)
			{
				return false;
			}
			string text = ClanClient.Instance.State.ravenFeatherItem;
			if (string.IsNullOrEmpty(text))
			{
				text = ModConfig.RavenFeatherItem.Value;
			}
			if ((Object)(object)item.m_dropPrefab != (Object)null)
			{
				return string.Equals(((Object)item.m_dropPrefab).name, text, StringComparison.OrdinalIgnoreCase);
			}
			GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(text) : null);
			ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null);
			if ((Object)(object)val2 != (Object)null && item.m_shared != null)
			{
				return item.m_shared.m_name == val2.m_itemData.m_shared.m_name;
			}
			return false;
		}

		public static bool RefusesItem(Inventory inv, ItemData item)
		{
			if (inv == null || item == null || inv.GetName() != "Clan Ward Feathers")
			{
				return false;
			}
			if (IsFeather(item))
			{
				return false;
			}
			Compat.ShowCenterMessage("The Clan Ward's store takes only " + ClanClient.Instance.State.ravenFeatherItem + ".");
			return true;
		}

		public static string SpawnRefusal(float metres)
		{
			return "Clan Ward cannot be placed here. Wards must be at least " + Mathf.RoundToInt(metres) + " m from the world spawn, every boss altar and every trader.";
		}

		public static bool WorldSpawn(out Vector3 spawn)
		{
			//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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			spawn = _spawn;
			if (_spawnFound)
			{
				return true;
			}
			ZoneSystem instance = ZoneSystem.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			try
			{
				LocationInstance val = default(LocationInstance);
				if (instance.FindClosestLocation("StartTemple", Vector3.zero, ref val))
				{
					_spawn = val.m_position;
				}
				else if (!instance.GetLocationIcon("StartTemple", ref _spawn))
				{
					return false;
				}
			}
			catch
			{
				return false;
			}
			_spawnFound = true;
			spawn = _spawn;
			return true;
		}

		public static void ForgetSpawn()
		{
			_spawnFound = false;
		}

		private static float Flat(float x, float z, Vector3 at)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			float num = x - at.x;
			float num2 = z - at.z;
			return Mathf.Sqrt(num * num + num2 * num2);
		}

		public static void Setup()
		{
			ZNetScene instance = ZNetScene.instance;
			if ((Object)(object)instance == (Object)null || (_attemptedScene == instance && (_registrationCollision || _setupFailed)))
			{
				return;
			}
			bool flag = (Object)(object)_prefab != (Object)null;
			try
			{
				if (_attemptedScene != instance)
				{
					_attemptedScene = instance;
					_availableScene = null;
					_registrationCollision = false;
					_setupFailed = false;
				}
				if (FindCollision(instance, Hash, _prefab, out var foreign))
				{
					ReportCollision("ClanWard", Hash, foreign);
					_registrationCollision = true;
					UnregisterFrom(instance, _prefab);
					RemoveFromHammer(ObjectDB.instance, _prefab);
					return;
				}
				if ((Object)(object)_prefab == (Object)null)
				{
					Create(instance);
				}
				if ((Object)(object)_prefab == (Object)null)
				{
					_setupFailed = true;
					return;
				}
				if (!RegisterWith(instance))
				{
					UnregisterFrom(instance, _prefab);
					RemoveFromHammer(ObjectDB.instance, _prefab);
					return;
				}
				_availableScene = instance;
				ObjectDB instance2 = ObjectDB.instance;
				if ((Object)(object)instance2 != (Object)null && instance2.m_items != null && instance2.m_items.Count > 0)
				{
					MakeFree();
					AddToHammer(instance2);
					if ((Object)(object)Player.m_localPlayer != (Object)null)
					{
						Teach(Player.m_localPlayer);
					}
				}
			}
			catch (Exception ex)
			{
				try
				{
					UnregisterFrom(instance, _prefab);
				}
				catch (Exception ex2)
				{
					Log.Error(ex2.ToString());
				}
				try
				{
					RemoveFromHammer(ObjectDB.instance, _prefab);
				}
				catch (Exception ex3)
				{
					Log.Error(ex3.ToString());
				}
				if (!flag)
				{
					try
					{
						Shutdown();
					}
					catch (Exception ex4)
					{
						Log.Error(ex4.ToString());
					}
				}
				_attemptedScene = instance;
				_availableScene = null;
				_registrationCollision = false;
				_setupFailed = true;
				Log.Error("Could not set up the Clan Ward: " + ex);
			}
		}

		private static void Create(ZNetScene scene)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Expected O, but got Unknown
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = scene.GetPrefab("guard_stone");
			if ((Object)(object)prefab == (Object)null)
			{
				Log.Warn("The vanilla Ward (guard_stone) was not found; the Clan Ward cannot be made.");
				return;
			}
			_holder = new GameObject("ClanWars_Prefabs");
			_holder.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)_holder);
			_prefab = Object.Instantiate<GameObject>(prefab, _holder.transform);
			((Object)_prefab).name = "ClanWard";
			Piece component = _prefab.GetComponent<Piece>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_name = "Clan Ward";
				component.m_description = "Claims the land around it for your clan. Rivals cannot build, dig or break anything inside it except during a raid on this Ward.";
				component.m_craftingStation = null;
				component.m_enabled = true;
				component.m_icon = TintIcon(component.m_icon);
			}
			PrivateArea component2 = _prefab.GetComponent<PrivateArea>();
			if ((Object)(object)component2 != (Object)null)
			{
				if (component2.m_radius > 0f)
				{
					VanillaRadius = component2.m_radius;
				}
				component2.m_name = "Clan Ward";
				component2.m_enabledByDefault = true;
				component2.m_radius = Mathf.Max(1f, ModConfig.WardClaimRadius.Value);
				if ((Object)(object)component2.m_areaMarker != (Object)null && (Object)(object)component2.m_areaMarker.m_prefab != (Object)null)
				{
					component2.m_areaMarker.m_prefab = TintedCopy(component2.m_areaMarker.m_prefab);
				}
				if ((Object)(object)component2.m_areaMarker != (Object)null && VanillaRadius > 0f)
				{
					component2.m_areaMarker.m_nrOfSegments = Mathf.Clamp(Mathf.RoundToInt((float)component2.m_areaMarker.m_nrOfSegments * component2.m_radius / VanillaRadius), 8, 400);
				}
				if (component2.m_flashEffect != null)
				{
					component2.m_flashEffect = ClaimFlash(component2.m_flashEffect, component2.m_radius);
					_flashRadius = component2.m_radius;
				}
			}
			WearNTear component3 = _prefab.GetComponent<WearNTear>();
			if ((Object)(object)component3 != (Object)null)
			{
				component3.m_health *= 2f;
			}
			Tint(_prefab);
			ScaleUp(_prefab, 2f);
			_prefab.AddComponent<WardColour>();
			Container val = _prefab.GetComponent<Container>() ?? _prefab.AddComponent<Container>();
			GameObject prefab2 = scene.GetPrefab("piece_chest_wood");
			Container val2 = (((Object)(object)prefab2 != (Object)null) ? prefab2.GetComponent<Container>() : null);
			val.m_name = "Clan Ward Feathers";
			val.m_width = 5;
			val.m_height = 1;
			val.m_privacy = (PrivacySetting)2;
			val.m_checkGuardStone = true;
			val.m_autoDestroyEmpty = false;
			val.m_defaultItems = new DropTable();
			val.m_openEffects = (EffectList)(((Object)(object)val2 != (Object)null) ? ((object)val2.m_openEffects) : ((object)new EffectList()));
			val.m_closeEffects = (EffectList)(((Object)(object)val2 != (Object)null) ? ((object)val2.m_closeEffects) : ((object)new EffectList()));
			if ((Object)(object)val2 != (Object)null)
			{
				val.m_bkg = val2.m_bkg;
			}
			Log.Info("Clan Ward prefab created.");
		}

		private static bool RegisterWith(ZNetScene scene)
		{
			if (FindCollision(scene, Hash, _prefab, out var foreign))
			{
				ReportCollision("ClanWard", Hash, foreign);
				_registrationCollision = true;
				return false;
			}
			if (!(NamedPrefabs?.GetValue(scene) is Dictionary<int, GameObject> dictionary))
			{
				throw new InvalidOperationException("ZNetScene.m_namedPrefabs is unavailable.");
			}
			bool flag = false;
			bool flag2 = false;
			try
			{
				if (!scene.m_prefabs.Contains(_prefab))
				{
					scene.m_prefabs.Add(_prefab);
					flag = true;
				}
				if (!dictionary.TryGetValue(Hash, out var value) || (Object)(object)value == (Object)null)
				{
					dictionary[Hash] = _prefab;
					flag2 = true;
				}
				return true;
			}
			catch
			{
				if (flag2 && dictionary.TryGetValue(Hash, out var value2) && value2 == _prefab)
				{
					dictionary.Remove(Hash);
				}
				if (flag)
				{
					scene.m_prefabs.Remove(_prefab);
				}
				throw;
			}
		}

		private static bool FindCollision(ZNetScene scene, int hash, GameObject owned, out GameObject foreign)
		{
			foreign = null;
			if (NamedPrefabs?.GetValue(scene) is Dictionary<int, GameObject> dictionary && dictionary.TryGetValue(hash, out var value) && (Object)(object)value != (Object)null && value != owned)
			{
				foreign = value;
				return true;
			}
			foreach (GameObject prefab in scene.m_prefabs)
			{
				if (!((Object)(object)prefab == (Object)null) && prefab != owned && StringExtensionMethods.GetStableHashCode(((Object)prefab).name) == hash)
				{
					foreign = prefab;
					return true;
				}
			}
			return false;
		}

		private static void ReportCollision(string prefabName, int hash, GameObject foreign)
		{
			Log.Error("Prefab registration collision: feature='Clan Ward', prefab='" + prefabName + "', hash=" + hash + ", foreign='" + (((Object)(object)foreign != (Object)null) ? ((Object)foreign).name : "<destroyed>") + "'. Clan Ward is disabled for this world.");
		}

		private static void UnregisterFrom(ZNetScene scene, GameObject prefab)
		{
			if (!((Object)(object)scene == (Object)null) && !((Object)(object)prefab == (Object)null))
			{
				scene.m_prefabs.Remove(prefab);
				if (NamedPrefabs?.GetValue(scene) is Dictionary<int, GameObject> dictionary && dictionary.TryGetValue(Hash, out var value) && value == prefab)
				{
					dictionary.Remove(Hash);
				}
			}
		}

		private static void RemoveFromHammer(ObjectDB db, GameObject prefab)
		{
			if (!((Object)(object)db == (Object)null) && !((Object)(object)prefab == (Object)null))
			{
				GameObject itemPrefab = db.GetItemPrefab("Hammer");
				PieceTable val = ((!((Object)(object)itemPrefab != (Object)null)) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_buildPieces);
				if ((Object)(object)val != (Object)null)
				{
					val.m_pieces.Remove(prefab);
				}
			}
		}

		public static void Shutdown()
		{
			GameObject prefab = _prefab;
			UnregisterFrom(ZNetScene.instance, prefab);
			RemoveFromHammer(ObjectDB.instance, prefab);
			if ((Object)(object)_holder != (Object)null)
			{
				Object.Destroy((Object)(object)_holder);
			}
			_holder = null;
			_prefab = null;
			_attemptedScene = null;
			_availableScene = null;
			_registrationCollision = false;
			_setupFailed = false;
			Areas.Clear();
			VanillaRadius = 32f;
			_flashRadius = 0f;
			_spawnFound = false;
			foreach (Object ownedAsset in OwnedAssets)
			{
				if (ownedAsset != (Object)null)
				{
					Object.Destroy(ownedAsset);
				}
			}
			OwnedAssets.Clear();
		}

		private static void AddToHammer(ObjectDB db)
		{
			GameObject itemPrefab = db.GetItemPrefab("Hammer");
			PieceTable val = ((!((Object)(object)itemPrefab != (Object)null)) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_buildPieces);
			if ((Object)(object)val == (Object)null)
			{
				Log.Warn("The Hammer's build table was not found; the Clan Ward is not in the build menu.");
			}
			else if (!val.m_pieces.Contains(_prefab))
			{
				val.m_pieces.Add(_prefab);
			}
		}

		private static void MakeFree()
		{
			Piece component = _prefab.GetComponent<Piece>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_resources = (Requirement[])(object)new Requirement[0];
			}
		}

		public static void Teach(Player player)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)_prefab == (Object)null || LearnPieces == null)
			{
				return;
			}
			try
			{
				LearnPieces.Invoke(player, null);
			}
			catch (Exception ex)
			{
				Log.Debug("Could not teach the Clan Ward: " + ex.Message);
			}
		}

		private static void ScaleUp(GameObject root, float factor)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_002b: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			foreach (Transform item in root.transform)
			{
				Transform val = item;
				if (!((Object)(object)((Component)val).GetComponentInChildren<CircleProjector>(true) != (Object)null))
				{
					val.localScale *= factor;
					val.localPosition *= factor;
				}
			}
			BoxCollider[] components = root.GetComponents<BoxCollider>();
			foreach (BoxCollider obj in components)
			{
				obj.size *= factor;
				obj.center *= factor;
			}
			CapsuleCollider[] components2 = root.GetComponents<CapsuleCollider>();
			foreach (CapsuleCollider obj2 in components2)
			{
				obj2.radius *= factor;
				obj2.height *= factor;
				obj2.center *= factor;
			}
			SphereCollider[] components3 = root.GetComponents<SphereCollider>();
			foreach (SphereCollider obj3 in components3)
			{
				obj3.radius *= factor;
				obj3.center *= factor;
			}
		}

		private static void Tint(GameObject root)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Invalid comparison between Unknown and I4
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Expected O, but got Unknown
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				Material[] sharedMaterials = val.sharedMaterials;
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					if ((Object)(object)sharedMaterials[j] != (Object)null)
					{
						sharedMaterials[j] = TintMaterial(sharedMaterials[j]);
					}
				}
				val.sharedMaterials = sharedMaterials;
			}
			Light[] componentsInChildren2 = root.GetComponentsInChildren<Light>(true);
			foreach (Light obj in componentsInChildren2)
			{
				obj.color = Blue;
				obj.intensity *= 0.5f;
			}
			ParticleSystem[] componentsInChildren3 = root.GetComponentsInChildren<ParticleSystem>(true);
			foreach (ParticleSystem obj2 in componentsInChildren3)
			{
				MainModule main = obj2.main;
				((MainModule)(ref main)).startColor = new MinMaxGradient(new Color(Blue.r, Blue.g, Blue.b, 0.6f));
				ColorOverLifetimeModule colorOverLifetime = obj2.colorOverLifetime;
				if (!((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled)
				{
					continue;
				}
				MinMaxGradient color = ((ColorOverLifetimeModule)(ref colorOverLifetime)).color;
				if ((int)((MinMaxGradient)(ref color)).mode == 1)
				{
					color = ((ColorOverLifetimeModule)(ref colorOverLifetime)).color;
					if (((MinMaxGradient)(ref color)).gradient != null)
					{
						Gradient val2 = new Gradient();
						GradientColorKey[] obj3 = new GradientColorKey[2]
						{
							new GradientColorKey(Blue, 0f),
							new GradientColorKey(Blue, 1f)
						};
						color = ((ColorOverLifetimeModule)(ref colorOverLifetime)).color;
						val2.SetKeys((GradientColorKey[])(object)obj3, ((MinMaxGradient)(ref color)).gradient.alphaKeys);
						((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(val2);
					}
				}
			}
		}

		private static Material TintMaterial(Material source)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0042: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			Material val = new Material(source);
			OwnedAssets.Add((Object)(object)val);
			((Object)val).name = ((Object)source).name + " (Clan)";
			if (val.HasProperty("_Color"))
			{
				val.SetColor("_Color", Color.Lerp(val.GetColor("_Color"), Blue, 0.45f));
			}
			if (val.HasProperty("_TintColor"))
			{
				val.SetColor("_TintColor", Blue * 0.6f);
			}
			if (val.HasProperty("_EmissionColor"))
			{
				val.SetColor("_EmissionColor", Blue * 0.6f);
			}
			return val;
		}

		private static GameObject TintedCopy(GameObject source)
		{
			GameObject obj = Object.Instantiate<GameObject>(source, _holder.transform);
			((Object)obj).name = ((Object)source).name;
			Tint(obj);
			return obj;
		}

		private static Sprite TintIcon(Sprite source)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)source == (Object)null || (int)SystemInfo.graphicsDeviceType == 4)
			{
				return source;
			}
			RenderTexture val = null;
			Texture2D val2 = null;
			RenderTexture active = RenderTexture.active;
			try
			{
				Texture2D texture = source.texture;
				Rect textureRect = source.textureRect;
				val = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0);
				Graphics.Blit((Texture)(object)texture, val);
				RenderTexture.active = val;
				int num = Mathf.RoundToInt(((Rect)(ref textureRect)).width);
				int num2 = Mathf.RoundToInt(((Rect)(ref textureRect)).height);
				val2 = new Texture2D(num, num2, (TextureFormat)4, false);
				val2.ReadPixels(new Rect(((Rect)(ref textureRect)).x, ((Rect)(ref textureRect)).y, (float)num, (float)num2), 0, 0);
				Color[] pixels = val2.GetPixels();
				Color val4 = default(Color);
				for (int i = 0; i < pixels.Length; i++)
				{
					Color val3 = pixels[i];
					float num3 = (val3.r + val3.g + val3.b) / 3f;
					((Color)(ref val4))..ctor(Blue.r * num3 * 1.6f, Blue.g * num3 * 1.6f, Blue.b * num3 * 1.6f, val3.a);
					pixels[i] = Color.Lerp(val3, val4, 0.7f);
				}
				val2.SetPixels(pixels);
				val2.Apply();
				Sprite val5 = Sprite.Create(val2, new Rect(0f, 0f, (float)num, (float)num2), new Vector2(0.5f, 0.5f));
				OwnedAssets.Add((Object)(object)val2);
				OwnedAssets.Add((Object)(object)val5);
				val2 = null;
				return val5;
			}
			catch (Exception ex)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					Object.Destroy((Object)(object)val2);
				}
				Log.Debug("Clan Ward icon kept as-is: " + ex.Message);
				return source;
			}
			finally
			{
				RenderTexture.active = active;
				if ((Object)(object)val != (Object)null)
				{
					RenderTexture.ReleaseTemporary(val);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "OnSpawned")]
	public static class Player_OnSpawned_ClanWard
	{
		private static void Postfix(Player __instance)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				ClanWard.Teach(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	public static class ZNetScene_Awake_ClanWard
	{
		private static void Postfix()
		{
			ClanWard.Setup();
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	public static class ObjectDB_Awake_ClanWard
	{
		private static void Postfix()
		{
			ClanWard.Setup();
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
	public static class ObjectDB_CopyOtherDB_ClanWard
	{
		private static void Postfix()
		{
			ClanWard.Setup();
		}
	}
	[HarmonyPatch(typeof(Player), "TryPlacePiece")]
	public static class Player_TryPlacePiece_ClanWard
	{
		private static bool Prefix(Piece piece, ref bool __result)
		{
			if ((Object)(object)piece == (Object)null || !ClanWard.Is(((Component)piece).gameObject))
			{
				return true;
			}
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return true;
			}
			string text = null;
			if (ClanClient.Instance.MyClan() == null)
			{
				text = "Join a clan to raise a Clan Ward";
			}
			else
			{
				ClanStateView state = ClanClient.Instance.State;
				string why;
				if (state.maxClanWards > 0 && state.ownWards.Count >= state.maxClanWards)
				{
					text = "Your clan already has " + state.maxClanWards + " Clan Wards";
				}
				else if (!ClanWard.SpacingLooksOk(state, out why))
				{
					text = why;
				}
			}
			if (text == null)
			{
				return true;
			}