Decompiled source of MoonforgedChristmasDecorations v1.0.6

MoonforgedChristmasDecorations.dll

Decompiled 3 days ago
using System;
using System.Collections;
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.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("MoonforgedChristmasDecorations")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MoonforgedChristmasDecorations")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: AssemblyFileVersion("1.0.6.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.6.0")]
namespace Moonforged.ChristmasDecorations;

[RequireComponent(typeof(LineRenderer))]
public class BezierRope : MonoBehaviour
{
	public Transform pointA;

	public Transform pointB;

	[Header("Look")]
	public int segments = 24;

	public float width = 0.015f;

	public float sag = 0.25f;

	public Material material;

	[Header("Cloth-like motion")]
	public float windStrength = 0.2f;

	public float jiggleAmplitude = 0.02f;

	public float jiggleSpeed = 1f;

	private LineRenderer _lr;

	private float _seed;

	private void Awake()
	{
		//IL_0083: 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)
		_lr = ((Component)this).GetComponent<LineRenderer>();
		_lr.useWorldSpace = true;
		_lr.startWidth = width;
		_lr.endWidth = width;
		_lr.numCornerVertices = 3;
		_lr.numCapVertices = 3;
		_lr.textureMode = (LineTextureMode)0;
		((Renderer)_lr).material = (Material)(((Object)(object)material != (Object)null) ? ((object)material) : ((object)new Material(Shader.Find("Sprites/Default"))));
		((Renderer)_lr).material.color = Color.black;
		_seed = Random.Range(0f, 1000f);
	}

	private void LateUpdate()
	{
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: 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_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: 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_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: 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_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: 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)
		//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_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: 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_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0136: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: 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_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_014f: 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_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_0169: Unknown result type (might be due to invalid IL or missing references)
		//IL_0170: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: 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_01d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f9: 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_0217: Unknown result type (might be due to invalid IL or missing references)
		//IL_0219: Unknown result type (might be due to invalid IL or missing references)
		//IL_021e: Unknown result type (might be due to invalid IL or missing references)
		//IL_022b: Unknown result type (might be due to invalid IL or missing references)
		//IL_022c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0231: Unknown result type (might be due to invalid IL or missing references)
		//IL_0236: Unknown result type (might be due to invalid IL or missing references)
		//IL_0245: Unknown result type (might be due to invalid IL or missing references)
		//IL_0246: Unknown result type (might be due to invalid IL or missing references)
		//IL_0247: Unknown result type (might be due to invalid IL or missing references)
		//IL_024c: 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_0255: Unknown result type (might be due to invalid IL or missing references)
		//IL_025a: Unknown result type (might be due to invalid IL or missing references)
		//IL_025f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0263: Unknown result type (might be due to invalid IL or missing references)
		//IL_0268: Unknown result type (might be due to invalid IL or missing references)
		//IL_026a: Unknown result type (might be due to invalid IL or missing references)
		//IL_026c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0270: Unknown result type (might be due to invalid IL or missing references)
		//IL_0277: Unknown result type (might be due to invalid IL or missing references)
		//IL_027c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0281: Unknown result type (might be due to invalid IL or missing references)
		//IL_028b: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)pointA == (Object)null) && !((Object)(object)pointB == (Object)null))
		{
			_lr.startWidth = width;
			_lr.endWidth = width;
			Vector3 position = pointA.position;
			Vector3 position2 = pointB.position;
			Vector3 val = (position + position2) * 0.5f;
			Vector3 val2 = Vector3.Lerp(position, val, 0.66f) + Vector3.down * sag;
			Vector3 val3 = Vector3.Lerp(position2, val, 0.66f) + Vector3.down * sag;
			Vector3 right = Vector3.right;
			if ((Object)(object)pointA != (Object)null)
			{
				right = pointA.right;
			}
			float num = Time.time + _seed;
			float num2 = Mathf.Sin(num * ((float)Math.PI * 2f) * Mathf.Max(0.01f, jiggleSpeed)) * jiggleAmplitude;
			val2 += right * windStrength * 0.5f + Vector3.up * num2 * 0.5f;
			val3 += right * windStrength * 1f + Vector3.down * num2 * 0.5f;
			int num3 = Mathf.Max(4, segments);
			_lr.positionCount = num3;
			float num4 = 1f / (float)(num3 - 1);
			for (int i = 0; i < num3; i++)
			{
				float num5 = (float)i * num4;
				Vector3 val4 = Mathf.Pow(1f - num5, 3f) * position + 3f * Mathf.Pow(1f - num5, 2f) * num5 * val2 + 3f * (1f - num5) * num5 * num5 * val3 + num5 * num5 * num5 * position2;
				float num6 = num5 * (1f - num5);
				Vector3 val5 = position2 - position;
				val5 = Vector3.Cross(((Vector3)(ref val5)).normalized, Vector3.up);
				Vector3 normalized = ((Vector3)(ref val5)).normalized;
				val4 += normalized * num2 * num6;
				_lr.SetPosition(i, val4);
			}
		}
	}
}
public class ChildLightsCycler : MonoBehaviour
{
	public string[] lightRendererNames = new string[3] { "Light1", "Light2", "Light3" };

	public float stepSeconds = 1f;

	public float intensity = 4.4f;

	private readonly List<Material> _mats = new List<Material>();

	private static readonly Color[] Palette = (Color[])(object)new Color[3]
	{
		Color.red,
		Color.yellow,
		Color.blue
	};

	private int _step;

	private Coroutine _runner;

	private void Awake()
	{
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		_mats.Clear();
		for (int i = 0; i < lightRendererNames.Length; i++)
		{
			Transform val = ((Component)this).transform.Find(lightRendererNames[i]);
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			Renderer component = ((Component)val).GetComponent<Renderer>();
			if (!((Object)(object)component == (Object)null))
			{
				Material sharedMaterial = component.sharedMaterial;
				if (!((Object)(object)sharedMaterial == (Object)null))
				{
					sharedMaterial.EnableKeyword("_EMISSION");
					sharedMaterial.SetColor("_EmissionColor", Palette[i % Palette.Length] * Mathf.LinearToGammaSpace(intensity));
					sharedMaterial.globalIlluminationFlags = (MaterialGlobalIlluminationFlags)1;
					_mats.Add(sharedMaterial);
				}
			}
		}
	}

	private void OnEnable()
	{
		if (_runner == null && _mats.Count > 0)
		{
			_runner = ((MonoBehaviour)this).StartCoroutine(Run());
		}
	}

	private void OnDisable()
	{
		if (_runner != null)
		{
			((MonoBehaviour)this).StopCoroutine(_runner);
			_runner = null;
		}
	}

	private IEnumerator Run()
	{
		float delay = Mathf.Max(0.05f, stepSeconds);
		while (true)
		{
			if (_mats.Count > 0)
			{
				ApplyStep();
			}
			yield return (object)new WaitForSeconds(delay);
		}
	}

	private void ApplyStep()
	{
		//IL_0035: 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_0041: 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)
		for (int i = 0; i < _mats.Count; i++)
		{
			Material val = _mats[i];
			if (!((Object)(object)val == (Object)null))
			{
				Color val2 = Palette[(i + _step) % Palette.Length];
				val.SetColor("_EmissionColor", val2 * Mathf.LinearToGammaSpace(intensity));
			}
		}
		_step = (_step + 1) % Palette.Length;
	}
}
public class ChristmasLightChaser : MonoBehaviour
{
	public enum AnimationMode
	{
		Chase,
		BlinkAll
	}

	public bool includeInactive = true;

	public Color[] defaultPalette = (Color[])(object)new Color[3]
	{
		Color.red,
		Color.yellow,
		Color.blue
	};

	public Color[] paletteOverride;

	public AnimationMode mode = AnimationMode.Chase;

	[Min(0.01f)]
	public float stepSeconds = 1f;

	[Min(0f)]
	public float emissionIntensity = 4.4f;

	public bool affectBaseColor = false;

	public string[] ignoreNameContains = new string[2] { "cable", "snap" };

	public List<Renderer> targets = new List<Renderer>();

	private readonly List<MaterialPropertyBlock> _mpbs = new List<MaterialPropertyBlock>();

	private int _colorId;

	private int _emissId;

	private int _step;

	private Coroutine _runner;

	private bool _liveStarted;

	private Color[] _palette;

	private void Awake()
	{
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Expected O, but got Unknown
		_palette = ((paletteOverride != null && paletteOverride.Length != 0) ? paletteOverride : defaultPalette);
		_colorId = Shader.PropertyToID("_Color");
		_emissId = Shader.PropertyToID("_EmissionColor");
		if (targets.Count == 0)
		{
			Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(includeInactive);
			foreach (Renderer val in componentsInChildren)
			{
				if (!Object.op_Implicit((Object)(object)val))
				{
					continue;
				}
				string text = ((Object)val).name.ToLowerInvariant();
				bool flag = false;
				for (int j = 0; j < ignoreNameContains.Length; j++)
				{
					if (text.Contains(ignoreNameContains[j]))
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					targets.Add(val);
				}
			}
		}
		_mpbs.Clear();
		foreach (Renderer target in targets)
		{
			if (Object.op_Implicit((Object)(object)target))
			{
				MaterialPropertyBlock val2 = new MaterialPropertyBlock();
				target.GetPropertyBlock(val2);
				if (Object.op_Implicit((Object)(object)target.material))
				{
					target.material.EnableKeyword("_EMISSION");
				}
				_mpbs.Add(val2);
			}
		}
	}

	private void OnEnable()
	{
		if (_runner == null)
		{
			_runner = ((MonoBehaviour)this).StartCoroutine(Run());
		}
	}

	private void OnDisable()
	{
		if (_runner != null)
		{
			((MonoBehaviour)this).StopCoroutine(_runner);
		}
		_runner = null;
		_liveStarted = false;
	}

	private IEnumerator Run()
	{
		WaitForSeconds poll = new WaitForSeconds(0.2f);
		WaitForSeconds stepWait = new WaitForSeconds(stepSeconds);
		while (true)
		{
			bool hasZdo = false;
			ZNetView znv = ((Component)this).GetComponentInParent<ZNetView>();
			if ((Object)(object)znv != (Object)null)
			{
				hasZdo = znv.GetZDO() != null;
			}
			if (!hasZdo)
			{
				_liveStarted = false;
				yield return poll;
				continue;
			}
			if (!_liveStarted)
			{
				_liveStarted = true;
				_step = 0;
			}
			int n = Mathf.Max(1, _palette.Length);
			if (mode == AnimationMode.Chase)
			{
				for (int i = 0; i < targets.Count; i++)
				{
					Renderer r = targets[i];
					if (Object.op_Implicit((Object)(object)r))
					{
						MaterialPropertyBlock mpb = _mpbs[i];
						Color c = _palette[(i + _step) % n];
						if (affectBaseColor)
						{
							mpb.SetColor(_colorId, c);
						}
						mpb.SetColor(_emissId, c * Mathf.LinearToGammaSpace(emissionIntensity));
						r.SetPropertyBlock(mpb);
					}
				}
			}
			else
			{
				Color c2 = _palette[_step % n];
				for (int j = 0; j < targets.Count; j++)
				{
					Renderer r2 = targets[j];
					if (Object.op_Implicit((Object)(object)r2))
					{
						MaterialPropertyBlock mpb2 = _mpbs[j];
						if (affectBaseColor)
						{
							mpb2.SetColor(_colorId, c2);
						}
						mpb2.SetColor(_emissId, c2 * Mathf.LinearToGammaSpace(emissionIntensity));
						r2.SetPropertyBlock(mpb2);
					}
				}
			}
			_step++;
			yield return stepWait;
		}
	}
}
public static class ChristmasLightChaserInstaller
{
	public static void InstallOn(GameObject prefabRoot, float stepSeconds, float emissionIntensity)
	{
		InstallOn(prefabRoot, stepSeconds, emissionIntensity, null, ChristmasLightChaser.AnimationMode.Chase);
	}

	public static void InstallOn(GameObject prefabRoot, float stepSeconds, float emissionIntensity, Color[] paletteOverride, ChristmasLightChaser.AnimationMode mode)
	{
		if (Object.op_Implicit((Object)(object)prefabRoot))
		{
			ChristmasLightChaser christmasLightChaser = prefabRoot.GetComponent<ChristmasLightChaser>();
			if (!Object.op_Implicit((Object)(object)christmasLightChaser))
			{
				christmasLightChaser = prefabRoot.AddComponent<ChristmasLightChaser>();
			}
			christmasLightChaser.includeInactive = true;
			christmasLightChaser.stepSeconds = stepSeconds;
			christmasLightChaser.emissionIntensity = emissionIntensity;
			christmasLightChaser.mode = mode;
			if (paletteOverride != null && paletteOverride.Length != 0)
			{
				christmasLightChaser.paletteOverride = paletteOverride;
			}
			christmasLightChaser.targets = CollectBulbRenderers(prefabRoot, new string[1] { "light" }, new string[6] { "cable", "wire", "string", "snap", "garland", "rope" });
		}
	}

	private static List<Renderer> CollectBulbRenderers(GameObject root, string[] includePrefixes, string[] ignoreContains)
	{
		List<Renderer> list = new List<Renderer>();
		if (!Object.op_Implicit((Object)(object)root))
		{
			return list;
		}
		Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
		foreach (Renderer val in componentsInChildren)
		{
			if (!Object.op_Implicit((Object)(object)val))
			{
				continue;
			}
			string text = ((Object)((Component)val).gameObject).name.ToLowerInvariant();
			bool flag = false;
			if (ignoreContains != null)
			{
				foreach (string value in ignoreContains)
				{
					if (!string.IsNullOrEmpty(value) && text.Contains(value))
					{
						flag = true;
						break;
					}
				}
			}
			if (flag)
			{
				continue;
			}
			bool flag2 = includePrefixes == null || includePrefixes.Length == 0;
			if (!flag2)
			{
				foreach (string value2 in includePrefixes)
				{
					if (!string.IsNullOrEmpty(value2) && text.StartsWith(value2))
					{
						flag2 = true;
						break;
					}
				}
			}
			if (flag2)
			{
				list.Add(val);
			}
		}
		return list;
	}
}
public class ChristmasLightsGlow : MonoBehaviour
{
	[Header("Target renderer (child name)")]
	public string rendererChildName = "Christmas tree.007";

	[Header("Choose how to select materials")]
	public bool useIndices = true;

	[Tooltip("Material slots that should glow (0-based)")]
	public int[] glowSlots = new int[3] { 2, 7, 8 };

	[Tooltip("Match by material name (contains, case-insensitive)")]
	public string[] glowNameContains = new string[1] { "vray_Christmas Tree Set3_4.001" };

	[Header("Glow settings")]
	public Color emissionColor = Color.yellow;

	public float intensity = 3f;

	public bool animate = false;

	public float cycleSeconds = 5f;

	private Renderer _rend;

	private Material[] _mats;

	private bool[] _shouldGlow;

	private void Awake()
	{
		//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
		Transform val = ((Component)this).transform.Find(rendererChildName);
		if ((Object)(object)val != (Object)null)
		{
			_rend = ((Component)val).GetComponent<Renderer>();
		}
		if ((Object)(object)_rend == (Object)null)
		{
			_rend = (from r in ((Component)this).GetComponentsInChildren<Renderer>(true)
				orderby (r.sharedMaterials != null) ? r.sharedMaterials.Length : 0 descending
				select r).FirstOrDefault();
		}
		if ((Object)(object)_rend == (Object)null)
		{
			return;
		}
		_mats = _rend.materials;
		_shouldGlow = new bool[_mats.Length];
		for (int num = 0; num < _mats.Length; num++)
		{
			bool flag = false;
			if (useIndices)
			{
				for (int num2 = 0; num2 < glowSlots.Length; num2++)
				{
					if (glowSlots[num2] == num)
					{
						flag = true;
						break;
					}
				}
			}
			else
			{
				string text = (((Object)(object)_mats[num] != (Object)null) ? ((Object)_mats[num]).name : "");
				for (int num3 = 0; num3 < glowNameContains.Length; num3++)
				{
					if (!string.IsNullOrEmpty(glowNameContains[num3]) && text.ToLower().Contains(glowNameContains[num3].ToLower()))
					{
						flag = true;
						break;
					}
				}
			}
			_shouldGlow[num] = flag;
			if (flag && (Object)(object)_mats[num] != (Object)null)
			{
				_mats[num].EnableKeyword("_EMISSION");
				Color val2 = emissionColor * Mathf.LinearToGammaSpace(intensity);
				_mats[num].SetColor("_EmissionColor", val2);
				_mats[num].globalIlluminationFlags = (MaterialGlobalIlluminationFlags)1;
			}
		}
		_rend.materials = _mats;
	}

	private void Update()
	{
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
		if (!animate || _mats == null)
		{
			return;
		}
		float num = Mathf.Max(0.01f, cycleSeconds);
		float num2 = Time.time % num / num;
		float num3 = 0.5f + 0.5f * Mathf.Sin(num2 * (float)Math.PI * 2f);
		for (int i = 0; i < _mats.Length; i++)
		{
			if (_shouldGlow[i] && (Object)(object)_mats[i] != (Object)null)
			{
				Color val = emissionColor * Mathf.LinearToGammaSpace(intensity * (0.5f + num3));
				_mats[i].SetColor("_EmissionColor", val);
			}
		}
	}
}
public class ConnectedLightControl : MonoBehaviour, Interactable, Hoverable
{
	public enum LightMode
	{
		Normal,
		Fast5x,
		Fast10x,
		Vibrate,
		Off
	}

	public string prefabIdentity = "";

	[Header("Connected lights")]
	[Min(0.05f)]
	public float connectionDistance = 0.35f;

	[Min(0.05f)]
	public float connectionRefreshSeconds = 0.25f;

	[Header("Rapid blink")]
	[Min(0.01f)]
	public float rapidBlinkSeconds = 0.03f;

	private const string ModeZdoKey = "mf_connected_light_mode";

	private const string ModeVersionZdoKey = "mf_connected_light_version";

	private static readonly List<ConnectedLightControl> Instances = new List<ConnectedLightControl>();

	private readonly List<Transform> _snapPoints = new List<Transform>();

	private readonly List<Renderer> _bulbRenderers = new List<Renderer>();

	private readonly List<MaterialPropertyBlock> _savedBulbBlocks = new List<MaterialPropertyBlock>();

	private readonly List<MaterialPropertyBlock> _workingBulbBlocks = new List<MaterialPropertyBlock>();

	private ZNetView _nview;

	private ChristmasLightChaser _chaser;

	private ChildLightsCycler _cycler;

	private IcicleFlow _icicleFlow;

	private ChristmasLightsGlow _glow;

	private float _baseChaserStep;

	private float _baseCyclerStep;

	private float _baseFlowDripStep;

	private float _baseFlowPause;

	private float _baseFlowBatchSpacing;

	private float _baseFlowUpdateInterval;

	private float _baseGlowCycle;

	private bool _baseChaserEnabled;

	private bool _baseCyclerEnabled;

	private bool _baseFlowEnabled;

	private bool _baseGlowEnabled;

	private bool _baseTimingCaptured;

	private LightMode _mode = LightMode.Normal;

	private int _modeVersion;

	private LightMode _appliedMode = LightMode.Normal;

	private int _appliedVersion;

	private bool _hasAppliedMode;

	private int _groupSignature;

	private int _linkedLightCount = 1;

	private int _blinkPhase = -1;

	private float _nextConnectionRefresh;

	private int _emissionColorId;

	private void Awake()
	{
		_emissionColorId = Shader.PropertyToID("_EmissionColor");
		EnsureNetworkView();
		CacheSnapPoints();
		CacheAnimationComponents();
	}

	private void Start()
	{
		EnsureNetworkView();
		CacheAnimationComponents();
		CaptureBaseTiming();
		CacheBulbRenderers();
		ReadNetworkMode(force: true);
		ApplyMode(_mode, _modeVersion, persist: false, forceRestart: true);
	}

	private void OnEnable()
	{
		if (!Instances.Contains(this))
		{
			Instances.Add(this);
		}
		_nextConnectionRefresh = 0f;
		_blinkPhase = -1;
	}

	private void OnDisable()
	{
		Instances.Remove(this);
	}

	private void Update()
	{
		EnsureNetworkView();
		if (ReadNetworkMode(force: false))
		{
			ApplyMode(_mode, _modeVersion, persist: false, forceRestart: true);
		}
		float time = Time.time;
		if (time >= _nextConnectionRefresh)
		{
			_nextConnectionRefresh = time + Mathf.Max(0.05f, connectionRefreshSeconds);
			RefreshLinkedGroup();
		}
		if (_mode == LightMode.Vibrate)
		{
			UpdateRapidBlink(time);
		}
	}

	public bool Interact(Humanoid user, bool hold, bool alt)
	{
		if (hold)
		{
			return false;
		}
		List<ConnectedLightControl> list = GatherConnectedControls(this);
		list.Sort(CompareStable);
		int highestVersion;
		LightMode current = ResolveGroupMode(list, out highestVersion);
		LightMode nextMode = GetNextMode(current);
		int version = highestVersion + 1;
		for (int i = 0; i < list.Count; i++)
		{
			list[i].ApplyMode(nextMode, version, persist: true, forceRestart: true);
		}
		return true;
	}

	public bool UseItem(Humanoid user, ItemData item)
	{
		return false;
	}

	public string GetHoverName()
	{
		return string.IsNullOrEmpty(prefabIdentity) ? "Christmas Lights" : prefabIdentity;
	}

	public float GetHoverOffset()
	{
		return 0f;
	}

	public string GetHoverText()
	{
		return "[<color=yellow><b>E</b></color>] Change light speed\nMode: <color=orange>" + GetModeName(_mode) + "</color>\nLinked lights: " + Mathf.Max(1, _linkedLightCount);
	}

	private static LightMode GetNextMode(LightMode current)
	{
		if (current >= LightMode.Off)
		{
			return LightMode.Normal;
		}
		return current + 1;
	}

	private static string GetModeName(LightMode mode)
	{
		return mode switch
		{
			LightMode.Fast5x => "5x Speed", 
			LightMode.Fast10x => "10x Speed", 
			LightMode.Vibrate => "Rapid Blink", 
			LightMode.Off => "Off", 
			_ => "Normal", 
		};
	}

	private void ApplyMode(LightMode mode, int version, bool persist, bool forceRestart)
	{
		bool flag = !_hasAppliedMode || _appliedMode != mode || _appliedVersion != version;
		LightMode lightMode = (_hasAppliedMode ? _appliedMode : LightMode.Normal);
		_mode = mode;
		_modeVersion = version;
		_appliedMode = mode;
		_appliedVersion = version;
		_hasAppliedMode = true;
		if (persist)
		{
			WriteNetworkMode();
		}
		if (!flag && !forceRestart)
		{
			return;
		}
		CacheAnimationComponents();
		CaptureBaseTiming();
		CacheBulbRenderers();
		bool flag2 = mode == LightMode.Vibrate || mode == LightMode.Off;
		bool flag3 = lightMode == LightMode.Vibrate || lightMode == LightMode.Off;
		if (flag2 && !flag3)
		{
			CaptureCurrentBulbState();
		}
		if (flag2)
		{
			DisableAnimationComponents();
			_blinkPhase = -1;
			if (mode == LightMode.Off)
			{
				SetBulbsOff();
			}
			else
			{
				UpdateRapidBlink(Time.time);
			}
		}
		else
		{
			RestoreBulbState();
			RestartAnimationComponents(mode switch
			{
				LightMode.Fast10x => 10f, 
				LightMode.Fast5x => 5f, 
				_ => 1f, 
			});
			_blinkPhase = -1;
		}
	}

	private void UpdateRapidBlink(float now)
	{
		int num = Mathf.FloorToInt(now / Mathf.Max(0.01f, rapidBlinkSeconds)) & 1;
		if (num != _blinkPhase)
		{
			_blinkPhase = num;
			if (num == 0)
			{
				SetBulbsOff();
			}
			else
			{
				RestoreBulbState();
			}
		}
	}

	private void CacheAnimationComponents()
	{
		if ((Object)(object)_chaser == (Object)null)
		{
			_chaser = ((Component)this).GetComponent<ChristmasLightChaser>();
		}
		if ((Object)(object)_cycler == (Object)null)
		{
			_cycler = ((Component)this).GetComponent<ChildLightsCycler>();
		}
		if ((Object)(object)_icicleFlow == (Object)null)
		{
			_icicleFlow = ((Component)this).GetComponent<IcicleFlow>();
		}
		if ((Object)(object)_glow == (Object)null)
		{
			_glow = ((Component)this).GetComponent<ChristmasLightsGlow>();
		}
	}

	private void CaptureBaseTiming()
	{
		if (!_baseTimingCaptured)
		{
			if ((Object)(object)_chaser != (Object)null)
			{
				_baseChaserStep = Mathf.Max(0.01f, _chaser.stepSeconds);
				_baseChaserEnabled = ((Behaviour)_chaser).enabled;
			}
			if ((Object)(object)_cycler != (Object)null)
			{
				_baseCyclerStep = Mathf.Max(0.01f, _cycler.stepSeconds);
				_baseCyclerEnabled = ((Behaviour)_cycler).enabled;
			}
			if ((Object)(object)_icicleFlow != (Object)null)
			{
				_baseFlowDripStep = Mathf.Max(0.01f, _icicleFlow.dripStepSeconds);
				_baseFlowPause = Mathf.Max(0f, _icicleFlow.pauseAfterColumn);
				_baseFlowBatchSpacing = Mathf.Max(0f, _icicleFlow.batchSpacingSeconds);
				_baseFlowUpdateInterval = Mathf.Max(0.01f, _icicleFlow.minUpdateInterval);
				_baseFlowEnabled = ((Behaviour)_icicleFlow).enabled;
			}
			if ((Object)(object)_glow != (Object)null)
			{
				_baseGlowCycle = Mathf.Max(0.01f, _glow.cycleSeconds);
				_baseGlowEnabled = ((Behaviour)_glow).enabled;
			}
			_baseTimingCaptured = true;
		}
	}

	private void RestartAnimationComponents(float speedMultiplier)
	{
		float num = Mathf.Max(1f, speedMultiplier);
		if ((Object)(object)_chaser != (Object)null)
		{
			((Behaviour)_chaser).enabled = false;
			_chaser.stepSeconds = Mathf.Max(0.01f, _baseChaserStep / num);
			((Behaviour)_chaser).enabled = _baseChaserEnabled;
		}
		if ((Object)(object)_cycler != (Object)null)
		{
			((Behaviour)_cycler).enabled = false;
			_cycler.stepSeconds = Mathf.Max(0.01f, _baseCyclerStep / num);
			((Behaviour)_cycler).enabled = _baseCyclerEnabled;
		}
		if ((Object)(object)_icicleFlow != (Object)null)
		{
			((Behaviour)_icicleFlow).enabled = false;
			_icicleFlow.dripStepSeconds = Mathf.Max(0.01f, _baseFlowDripStep / num);
			_icicleFlow.pauseAfterColumn = _baseFlowPause / num;
			_icicleFlow.batchSpacingSeconds = _baseFlowBatchSpacing / num;
			_icicleFlow.minUpdateInterval = Mathf.Max(0.01f, _baseFlowUpdateInterval / num);
			((Behaviour)_icicleFlow).enabled = _baseFlowEnabled;
		}
		if ((Object)(object)_glow != (Object)null)
		{
			((Behaviour)_glow).enabled = false;
			_glow.cycleSeconds = Mathf.Max(0.01f, _baseGlowCycle / num);
			((Behaviour)_glow).enabled = _baseGlowEnabled;
		}
	}

	private void DisableAnimationComponents()
	{
		if ((Object)(object)_chaser != (Object)null)
		{
			((Behaviour)_chaser).enabled = false;
		}
		if ((Object)(object)_cycler != (Object)null)
		{
			((Behaviour)_cycler).enabled = false;
		}
		if ((Object)(object)_icicleFlow != (Object)null)
		{
			((Behaviour)_icicleFlow).enabled = false;
		}
		if ((Object)(object)_glow != (Object)null)
		{
			((Behaviour)_glow).enabled = false;
		}
	}

	private void CacheBulbRenderers()
	{
		if (_bulbRenderers.Count > 0)
		{
			return;
		}
		HashSet<Renderer> unique = new HashSet<Renderer>();
		if ((Object)(object)_chaser != (Object)null)
		{
			for (int i = 0; i < _chaser.targets.Count; i++)
			{
				AddBulbRenderer(_chaser.targets[i], unique);
			}
		}
		if ((Object)(object)_cycler != (Object)null)
		{
			for (int j = 0; j < _cycler.lightRendererNames.Length; j++)
			{
				Transform val = FindChildByName(((Component)this).transform, _cycler.lightRendererNames[j]);
				if ((Object)(object)val != (Object)null)
				{
					AddBulbRenderer(((Component)val).GetComponent<Renderer>(), unique);
				}
			}
		}
		if ((Object)(object)_icicleFlow != (Object)null)
		{
			Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				if ((Object)(object)val2 != (Object)null && ((Object)((Component)val2).gameObject).name.StartsWith(_icicleFlow.bulbNamePrefix))
				{
					AddBulbRenderer(val2, unique);
				}
			}
		}
		if (_bulbRenderers.Count == 0)
		{
			Renderer[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val3 in componentsInChildren2)
			{
				if ((Object)(object)val3 != (Object)null && ((Object)((Component)val3).gameObject).name.ToLowerInvariant().StartsWith("light"))
				{
					AddBulbRenderer(val3, unique);
				}
			}
		}
		CaptureCurrentBulbState();
	}

	private void AddBulbRenderer(Renderer renderer, HashSet<Renderer> unique)
	{
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Expected O, but got Unknown
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Expected O, but got Unknown
		if (!((Object)(object)renderer == (Object)null) && unique.Add(renderer))
		{
			Material sharedMaterial = renderer.sharedMaterial;
			if ((Object)(object)sharedMaterial != (Object)null)
			{
				sharedMaterial.EnableKeyword("_EMISSION");
			}
			_bulbRenderers.Add(renderer);
			_savedBulbBlocks.Add(new MaterialPropertyBlock());
			_workingBulbBlocks.Add(new MaterialPropertyBlock());
		}
	}

	private void CaptureCurrentBulbState()
	{
		for (int i = 0; i < _bulbRenderers.Count; i++)
		{
			Renderer val = _bulbRenderers[i];
			if ((Object)(object)val != (Object)null)
			{
				val.GetPropertyBlock(_savedBulbBlocks[i]);
			}
		}
	}

	private void RestoreBulbState()
	{
		for (int i = 0; i < _bulbRenderers.Count; i++)
		{
			Renderer val = _bulbRenderers[i];
			if ((Object)(object)val != (Object)null)
			{
				val.SetPropertyBlock(_savedBulbBlocks[i]);
			}
		}
	}

	private void SetBulbsOff()
	{
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < _bulbRenderers.Count; i++)
		{
			Renderer val = _bulbRenderers[i];
			if (!((Object)(object)val == (Object)null))
			{
				MaterialPropertyBlock val2 = _workingBulbBlocks[i];
				val.GetPropertyBlock(val2);
				val2.SetColor(_emissionColorId, Color.black);
				val.SetPropertyBlock(val2);
			}
		}
	}

	private void RefreshLinkedGroup()
	{
		List<ConnectedLightControl> list = GatherConnectedControls(this);
		list.Sort(CompareStable);
		_linkedLightCount = Mathf.Max(1, list.Count);
		if (list.Count == 0 || (Object)(object)list[0] != (Object)(object)this)
		{
			return;
		}
		int highestVersion;
		LightMode lightMode = ResolveGroupMode(list, out highestVersion);
		int num = CalculateGroupSignature(list);
		bool flag = false;
		for (int i = 0; i < list.Count; i++)
		{
			ConnectedLightControl connectedLightControl = list[i];
			connectedLightControl._linkedLightCount = list.Count;
			if (connectedLightControl._groupSignature != num)
			{
				flag = true;
			}
		}
		for (int j = 0; j < list.Count; j++)
		{
			ConnectedLightControl connectedLightControl2 = list[j];
			connectedLightControl2._groupSignature = num;
			bool flag2 = connectedLightControl2._mode != lightMode || connectedLightControl2._modeVersion != highestVersion;
			bool flag3 = !connectedLightControl2._hasAppliedMode || connectedLightControl2._appliedMode != lightMode || connectedLightControl2._appliedVersion != highestVersion;
			connectedLightControl2.ApplyMode(lightMode, highestVersion, flag2, flag || flag2 || flag3);
		}
	}

	private static LightMode ResolveGroupMode(List<ConnectedLightControl> group, out int highestVersion)
	{
		highestVersion = 0;
		LightMode result = LightMode.Normal;
		for (int i = 0; i < group.Count; i++)
		{
			ConnectedLightControl connectedLightControl = group[i];
			connectedLightControl.ReadNetworkMode(force: false);
			if (i == 0 || connectedLightControl._modeVersion > highestVersion)
			{
				highestVersion = connectedLightControl._modeVersion;
				result = connectedLightControl._mode;
			}
		}
		return result;
	}

	private static List<ConnectedLightControl> GatherConnectedControls(ConnectedLightControl origin)
	{
		List<ConnectedLightControl> list = new List<ConnectedLightControl>();
		if ((Object)(object)origin == (Object)null)
		{
			return list;
		}
		list.Add(origin);
		if (!origin.IsLiveInstance())
		{
			return list;
		}
		Queue<ConnectedLightControl> queue = new Queue<ConnectedLightControl>();
		HashSet<ConnectedLightControl> hashSet = new HashSet<ConnectedLightControl>();
		queue.Enqueue(origin);
		hashSet.Add(origin);
		while (queue.Count > 0)
		{
			ConnectedLightControl connectedLightControl = queue.Dequeue();
			for (int i = 0; i < Instances.Count; i++)
			{
				ConnectedLightControl connectedLightControl2 = Instances[i];
				if (!((Object)(object)connectedLightControl2 == (Object)null) && !((Object)(object)connectedLightControl2 == (Object)(object)connectedLightControl) && !hashSet.Contains(connectedLightControl2) && ((Behaviour)connectedLightControl2).isActiveAndEnabled && connectedLightControl2.IsLiveInstance() && SamePrefab(connectedLightControl, connectedLightControl2) && AreConnected(connectedLightControl, connectedLightControl2))
				{
					hashSet.Add(connectedLightControl2);
					list.Add(connectedLightControl2);
					queue.Enqueue(connectedLightControl2);
				}
			}
		}
		return list;
	}

	private static bool SamePrefab(ConnectedLightControl a, ConnectedLightControl b)
	{
		return !string.IsNullOrEmpty(a.prefabIdentity) && string.Equals(a.prefabIdentity, b.prefabIdentity, StringComparison.Ordinal);
	}

	private static bool AreConnected(ConnectedLightControl a, ConnectedLightControl b)
	{
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		a.CacheSnapPoints();
		b.CacheSnapPoints();
		if (a._snapPoints.Count == 0 || b._snapPoints.Count == 0)
		{
			return false;
		}
		float num = Mathf.Max(a.connectionDistance, b.connectionDistance);
		float num2 = num * num;
		for (int i = 0; i < a._snapPoints.Count; i++)
		{
			for (int j = 0; j < b._snapPoints.Count; j++)
			{
				Vector3 val = a._snapPoints[i].position - b._snapPoints[j].position;
				if (((Vector3)(ref val)).sqrMagnitude <= num2)
				{
					return true;
				}
			}
		}
		return false;
	}

	private void CacheSnapPoints()
	{
		if (_snapPoints.Count > 0)
		{
			return;
		}
		Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(true);
		foreach (Transform val in componentsInChildren)
		{
			if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)((Component)this).transform && ((Object)val).name.ToLowerInvariant().Contains("snap"))
			{
				_snapPoints.Add(val);
			}
		}
	}

	private static Transform FindChildByName(Transform root, string childName)
	{
		if ((Object)(object)root == (Object)null || string.IsNullOrEmpty(childName))
		{
			return null;
		}
		Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			if ((Object)(object)componentsInChildren[i] != (Object)null && ((Object)componentsInChildren[i]).name == childName)
			{
				return componentsInChildren[i];
			}
		}
		return null;
	}

	private static int CalculateGroupSignature(List<ConnectedLightControl> group)
	{
		int num = 17;
		for (int i = 0; i < group.Count; i++)
		{
			num = num * 31 + ((Object)group[i]).GetInstanceID();
		}
		return num;
	}

	private static int CompareStable(ConnectedLightControl a, ConnectedLightControl b)
	{
		//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_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_0020: 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_0062: Unknown result type (might be due to invalid IL or missing references)
		Vector3 position = ((Component)a).transform.position;
		Vector3 position2 = ((Component)b).transform.position;
		int num = position.x.CompareTo(position2.x);
		if (num != 0)
		{
			return num;
		}
		num = position.z.CompareTo(position2.z);
		if (num != 0)
		{
			return num;
		}
		num = position.y.CompareTo(position2.y);
		if (num != 0)
		{
			return num;
		}
		return ((Object)a).GetInstanceID().CompareTo(((Object)b).GetInstanceID());
	}

	private bool IsLiveInstance()
	{
		EnsureNetworkView();
		return (Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.GetZDO() != null;
	}

	private void EnsureNetworkView()
	{
		if ((Object)(object)_nview == (Object)null)
		{
			_nview = ((Component)this).GetComponent<ZNetView>();
		}
	}

	private bool ReadNetworkMode(bool force)
	{
		EnsureNetworkView();
		if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
		{
			return false;
		}
		ZDO zDO = _nview.GetZDO();
		if (zDO == null)
		{
			return false;
		}
		int num = zDO.GetInt("mf_connected_light_version", 0);
		if (!force && num <= _modeVersion)
		{
			return false;
		}
		int num2 = zDO.GetInt("mf_connected_light_mode", 0);
		if (num2 < 0 || num2 > 4)
		{
			num2 = 0;
		}
		LightMode lightMode = (LightMode)num2;
		bool result = _mode != lightMode || _modeVersion != num;
		_mode = lightMode;
		_modeVersion = num;
		return result;
	}

	private void WriteNetworkMode()
	{
		EnsureNetworkView();
		if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
		{
			return;
		}
		if (!_nview.IsOwner())
		{
			MethodInfo method = typeof(ZNetView).GetMethod("ClaimOwnership", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method != null)
			{
				try
				{
					method.Invoke(_nview, null);
				}
				catch
				{
				}
			}
		}
		ZDO zDO = _nview.GetZDO();
		if (zDO != null)
		{
			zDO.Set("mf_connected_light_mode", (int)_mode);
			zDO.Set("mf_connected_light_version", _modeVersion);
		}
	}
}
public class IcicleLampFlow : MonoBehaviour, Interactable, Hoverable
{
	public enum AnimationSelection
	{
		AllAnimations,
		DiagonalLeftToRight,
		DiagonalRightToLeft,
		FreezeFill,
		RandomDrops,
		FallingStars,
		Sparkles,
		DrippingSnow,
		CascadeChase,
		TwinkleBlast,
		MultiModeFlashing
	}

	private enum AnimationPhase
	{
		DiagonalLineLeftToRight,
		DiagonalLineRightToLeft,
		FreezeFill,
		RandomDrops,
		FallingStars,
		SparkleFinale,
		DrippingSnow,
		CascadeChase,
		TwinkleBlast,
		MultiModeFlashing
	}

	private class Column
	{
		public List<Renderer> bulbs = new List<Renderer>();

		public List<MaterialPropertyBlock> mpb = new List<MaterialPropertyBlock>();
	}

	private class RandomDrop
	{
		public int columnIndex;

		public int startStep;
	}

	private class FallingStar
	{
		public int centerColumn;

		public int startDelay;
	}

	private class LinkedMember
	{
		public IcicleLampFlow flow;

		public bool reverseColumns;
	}

	[Header("Target naming")]
	public string columnNamePrefix = "Icicle_Lamp_";

	public string bulbNamePrefix = "Light_";

	public string leftSnapName = "Snappoint_Left";

	public string rightSnapName = "Snappoint_Right";

	[Header("Look")]
	public Color dripColor = new Color(0.6f, 0.85f, 1f);

	[Min(0f)]
	public float emissionIntensity = 4.5f;

	public bool affectBaseColor = false;

	[Header("Timing")]
	[Min(0.01f)]
	public float raindropStepSeconds = 0.05f;

	[Min(0.01f)]
	public float diagonalLineStepSeconds = 0.1f;

	[Min(0.01f)]
	public float freezeFillStepSeconds = 0.12f;

	[Min(0.01f)]
	public float fallingStarStepSeconds = 0.06f;

	[Min(0.01f)]
	public float sparkleStepSeconds = 0.08f;

	[Min(0.01f)]
	public float drippingStepSeconds = 0.08f;

	[Min(0.01f)]
	public float cascadeStepSeconds = 0.08f;

	[Min(0.01f)]
	public float twinkleStepSeconds = 0.08f;

	[Min(0.01f)]
	public float multiModeStepSeconds = 0.08f;

	[Min(0f)]
	public float pauseBetweenAnimations = 0.6f;

	[Header("Random animations")]
	[Range(1f, 16f)]
	public int randomDropCount = 8;

	[Range(1f, 3f)]
	public int fallingStarCount = 3;

	[Range(0.01f, 1f)]
	public float sparkleChance = 0.12f;

	[Min(1f)]
	public int sparkleSteps = 24;

	[Range(1f, 5f)]
	public int diagonalLineCount = 3;

	[Min(8f)]
	public int twinkleBlastSteps = 48;

	[Min(8f)]
	public int multiModeStepsPerPattern = 24;

	[Header("Connected lamps")]
	[Min(0.05f)]
	public float connectionDistance = 0.75f;

	[Min(0.05f)]
	public float connectionRefreshSeconds = 0.25f;

	[Header("Advanced")]
	public bool includeInactive = true;

	[Header("Performance")]
	[Min(0.01f)]
	public float minUpdateInterval = 0.01f;

	[Min(0f)]
	public float activeDistance = 60f;

	private const int StarWidth = 5;

	private const int StarHeight = 5;

	private const string ModeZdoKey = "mf_icicle_animation_mode";

	private const string ModeVersionZdoKey = "mf_icicle_animation_version";

	private static readonly int[,] StarMask = new int[5, 5]
	{
		{ 0, 0, 1, 0, 0 },
		{ 1, 0, 1, 0, 1 },
		{ 0, 1, 1, 1, 0 },
		{ 1, 1, 1, 1, 1 },
		{ 0, 1, 0, 1, 0 }
	};

	private static readonly List<IcicleLampFlow> Instances = new List<IcicleLampFlow>();

	private readonly List<Column> _columns = new List<Column>();

	private readonly List<Column> _animationColumns = new List<Column>();

	private readonly List<LinkedMember> _linkedMembers = new List<LinkedMember>();

	private readonly List<RandomDrop> _randomDrops = new List<RandomDrop>();

	private readonly List<FallingStar> _fallingStars = new List<FallingStar>();

	private ZNetView _nview;

	private Transform _leftSnap;

	private Transform _rightSnap;

	private float _gammaIntensity;

	private int _colorId;

	private int _emissId;

	private float _accum;

	private bool _isActive;

	private bool _isGroupLeader = true;

	private AnimationSelection _selectedMode = AnimationSelection.AllAnimations;

	private int _modeVersion;

	private AnimationPhase _phase;

	private int _step = -1;

	private int _maxBulbCount;

	private int _diagonalLineStepCount;

	private int _cascadeStepCount;

	private int _randomDropStepCount;

	private int _fallingStarStepCount;

	private int _groupSignature;

	private int _linkedLampCount = 1;

	private float _nextStepTime;

	private float _nextConnectionRefresh;

	private void Awake()
	{
		_colorId = Shader.PropertyToID("_Color");
		_emissId = Shader.PropertyToID("_EmissionColor");
		_gammaIntensity = Mathf.LinearToGammaSpace(Mathf.Max(0f, emissionIntensity));
		CacheSnapPoints();
		BuildColumns();
		UseLocalAnimationGrid();
		InstallInteractionProxies();
		EnsureNetworkView();
	}

	private void Start()
	{
		EnsureNetworkView();
		ReadNetworkSelection(force: true);
	}

	private void OnEnable()
	{
		if (!Instances.Contains(this))
		{
			Instances.Add(this);
		}
		CacheSnapPoints();
		InstallInteractionProxies();
		PrepareMPBs();
		SetLocalAllOff();
		_accum = 0f;
		_isActive = false;
		_nextConnectionRefresh = 0f;
	}

	private void OnDisable()
	{
		Instances.Remove(this);
		SetLocalAllOff();
		_isActive = false;
	}

	private void Update()
	{
		EnsureNetworkView();
		ReadNetworkSelection(force: false);
		float time = Time.time;
		if (time >= _nextConnectionRefresh)
		{
			_nextConnectionRefresh = time + Mathf.Max(0.05f, connectionRefreshSeconds);
			RefreshLinkedGroup(time);
		}
		if (!_isGroupLeader || _animationColumns.Count == 0)
		{
			return;
		}
		if (!IsPlayerNearLinkedGroup())
		{
			if (_isActive)
			{
				SetAllOff();
				_isActive = false;
			}
			return;
		}
		if (!_isActive)
		{
			_isActive = true;
			ResetSequence(time);
		}
		_accum += Time.deltaTime;
		if (_accum < minUpdateInterval)
		{
			return;
		}
		_accum = 0f;
		if (!(time < _nextStepTime))
		{
			switch (_phase)
			{
			case AnimationPhase.DiagonalLineLeftToRight:
				AdvanceDiagonalLine(time, reverse: false);
				break;
			case AnimationPhase.DiagonalLineRightToLeft:
				AdvanceDiagonalLine(time, reverse: true);
				break;
			case AnimationPhase.FreezeFill:
				AdvanceFreezeFill(time);
				break;
			case AnimationPhase.RandomDrops:
				AdvanceRandomDrops(time);
				break;
			case AnimationPhase.FallingStars:
				AdvanceFallingStars(time);
				break;
			case AnimationPhase.SparkleFinale:
				AdvanceSparkleFinale(time);
				break;
			case AnimationPhase.DrippingSnow:
				AdvanceDrippingSnow(time);
				break;
			case AnimationPhase.CascadeChase:
				AdvanceCascadeChase(time);
				break;
			case AnimationPhase.TwinkleBlast:
				AdvanceTwinkleBlast(time);
				break;
			case AnimationPhase.MultiModeFlashing:
				AdvanceMultiModeFlashing(time);
				break;
			}
		}
	}

	public bool Interact(Humanoid user, bool hold, bool alt)
	{
		if (hold)
		{
			return false;
		}
		List<LinkedMember> list = BuildOrderedGroup(this);
		int highestVersion;
		AnimationSelection current = ResolveGroupSelection(list, out highestVersion);
		AnimationSelection nextSelection = GetNextSelection(current);
		int version = highestVersion + 1;
		for (int i = 0; i < list.Count; i++)
		{
			list[i].flow.ApplySelection(nextSelection, version, persist: true);
		}
		return true;
	}

	public bool UseItem(Humanoid user, ItemData item)
	{
		return false;
	}

	public string GetHoverName()
	{
		return "Icicle Christmas Lights";
	}

	public float GetHoverOffset()
	{
		return 0f;
	}

	public string GetHoverText()
	{
		return "[<color=yellow><b>E</b></color>] Change animation\nMode: <color=orange>" + GetSelectionName(_selectedMode) + "</color>\nLinked lamps: " + Mathf.Max(1, _linkedLampCount);
	}

	private void AdvanceDiagonalLine(float now, bool reverse)
	{
		_step++;
		if (_step < _diagonalLineStepCount)
		{
			SetDiagonalLines(_step, reverse);
			_nextStepTime = now + Mathf.Max(0.01f, diagonalLineStepSeconds);
		}
		else
		{
			CompletePhase((!reverse) ? AnimationPhase.DiagonalLineRightToLeft : AnimationPhase.FreezeFill, now);
		}
	}

	private void AdvanceFreezeFill(float now)
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		_step++;
		if (_step < _maxBulbCount)
		{
			for (int i = 0; i < _animationColumns.Count; i++)
			{
				SetColumnThrough(_animationColumns[i], _step, dripColor);
			}
			_nextStepTime = now + Mathf.Max(0.01f, freezeFillStepSeconds);
		}
		else
		{
			CompletePhase(AnimationPhase.RandomDrops, now);
		}
	}

	private void AdvanceRandomDrops(float now)
	{
		_step++;
		if (_step == 0)
		{
			PrepareRandomDrops();
		}
		if (_step < _randomDropStepCount)
		{
			SetRandomDrops(_step);
			_nextStepTime = now + Mathf.Max(0.01f, raindropStepSeconds);
		}
		else
		{
			CompletePhase(AnimationPhase.FallingStars, now);
		}
	}

	private void AdvanceFallingStars(float now)
	{
		_step++;
		if (_step == 0)
		{
			PrepareFallingStars();
		}
		if (_step < _fallingStarStepCount)
		{
			SetFallingStars(_step);
			_nextStepTime = now + Mathf.Max(0.01f, fallingStarStepSeconds);
		}
		else
		{
			CompletePhase(AnimationPhase.SparkleFinale, now);
		}
	}

	private void AdvanceSparkleFinale(float now)
	{
		_step++;
		if (_step < Mathf.Max(1, sparkleSteps))
		{
			SetRandomSparkles();
			_nextStepTime = now + Mathf.Max(0.01f, sparkleStepSeconds);
		}
		else
		{
			CompletePhase(AnimationPhase.DrippingSnow, now);
		}
	}

	private void AdvanceDrippingSnow(float now)
	{
		_step++;
		int num = Mathf.Max(12, _maxBulbCount * 4 + 8);
		if (_step < num)
		{
			SetDrippingSnow(_step);
			_nextStepTime = now + Mathf.Max(0.01f, drippingStepSeconds);
		}
		else
		{
			CompletePhase(AnimationPhase.CascadeChase, now);
		}
	}

	private void AdvanceCascadeChase(float now)
	{
		_step++;
		if (_step < _cascadeStepCount)
		{
			SetCascadeChase(_step);
			_nextStepTime = now + Mathf.Max(0.01f, cascadeStepSeconds);
		}
		else
		{
			CompletePhase(AnimationPhase.TwinkleBlast, now);
		}
	}

	private void AdvanceTwinkleBlast(float now)
	{
		_step++;
		if (_step < Mathf.Max(8, twinkleBlastSteps))
		{
			SetTwinkleBlast(_step);
			_nextStepTime = now + Mathf.Max(0.01f, twinkleStepSeconds);
		}
		else
		{
			CompletePhase(AnimationPhase.MultiModeFlashing, now);
		}
	}

	private void AdvanceMultiModeFlashing(float now)
	{
		_step++;
		int num = Mathf.Max(8, multiModeStepsPerPattern);
		int num2 = num * 8;
		if (_step < num2)
		{
			SetMultiModePattern(_step, num);
			_nextStepTime = now + Mathf.Max(0.01f, multiModeStepSeconds);
		}
		else
		{
			CompletePhase(AnimationPhase.DiagonalLineLeftToRight, now);
		}
	}

	private void CompletePhase(AnimationPhase allAnimationsNextPhase, float now)
	{
		SetAllOff();
		_phase = ((_selectedMode == AnimationSelection.AllAnimations) ? allAnimationsNextPhase : GetSelectedPhase(_selectedMode));
		_step = -1;
		_nextStepTime = now + Mathf.Max(0f, pauseBetweenAnimations);
	}

	private void ResetSequence(float now)
	{
		SetAllOff();
		_randomDrops.Clear();
		_fallingStars.Clear();
		_phase = GetSelectedPhase(_selectedMode);
		_step = -1;
		_nextStepTime = now;
	}

	private static AnimationSelection GetNextSelection(AnimationSelection current)
	{
		if (current >= AnimationSelection.MultiModeFlashing)
		{
			return AnimationSelection.AllAnimations;
		}
		return current + 1;
	}

	private static AnimationPhase GetSelectedPhase(AnimationSelection selection)
	{
		return selection switch
		{
			AnimationSelection.DiagonalRightToLeft => AnimationPhase.DiagonalLineRightToLeft, 
			AnimationSelection.FreezeFill => AnimationPhase.FreezeFill, 
			AnimationSelection.RandomDrops => AnimationPhase.RandomDrops, 
			AnimationSelection.FallingStars => AnimationPhase.FallingStars, 
			AnimationSelection.Sparkles => AnimationPhase.SparkleFinale, 
			AnimationSelection.DrippingSnow => AnimationPhase.DrippingSnow, 
			AnimationSelection.CascadeChase => AnimationPhase.CascadeChase, 
			AnimationSelection.TwinkleBlast => AnimationPhase.TwinkleBlast, 
			AnimationSelection.MultiModeFlashing => AnimationPhase.MultiModeFlashing, 
			_ => AnimationPhase.DiagonalLineLeftToRight, 
		};
	}

	private static string GetSelectionName(AnimationSelection selection)
	{
		return selection switch
		{
			AnimationSelection.DiagonalLeftToRight => "Diagonal Line Left to Right", 
			AnimationSelection.DiagonalRightToLeft => "Diagonal Line Right to Left", 
			AnimationSelection.FreezeFill => "Freeze Fill", 
			AnimationSelection.RandomDrops => "Random Raindrops", 
			AnimationSelection.FallingStars => "Falling Stars", 
			AnimationSelection.Sparkles => "Random Sparkles", 
			AnimationSelection.DrippingSnow => "Dripping / Falling Snow", 
			AnimationSelection.CascadeChase => "Cascading / Chasing", 
			AnimationSelection.TwinkleBlast => "Twinkling / Blasting", 
			AnimationSelection.MultiModeFlashing => "8-Pattern Flashing", 
			_ => "All Animations", 
		};
	}

	private void ApplySelection(AnimationSelection selection, int version, bool persist)
	{
		bool flag = _selectedMode != selection || _modeVersion != version;
		_selectedMode = selection;
		_modeVersion = version;
		if (persist)
		{
			WriteNetworkSelection();
		}
		if (flag)
		{
			_isActive = false;
		}
	}

	private void EnsureNetworkView()
	{
		if ((Object)(object)_nview == (Object)null)
		{
			_nview = ((Component)this).GetComponent<ZNetView>();
		}
	}

	private bool ReadNetworkSelection(bool force)
	{
		EnsureNetworkView();
		if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
		{
			return false;
		}
		ZDO zDO = _nview.GetZDO();
		if (zDO == null)
		{
			return false;
		}
		int num = zDO.GetInt("mf_icicle_animation_version", 0);
		if (!force && num <= _modeVersion)
		{
			return false;
		}
		int num2 = zDO.GetInt("mf_icicle_animation_mode", 0);
		if (num2 < 0 || num2 > 10)
		{
			num2 = 0;
		}
		AnimationSelection animationSelection = (AnimationSelection)num2;
		bool flag = _selectedMode != animationSelection || _modeVersion != num;
		_selectedMode = animationSelection;
		_modeVersion = num;
		if (flag)
		{
			_isActive = false;
		}
		return flag;
	}

	private void WriteNetworkSelection()
	{
		EnsureNetworkView();
		if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
		{
			return;
		}
		if (!_nview.IsOwner())
		{
			MethodInfo method = typeof(ZNetView).GetMethod("ClaimOwnership", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method != null)
			{
				try
				{
					method.Invoke(_nview, null);
				}
				catch
				{
				}
			}
		}
		ZDO zDO = _nview.GetZDO();
		if (zDO != null)
		{
			zDO.Set("mf_icicle_animation_mode", (int)_selectedMode);
			zDO.Set("mf_icicle_animation_version", _modeVersion);
		}
	}

	private void RefreshLinkedGroup(float now)
	{
		List<LinkedMember> list = BuildOrderedGroup(this);
		_linkedLampCount = Mathf.Max(1, list.Count);
		bool isGroupLeader = _isGroupLeader;
		_isGroupLeader = list.Count == 0 || (Object)(object)list[0].flow == (Object)(object)this;
		if (!_isGroupLeader)
		{
			if (isGroupLeader)
			{
				_isActive = false;
			}
			return;
		}
		if (!isGroupLeader)
		{
			_isActive = false;
		}
		int highestVersion;
		AnimationSelection animationSelection = ResolveGroupSelection(list, out highestVersion);
		for (int i = 0; i < list.Count; i++)
		{
			IcicleLampFlow flow = list[i].flow;
			if (flow._selectedMode != animationSelection || flow._modeVersion != highestVersion)
			{
				flow.ApplySelection(animationSelection, highestVersion, persist: true);
			}
		}
		int num = CalculateGroupSignature(list);
		if (num != _groupSignature)
		{
			SetAllOff();
			_linkedMembers.Clear();
			_linkedMembers.AddRange(list);
			RebuildAnimationGrid();
			_groupSignature = num;
			_isActive = false;
			_nextStepTime = now;
		}
	}

	private static AnimationSelection ResolveGroupSelection(List<LinkedMember> group, out int highestVersion)
	{
		highestVersion = 0;
		AnimationSelection result = AnimationSelection.AllAnimations;
		for (int i = 0; i < group.Count; i++)
		{
			IcicleLampFlow flow = group[i].flow;
			flow.ReadNetworkSelection(force: false);
			if (i == 0 || flow._modeVersion > highestVersion)
			{
				highestVersion = flow._modeVersion;
				result = flow._selectedMode;
			}
		}
		return result;
	}

	private static int CalculateGroupSignature(List<LinkedMember> group)
	{
		int num = 17;
		for (int i = 0; i < group.Count; i++)
		{
			num = num * 31 + ((Object)group[i].flow).GetInstanceID();
			num = num * 31 + (group[i].reverseColumns ? 1 : 0);
		}
		return num;
	}

	private void RebuildAnimationGrid()
	{
		_animationColumns.Clear();
		for (int i = 0; i < _linkedMembers.Count; i++)
		{
			LinkedMember linkedMember = _linkedMembers[i];
			if (linkedMember.reverseColumns)
			{
				for (int num = linkedMember.flow._columns.Count - 1; num >= 0; num--)
				{
					_animationColumns.Add(linkedMember.flow._columns[num]);
				}
			}
			else
			{
				for (int j = 0; j < linkedMember.flow._columns.Count; j++)
				{
					_animationColumns.Add(linkedMember.flow._columns[j]);
				}
			}
		}
		RecalculateAnimationGrid();
	}

	private void UseLocalAnimationGrid()
	{
		_animationColumns.Clear();
		for (int i = 0; i < _columns.Count; i++)
		{
			_animationColumns.Add(_columns[i]);
		}
		RecalculateAnimationGrid();
	}

	private void RecalculateAnimationGrid()
	{
		_maxBulbCount = 0;
		_cascadeStepCount = 0;
		for (int i = 0; i < _animationColumns.Count; i++)
		{
			int count = _animationColumns[i].bulbs.Count;
			if (count > _maxBulbCount)
			{
				_maxBulbCount = count;
			}
			_cascadeStepCount += count;
		}
		int num = Mathf.Max(1, Mathf.CeilToInt((float)_animationColumns.Count * 0.5f));
		int num2 = Mathf.Max(1, diagonalLineCount);
		_diagonalLineStepCount = _animationColumns.Count + _maxBulbCount + num * (num2 - 1);
		_cascadeStepCount += _animationColumns.Count + 2;
	}

	private bool IsPlayerNearLinkedGroup()
	{
		//IL_007b: 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)
		if (activeDistance <= 0f)
		{
			return true;
		}
		for (int i = 0; i < _linkedMembers.Count; i++)
		{
			IcicleLampFlow flow = _linkedMembers[i].flow;
			if ((Object)(object)flow != (Object)null && Player.IsPlayerInRange(((Component)flow).transform.position, activeDistance))
			{
				return true;
			}
		}
		return Player.IsPlayerInRange(((Component)this).transform.position, activeDistance);
	}

	private static List<LinkedMember> BuildOrderedGroup(IcicleLampFlow origin)
	{
		List<IcicleLampFlow> list = GatherConnectedFlows(origin);
		list.Sort(CompareStable);
		List<LinkedMember> list2 = new List<LinkedMember>();
		if (list.Count == 0)
		{
			return list2;
		}
		IcicleLampFlow icicleLampFlow = list[0];
		for (int i = 0; i < list.Count; i++)
		{
			if (GetConnectionDegree(list[i], list) <= 1)
			{
				icicleLampFlow = list[i];
				break;
			}
		}
		bool neighborEndpointIsRight;
		bool flag = (Object)(object)GetNeighborAtEndpoint(icicleLampFlow, useRightEndpoint: false, list, null, out neighborEndpointIsRight) != (Object)null;
		bool neighborEndpointIsRight2;
		bool flag2 = (Object)(object)GetNeighborAtEndpoint(icicleLampFlow, useRightEndpoint: true, list, null, out neighborEndpointIsRight2) != (Object)null || !flag;
		HashSet<IcicleLampFlow> hashSet = new HashSet<IcicleLampFlow>();
		IcicleLampFlow icicleLampFlow2 = icicleLampFlow;
		IcicleLampFlow excluded = null;
		while ((Object)(object)icicleLampFlow2 != (Object)null && !hashSet.Contains(icicleLampFlow2))
		{
			hashSet.Add(icicleLampFlow2);
			LinkedMember linkedMember = new LinkedMember();
			linkedMember.flow = icicleLampFlow2;
			linkedMember.reverseColumns = !flag2;
			list2.Add(linkedMember);
			bool neighborEndpointIsRight3;
			IcicleLampFlow neighborAtEndpoint = GetNeighborAtEndpoint(icicleLampFlow2, flag2, list, excluded, out neighborEndpointIsRight3);
			if ((Object)(object)neighborAtEndpoint == (Object)null || hashSet.Contains(neighborAtEndpoint))
			{
				break;
			}
			excluded = icicleLampFlow2;
			icicleLampFlow2 = neighborAtEndpoint;
			flag2 = !neighborEndpointIsRight3;
		}
		for (int j = 0; j < list.Count; j++)
		{
			if (!hashSet.Contains(list[j]))
			{
				LinkedMember linkedMember2 = new LinkedMember();
				linkedMember2.flow = list[j];
				linkedMember2.reverseColumns = false;
				list2.Add(linkedMember2);
			}
		}
		return list2;
	}

	private static List<IcicleLampFlow> GatherConnectedFlows(IcicleLampFlow origin)
	{
		List<IcicleLampFlow> list = new List<IcicleLampFlow>();
		if ((Object)(object)origin == (Object)null)
		{
			return list;
		}
		list.Add(origin);
		if (!origin.IsSceneInstance())
		{
			return list;
		}
		Queue<IcicleLampFlow> queue = new Queue<IcicleLampFlow>();
		HashSet<IcicleLampFlow> hashSet = new HashSet<IcicleLampFlow>();
		queue.Enqueue(origin);
		hashSet.Add(origin);
		while (queue.Count > 0)
		{
			IcicleLampFlow icicleLampFlow = queue.Dequeue();
			for (int i = 0; i < Instances.Count; i++)
			{
				IcicleLampFlow icicleLampFlow2 = Instances[i];
				if (!((Object)(object)icicleLampFlow2 == (Object)null) && !((Object)(object)icicleLampFlow2 == (Object)(object)icicleLampFlow) && !hashSet.Contains(icicleLampFlow2) && ((Behaviour)icicleLampFlow2).isActiveAndEnabled && icicleLampFlow2.IsSceneInstance() && AreConnected(icicleLampFlow, icicleLampFlow2))
				{
					hashSet.Add(icicleLampFlow2);
					list.Add(icicleLampFlow2);
					queue.Enqueue(icicleLampFlow2);
				}
			}
		}
		return list;
	}

	private static bool AreConnected(IcicleLampFlow a, IcicleLampFlow b)
	{
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: 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)
		a.CacheSnapPoints();
		b.CacheSnapPoints();
		float num = Mathf.Max(a.connectionDistance, b.connectionDistance);
		float num2 = num * num;
		Transform[] array = (Transform[])(object)new Transform[2] { a._leftSnap, a._rightSnap };
		Transform[] array2 = (Transform[])(object)new Transform[2] { b._leftSnap, b._rightSnap };
		for (int i = 0; i < array.Length; i++)
		{
			if ((Object)(object)array[i] == (Object)null)
			{
				continue;
			}
			for (int j = 0; j < array2.Length; j++)
			{
				if (!((Object)(object)array2[j] == (Object)null))
				{
					Vector3 val = array[i].position - array2[j].position;
					if (((Vector3)(ref val)).sqrMagnitude <= num2)
					{
						return true;
					}
				}
			}
		}
		return false;
	}

	private static int GetConnectionDegree(IcicleLampFlow flow, List<IcicleLampFlow> group)
	{
		HashSet<IcicleLampFlow> hashSet = new HashSet<IcicleLampFlow>();
		bool neighborEndpointIsRight;
		IcicleLampFlow neighborAtEndpoint = GetNeighborAtEndpoint(flow, useRightEndpoint: false, group, null, out neighborEndpointIsRight);
		if ((Object)(object)neighborAtEndpoint != (Object)null)
		{
			hashSet.Add(neighborAtEndpoint);
		}
		bool neighborEndpointIsRight2;
		IcicleLampFlow neighborAtEndpoint2 = GetNeighborAtEndpoint(flow, useRightEndpoint: true, group, null, out neighborEndpointIsRight2);
		if ((Object)(object)neighborAtEndpoint2 != (Object)null)
		{
			hashSet.Add(neighborAtEndpoint2);
		}
		return hashSet.Count;
	}

	private static IcicleLampFlow GetNeighborAtEndpoint(IcicleLampFlow flow, bool useRightEndpoint, List<IcicleLampFlow> group, IcicleLampFlow excluded, out bool neighborEndpointIsRight)
	{
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: 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)
		neighborEndpointIsRight = false;
		flow.CacheSnapPoints();
		Transform val = (useRightEndpoint ? flow._rightSnap : flow._leftSnap);
		if ((Object)(object)val == (Object)null)
		{
			return null;
		}
		IcicleLampFlow result = null;
		float num = float.PositiveInfinity;
		for (int i = 0; i < group.Count; i++)
		{
			IcicleLampFlow icicleLampFlow = group[i];
			if ((Object)(object)icicleLampFlow == (Object)null || (Object)(object)icicleLampFlow == (Object)(object)flow || (Object)(object)icicleLampFlow == (Object)(object)excluded)
			{
				continue;
			}
			icicleLampFlow.CacheSnapPoints();
			Transform[] array = (Transform[])(object)new Transform[2] { icicleLampFlow._leftSnap, icicleLampFlow._rightSnap };
			for (int j = 0; j < array.Length; j++)
			{
				Transform val2 = array[j];
				if (!((Object)(object)val2 == (Object)null))
				{
					float num2 = Mathf.Max(flow.connectionDistance, icicleLampFlow.connectionDistance);
					Vector3 val3 = val.position - val2.position;
					float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
					if (!(sqrMagnitude > num2 * num2) && !(sqrMagnitude >= num))
					{
						result = icicleLampFlow;
						num = sqrMagnitude;
						neighborEndpointIsRight = j == 1;
					}
				}
			}
		}
		return result;
	}

	private static int CompareStable(IcicleLampFlow a, IcicleLampFlow b)
	{
		//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_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_0020: 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_0065: Unknown result type (might be due to invalid IL or missing references)
		Vector3 position = ((Component)a).transform.position;
		Vector3 position2 = ((Component)b).transform.position;
		int num = position.x.CompareTo(position2.x);
		if (num != 0)
		{
			return num;
		}
		num = position.z.CompareTo(position2.z);
		if (num != 0)
		{
			return num;
		}
		num = position.y.CompareTo(position2.y);
		if (num != 0)
		{
			return num;
		}
		num = string.CompareOrdinal(((Object)((Component)a).gameObject).name, ((Object)((Component)b).gameObject).name);
		if (num != 0)
		{
			return num;
		}
		return ((Object)a).GetInstanceID().CompareTo(((Object)b).GetInstanceID());
	}

	private bool IsSceneInstance()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		int result;
		if ((Object)(object)((Component)this).gameObject != (Object)null)
		{
			Scene scene = ((Component)this).gameObject.scene;
			result = (((Scene)(ref scene)).IsValid() ? 1 : 0);
		}
		else
		{
			result = 0;
		}
		return (byte)result != 0;
	}

	private void CacheSnapPoints()
	{
		if ((Object)(object)_leftSnap == (Object)null)
		{
			_leftSnap = FindChildByName(((Component)this).transform, leftSnapName);
		}
		if ((Object)(object)_rightSnap == (Object)null)
		{
			_rightSnap = FindChildByName(((Component)this).transform, rightSnapName);
		}
		if ((Object)(object)_leftSnap == (Object)null)
		{
			_leftSnap = FindSnapPointBySide(((Component)this).transform, "left");
		}
		if ((Object)(object)_rightSnap == (Object)null)
		{
			_rightSnap = FindSnapPointBySide(((Component)this).transform, "right");
		}
	}

	private static Transform FindChildByName(Transform root, string childName)
	{
		if ((Object)(object)root == (Object)null || string.IsNullOrEmpty(childName))
		{
			return null;
		}
		Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
		foreach (Transform val in componentsInChildren)
		{
			if ((Object)(object)val != (Object)null && string.Equals(((Object)val).name, childName, StringComparison.OrdinalIgnoreCase))
			{
				return val;
			}
		}
		return null;
	}

	private static Transform FindSnapPointBySide(Transform root, string side)
	{
		if ((Object)(object)root == (Object)null || string.IsNullOrEmpty(side))
		{
			return null;
		}
		Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
		foreach (Transform val in componentsInChildren)
		{
			if (!((Object)(object)val == (Object)null))
			{
				string text = ((Object)val).name.ToLowerInvariant();
				if (text.Contains("snap") && text.Contains(side))
				{
					return val;
				}
			}
		}
		return null;
	}

	private void InstallInteractionProxies()
	{
		Collider[] componentsInChildren = ((Component)this).GetComponentsInChildren<Collider>(true);
		foreach (Collider val in componentsInChildren)
		{
			if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)(object)((Component)this).gameObject))
			{
				IcicleLampInteractionProxy icicleLampInteractionProxy = ((Component)val).GetComponent<IcicleLampInteractionProxy>() ?? ((Component)val).gameObject.AddComponent<IcicleLampInteractionProxy>();
				icicleLampInteractionProxy.Configure(this);
			}
		}
	}

	private void PrepareRandomDrops()
	{
		_randomDrops.Clear();
		_randomDropStepCount = 0;
		List<int> list = new List<int>();
		for (int i = 0; i < _animationColumns.Count; i++)
		{
			list.Add(i);
		}
		int num = Mathf.Min(Mathf.Max(1, randomDropCount), list.Count);
		for (int j = 0; j < num; j++)
		{
			int index = Random.Range(0, list.Count);
			int num2 = list[index];
			list.RemoveAt(index);
			RandomDrop randomDrop = new RandomDrop();
			randomDrop.columnIndex = num2;
			randomDrop.startStep = Random.Range(0, 6);
			_randomDrops.Add(randomDrop);
			int num3 = randomDrop.startStep + _animationColumns[num2].bulbs.Count;
			if (num3 > _randomDropStepCount)
			{
				_randomDropStepCount = num3;
			}
		}
	}

	private void PrepareFallingStars()
	{
		_fallingStars.Clear();
		_fallingStarStepCount = 0;
		List<int> list = new List<int>();
		int num = 2;
		for (int i = num; i < _animationColumns.Count - num; i++)
		{
			list.Add(i);
		}
		int num2 = 0;
		int num3 = Mathf.Min(Mathf.Max(1, fallingStarCount), list.Count);
		while (_fallingStars.Count < num3 && list.Count > 0)
		{
			int index = Random.Range(0, list.Count);
			FallingStar fallingStar = new FallingStar();
			fallingStar.centerColumn = list[index];
			fallingStar.startDelay = _fallingStars.Count * 3 + Random.Range(0, 3);
			_fallingStars.Add(fallingStar);
			for (int num4 = list.Count - 1; num4 >= 0; num4--)
			{
				if (Mathf.Abs(list[num4] - fallingStar.centerColumn) < 5)
				{
					list.RemoveAt(num4);
				}
			}
			if (fallingStar.startDelay > num2)
			{
				num2 = fallingStar.startDelay;
			}
		}
		_fallingStarStepCount = _maxBulbCount + 5 - 1 + num2;
	}

	private void SetRandomDrops(int step)
	{
		//IL_008f: 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)
		for (int i = 0; i < _animationColumns.Count; i++)
		{
			Column column = _animationColumns[i];
			int num = -1;
			for (int j = 0; j < _randomDrops.Count; j++)
			{
				RandomDrop randomDrop = _randomDrops[j];
				if (randomDrop.columnIndex == i)
				{
					num = step - randomDrop.startStep;
					break;
				}
			}
			if (num >= 0 && num < column.bulbs.Count)
			{
				SetColumnActive(column, num, dripColor);
			}
			else
			{
				SetColumnAll(column, Color.black);
			}
		}
	}

	private void SetFallingStars(int step)
	{
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		int num = 2;
		for (int i = 0; i < _animationColumns.Count; i++)
		{
			Column column = _animationColumns[i];
			for (int j = 0; j < column.bulbs.Count; j++)
			{
				bool flag = false;
				for (int k = 0; k < _fallingStars.Count; k++)
				{
					if (flag)
					{
						break;
					}
					FallingStar fallingStar = _fallingStars[k];
					int num2 = i - (fallingStar.centerColumn - num);
					int num3 = step - 4 - fallingStar.startDelay;
					int num4 = j - num3;
					if (num2 >= 0 && num2 < 5 && num4 >= 0 && num4 < 5 && StarMask[num4, num2] != 0)
					{
						flag = true;
					}
				}
				SetBulb(column, j, flag ? dripColor : Color.black);
			}
		}
	}

	private void SetRandomSparkles()
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Clamp01(sparkleChance);
		for (int i = 0; i < _animationColumns.Count; i++)
		{
			Column column = _animationColumns[i];
			for (int j = 0; j < column.bulbs.Count; j++)
			{
				SetBulb(column, j, (Random.value < num) ? dripColor : Color.black);
			}
		}
	}

	private void SetDiagonalLines(int step, bool reverse)
	{
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		int count = _animationColumns.Count;
		int num = Mathf.Max(1, Mathf.CeilToInt((float)count * 0.5f));
		int num2 = Mathf.Max(1, diagonalLineCount);
		for (int i = 0; i < count; i++)
		{
			Column column = _animationColumns[i];
			for (int j = 0; j < column.bulbs.Count; j++)
			{
				bool flag = false;
				for (int k = 0; k < num2; k++)
				{
					if (flag)
					{
						break;
					}
					int num3 = step - k * num;
					int num4 = num3 - j;
					if (reverse)
					{
						num4 = count - 1 - num4;
					}
					flag = i == num4;
				}
				SetBulb(column, j, flag ? dripColor : Color.black);
			}
		}
	}

	private void SetDrippingSnow(int step)
	{
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		int num = Mathf.Max(6, _maxBulbCount + 5);
		for (int i = 0; i < _animationColumns.Count; i++)
		{
			Column column = _animationColumns[i];
			int num2 = (step + i * 3) % num - 2;
			for (int j = 0; j < column.bulbs.Count; j++)
			{
				SetBulb(column, j, dripColor * (num2 - j) switch
				{
					2 => 0.2f, 
					1 => 0.55f, 
					0 => 1f, 
					_ => 0f, 
				});
			}
		}
	}

	private void SetCascadeChase(int step)
	{
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0165: 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)
		int num = _animationColumns.Count + 2;
		if (step < num)
		{
			for (int i = 0; i < _animationColumns.Count; i++)
			{
				Column column = _animationColumns[i];
				float num2 = (step - i) switch
				{
					1 => 0.45f, 
					0 => 1f, 
					_ => 0f, 
				};
				for (int j = 0; j < column.bulbs.Count; j++)
				{
					SetBulb(column, j, (j == 0) ? (dripColor * num2) : Color.black);
				}
			}
			return;
		}
		int num3 = step - num;
		int num4 = -1;
		int num5 = -1;
		for (int k = 0; k < _animationColumns.Count; k++)
		{
			int count = _animationColumns[k].bulbs.Count;
			if (num3 < count)
			{
				num4 = k;
				num5 = num3;
				break;
			}
			num3 -= count;
		}
		for (int l = 0; l < _animationColumns.Count; l++)
		{
			Column column2 = _animationColumns[l];
			for (int m = 0; m < column2.bulbs.Count; m++)
			{
				float num6 = ((l == num4 && m == num5) ? 1f : ((l == num4 && m == num5 - 1) ? 0.45f : 0f));
				SetBulb(column2, m, dripColor * num6);
			}
		}
	}

	private void SetTwinkleBlast(int step)
	{
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		bool flag = step / 12 % 2 == 1;
		for (int i = 0; i < _animationColumns.Count; i++)
		{
			Column column = _animationColumns[i];
			for (int j = 0; j < column.bulbs.Count; j++)
			{
				float num;
				if (flag)
				{
					num = ((Mathf.Abs(step * 11 + i * 7 + j * 13) % 23 == 0) ? 1.35f : 0f);
				}
				else
				{
					float num2 = (float)step * 0.16f + (float)i * 1.37f + (float)j * 0.73f;
					float num3 = 0.5f + 0.5f * Mathf.Sin(num2);
					num = 0.05f + 0.95f * num3 * num3 * num3;
				}
				SetBulb(column, j, dripColor * num);
			}
		}
	}

	private void SetMultiModePattern(int step, int patternSteps)
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: 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_0098: Unknown result type (might be due to invalid IL or missing references)
		int num = Mathf.Clamp(step / patternSteps, 0, 7);
		int num2 = step % patternSteps;
		switch (num)
		{
		case 0:
			SetEveryBulb(dripColor);
			break;
		case 1:
		{
			float num3 = ((patternSteps <= 1) ? 0f : ((float)num2 / (float)(patternSteps - 1)));
			float num4 = 0.1f + 0.9f * (0.5f - 0.5f * Mathf.Cos(num3 * (float)Math.PI * 2f));
			SetEveryBulb(dripColor * num4);
			break;
		}
		case 2:
			SetSequentialWave(num2);
			break;
		case 3:
			SetHorizontalMainLineChase(num2);
			break;
		case 4:
			SetAlternatingStrands(num2, patternSteps);
			break;
		case 5:
			SetEveryBulb((num2 % 2 == 0) ? dripColor : Color.black);
			break;
		case 6:
			SetTwinkleBlast(num2);
			break;
		default:
			SetDrippingSnow(num2);
			break;
		}
	}

	private void SetSequentialWave(int step)
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < _animationColumns.Count; i++)
		{
			float num = 0.5f + 0.5f * Mathf.Sin((float)step * 0.55f - (float)i * 0.85f);
			SetColumnAll(_animationColumns[i], dripColor * (0.1f + 0.9f * num));
		}
	}

	private void SetHorizontalMainLineChase(int step)
	{
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		int num = Mathf.Max(1, _animationColumns.Count + 2);
		int num2 = step % num;
		for (int i = 0; i < _animationColumns.Count; i++)
		{
			Column column = _animationColumns[i];
			float num3 = (num2 - i) switch
			{
				2 => 0.2f, 
				1 => 0.55f, 
				0 => 1f, 
				_ => 0f, 
			};
			for (int j = 0; j < column.bulbs.Count; j++)
			{
				SetBulb(column, j, (j == 0) ? (dripColor * num3) : Color.black);
			}
		}
	}

	private void SetAlternatingStrands(int step, int patternSteps)
	{
		//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)
		int num = Mathf.Max(1, patternSteps / 6);
		bool flag = step / num % 2 == 0;
		for (int i = 0; i < _animationColumns.Count; i++)
		{
			bool flag2 = ((i % 2 == 0) ? flag : (!flag));
			SetColumnAll(_animationColumns[i], flag2 ? dripColor : Color.black);
		}
	}

	private void SetEveryBulb(Color color)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < _animationColumns.Count; i++)
		{
			SetColumnAll(_animationColumns[i], color);
		}
	}

	private void BuildColumns()
	{
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_0192: Expected O, but got Unknown
		_columns.Clear();
		List<Transform> list = new List<Transform>();
		Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(includeInactive);
		foreach (Transform val in componentsInChildren)
		{
			if (Object.op_Implicit((Object)(object)val) && (string.IsNullOrEmpty(columnNamePrefix) || ((Object)val).name.StartsWith(columnNamePrefix)))
			{
				list.Add(val);
			}
		}
		list.Sort((Transform a, Transform b) => string.CompareOrdinal(((Object)a).name, ((Object)b).name));
		for (int num = 0; num < list.Count; num++)
		{
			Transform val2 = list[num];
			Column column = new Column();
			Renderer[] componentsInChildren2 = ((Component)val2).GetComponentsInChildren<Renderer>(includeInactive);
			foreach (Renderer val3 in componentsInChildren2)
			{
				if (Object.op_Implicit((Object)(object)val3) && (string.IsNullOrEmpty(bulbNamePrefix) || ((Object)((Component)val3).gameObject).name.StartsWith(bulbNamePrefix)))
				{
					column.bulbs.Add(val3);
				}
			}
			if (column.bulbs.Count != 0)
			{
				column.bulbs.Sort((Renderer a, Renderer b) => string.CompareOrdinal(((Object)((Component)a).gameObject).name, ((Object)((Component)b).gameObject).name));
				for (int num3 = 0; num3 < column.bulbs.Count; num3++)
				{
					column.mpb.Add(new MaterialPropertyBlock());
				}
				_columns.Add(column);
			}
		}
	}

	private void PrepareMPBs()
	{
		for (int i = 0; i < _columns.Count; i++)
		{
			Column column = _columns[i];
			for (int j = 0; j < column.bulbs.Count; j++)
			{
				Renderer val = column.bulbs[j];
				if (Object.op_Implicit((Object)(object)val))
				{
					Material sharedMaterial = val.sharedMaterial;
					if ((Object)(object)sharedMaterial != (Object)null)
					{
						sharedMaterial.EnableKeyword("_EMISSION");
					}
					val.GetPropertyBlock(column.mpb[j]);
				}
			}
		}
	}

	private void SetColumnActive(Column col, int activeIndex, Color onColor)
	{
		//IL_0014: 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)
		for (int i = 0; i < col.bulbs.Count; i++)
		{
			SetBulb(col, i, (i == activeIndex) ? onColor : Color.black);
		}
	}

	private void SetColumnThrough(Column col, int activeIndex, Color onColor)
	{
		//IL_0014: 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)
		for (int i = 0; i < col.bulbs.Count; i++)
		{
			SetBulb(col, i, (i <= activeIndex) ? onColor : Color.black);
		}
	}

	private void SetColumnAll(Column col, Color color)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < col.bulbs.Count; i++)
		{
			SetBulb(col, i, color);
		}
	}

	private void SetBulb(Column col, int bulbIndex, Color color)
	{
		//IL_0049: 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_003b: Unknown result type (might be due to invalid IL or missing references)
		Renderer val = col.bulbs[bulbIndex];
		if (Object.op_Implicit((Object)(object)val))
		{
			MaterialPropertyBlock val2 = col.mpb[bulbIndex];
			if (affectBaseColor)
			{
				val2.SetColor(_colorId, color);
			}
			val2.SetColor(_emissId, color * _gammaIntensity);
			val.SetPropertyBlock(val2);
		}
	}

	private void SetAllOff()
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < _animationColumns.Count; i++)
		{
			SetColumnAll(_animationColumns[i], Color.black);
		}
	}

	private void SetLocalAllOff()
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < _columns.Count; i++)
		{
			SetColumnAll(_columns[i], Color.black);
		}
	}
}
public class IcicleLampInteractionProxy : MonoBehaviour, Interactable, Hoverable
{
	private IcicleLampFlow _owner;

	public void Configure(IcicleLampFlow owner)
	{
		_owner = owner;
	}

	public bool Interact(Humanoid user, bool hold, bool alt)
	{
		IcicleLampFlow owner = GetOwner();
		return (Object)(object)owner != (Object)null && owner.Interact(user, hold, alt);
	}

	public bool UseItem(Humanoid user, ItemData item)
	{
		IcicleLampFlow owner = GetOwner();
		return (Object)(object)owner != (Object)null && owner.UseItem(user, item);
	}

	public string GetHoverName()
	{
		IcicleLampFlow owner = GetOwner();
		return ((Object)(object)owner != (Object)null) ? owner.GetHoverName() : "Icicle Christmas Lights";
	}

	public float GetHoverOffset()
	{
		return 0f;
	}

	public string GetHoverText()
	{
		IcicleLampFlow owner = GetOwner();
		return ((Object)(object)owner != (Object)null) ? owner.GetHoverText() : "";
	}

	private IcicleLampFlow GetOwner()
	{
		if ((Object)(object)_owner == (Object)null)
		{
			_owner = ((Component)this).GetComponentInParent<IcicleLampFlow>();
		}
		return _owner;
	}
}
public class WrappingBoxProxy : MonoBehaviour, Interactable, Hoverable
{
	private WrappingBoxProcessor processor;

	private void Awake()
	{
		processor = ((Component)this).GetComponentInChildren<WrappingBoxProcessor>(true);
	}

	public bool Interact(Humanoid user, bool hold, bool alt)
	{
		return false;
	}

	public bool UseItem(Humanoid user, ItemData item)
	{
		return false;
	}

	public string GetHoverName()
	{
		return "Wrapper";
	}

	public float GetHoverOffset()
	{
		return 0f;
	}

	public string GetHoverText()
	{
		if ((Object)(object)processor != (Object)null && processor.CanWrap())
		{
			return "Wrapper\n[<color=yellow><b>E</b></color>] Open\n<color=orange>Close box to wrap gift</color>";
		}
		return "Wrapper\n[<color=yellow><b>E</b></color>] Open\n(Add 1 gift + 1 item)";
	}
}
public static class WrappedGiftUse
{
	public const string KEY_PREFAB = "wrapped_prefab";

	public const string KEY_STACK = "wrapped_stack";

	public const string KEY_QUALITY = "wrapped_quality";

	public const string KEY_VARIANT = "wrapped_variant";

	public const string KEY_DURABILITY = "wrapped_durability";

	public static bool OnUse(ItemData gift, Player player)
	{
		if (gift == null || (Object)(object)player == (Object)null)
		{
			return false;
		}
		Inventory inventory = ((Humanoid)player).GetInventory();
		if (inventory == null)
		{
			return false;
		}
		Dictionary<string, string> customData = gift.m_customData;
		if (customData == null || !customData.TryGetValue("wrapped_prefab", out var value))
		{
			return false;
		}
		ZNetScene instance = ZNetScene.instance;
		GameObject val = ((instance != null) ? instance.GetPrefab(value) : null);
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		ItemDrop component = val.GetComponent<ItemDrop>();
		if ((Object)(object)component == (Object)null)
		{
			return false;
		}
		int result = 1;
		int result2 = 1;
		int result3 = 0;
		float result4 = 0f;
		if (customData.TryGetValue("wrapped_stack", out var value2))
		{
			int.TryParse(value2, out result);
		}
		if (customData.TryGetValue("wrapped_quality", out value2))
		{
			int.TryParse(value2, out result2);
		}
		if (customData.TryGetValue("wrapped_variant", out value2))
		{
			int.TryParse(value2, out result3);
		}
		if (customData.TryGetValue("wrapped_durability", out value2))
		{
			float.TryParse(value2, NumberStyles.Float, CultureInfo.InvariantCulture, out result4);
		}
		ItemData val2 = component.m_itemData.Clone();
		val2.m_dropPrefab = val;
		val2.m_stack = Mathf.Max(1, result);
		val2.m_quality = Mathf.Max(1, result2);
		val2.m_variant = result3;
		if (result4 > 0f)
		{
			val2.m_durability = result4;
		}
		if (!inventory.CanAddItem(val2, -1))
		{
			return false;
		}
		inventory.AddItem(val2);
		inventory.RemoveItem(gift, 1);
		return true;
	}

	public static bool OnUse(ItemData gift)
	{
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			return false;
		}
		return OnUse(gift, localPlayer);
	}
}
public class WrappingBoxProcessor : MonoBehaviour
{
	private Container container;

	private ZNetView nview;

	private bool wasInUseLastFrame = false;

	private bool wrapInProgress = false;

	private Vector3 restLocalPosition;

	private Quaternion restLocalRotation;

	private Coroutine idleShakeCoroutine;

	private Coroutine completionAnimationCoroutine;

	private float nextIdleShakeTime;

	private const float WRAP_DELAY = 3.8f;

	private const float IDLE_SHAKE_MIN_DELAY = 4f;

	private const float IDLE_SHAKE_MAX_DELAY = 7.5f;

	private const float IDLE_SHAKE_DURATION = 0.45f;

	private const float IDLE_SHAKE_ROTATION_DEGREES = 2.25f;

	private const float IDLE_SHAKE_SIDE_DISTANCE = 0.003f;

	private const float COMPLETE_ANIMATION_DURATION = 0.9f;

	private const float COMPLETE_JUMP_HEIGHT = 0.05f;

	private const string COMPLETE_ANIMATION_RPC = "RPC_Moonforged_WrappingBoxComplete";

	private void Awake()
	{
		//IL_0021: 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_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		container = ((Component)this).GetComponentInChildren<Container>(true);
		nview = ((Component)this).GetComponent<ZNetView>();
		restLocalPosition = ((Component)this).transform.localPosition;
		restLocalRotation = ((Component)this).transform.localRotation;
		ScheduleNextIdleShake();
		if ((Object)(object)nview != (Object)null)
		{
			nview.Register("RPC_Moonforged_WrappingBoxComplete", (Action<long>)RPC_PlayCompletionAnimation);
		}
	}

	private void OnDisable()
	{
		StopAllVisualAnimation();
	}

	private void Update()
	{
		if ((Object)(object)container == (Object)null)
		{
			return;
		}
		bool flag = container.IsInUse();
		UpdateIdleAnimation(flag);
		if ((Object)(object)nview != (Object)null && !nview.IsOwner())
		{
			wasInUseLastFrame = flag;
			return;
		}
		if (wasInUseLastFrame && !flag && !wrapInProgress && CanWrap())
		{
			((MonoBehaviour)this).StartCoroutine(WrapSequence());
		}
		wasInUseLastFrame = flag;
	}

	private void UpdateIdleAnimation(bool isInUse)
	{
		if (isInUse || wrapInProgress || completionAnimationCoroutine != null)
		{
			StopIdleShakeAndReset();
		}
		else if (idleShakeCoroutine == null && Time.time >= nextIdleShakeTime)
		{
			idleShakeCoroutine = ((MonoBehaviour)this).StartCoroutine(IdleShakeRoutine());
		}
	}

	private void ScheduleNextIdleShake()
	{
		nextIdleShakeTime = Time.time + Random.Range(4f, 7.5f);
	}

	private IEnumerator IdleShakeRoutine()
	{
		float elapsed = 0f;
		while (elapsed < 0.45f && !((Object)(object)container == (Object)null) && !container.IsInUse() && !wrapInProgress)
		{
			float normalized = elapsed / 0.45f;
			float envelope = Mathf.Sin(normalized * (float)Math.PI);
			float wave = Mathf.Sin(normalized * (float)Math.PI * 6f);
			float yaw = wave * envelope * 2.25f;
			float side = wave * envelope * 0.003f;
			((Component)this).transform.localPosition = restLocalPosition + Vector3.right * side;
			((Component)this).transform.localRotation = restLocalRotation * Quaternion.Euler(0f, yaw, 0f);
			elapsed += Time.deltaTime;
			yield return null;
		}
		RestoreRestTransform();
		idleShakeCoroutine = null;
		ScheduleNextIdleShake();
	}

	private void StopIdleShakeAndReset()
	{
		if (idleShakeCoroutine != null)
		{
			((MonoBehaviour)this).StopCoroutine(idleShakeCoroutine);
			idleShakeCoroutine = null;
			ScheduleNextIdleShake();
		}
		if (completionAnimationCoroutine == null)
		{
			RestoreRestTransform();
		}
	}

	private void StopAllVisualAnimation()
	{
		if (idleShakeCoroutine != null)
		{
			((MonoBehaviour)this).StopCoroutine(idleShakeCoroutine);
			idleShakeCoroutine = null;
		}
		if (completionAnimationCoroutine != null)
		{
			((MonoBehaviour)this).StopCoroutine(completionAnimationCoroutine);
			completionAnimationCoroutine = null;
		}
		RestoreRestTransform();
	}

	private void RestoreRestTransform()
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		((Component)this).transform.localPosition = restLocalPosition;
		((Component)this).transform.localRotation = restLocalRotation;
	}

	private bool IsWrappingPaper(ItemData item)
	{
		if (item == null || (Object)(object)item.m_dropPrefab == (Object)null)
		{
			return false;
		}
		return ((Object)item.m_dropPrefab).name.Contains("WrappingPaper");
	}

	private string GetGiftPrefabNameFromPaper(string paperPrefabName)
	{
		if (string.IsNullOrEmpty(paperPrefabName))
		{
			return null;
		}
		switch (paperPrefabName)
		{
		case "M_Green_Gold_WrappingPaper":
			return "M_Green_Gold_Gift";
		case "M_WrappingPaper_SnowFlake_Blue":
			return "M_SnowFlake_Blue";
		case "M_WrappingPaper_SnowFlake_Red":
			return "M_SnowFlake_Red";
		default:
			if (paperPrefabName.StartsWith("M_WrappingPaper_"))
			{
				return "M_Gift_" + paperPrefabName.Substring("M_WrappingPaper_".Length);
			}
			return paperPrefabName.Replace("WrappingPaper", "Gift");
		}
	}

	public bool CanWrap()
	{
		List<ItemData> allItems = container.GetInventory().GetAllItems();
		if (allItems.Count != 2)
		{
			return false;
		}
		ItemData val = null;
		ItemData val2 = null;
		foreach (ItemData item in allItems)
		{
			if (IsWrappingPaper(item))
			{
				val = item;
			}
			else
			{
				val2 = item;
			}
		}
		return val != null && val2 != null;
	}

	private IEnumerator WrapSequence()
	{
		wrapInProgress = true;
		StopIdleShakeAndReset();
		yield return ((MonoBehaviour)this).StartCoroutine(BlinkRoutine(3.8f));
		Wrap();
		PlayCompletionAnimationForEveryone();
		SpawnTamedFX();
		yield return (object)new WaitForSeconds(0.9f);
		SpawnBuildSmoke();
		wrapInProgress = false;
		ScheduleNextIdleShake();
	}

	private void PlayCompletionAnimationForEveryone()
	{
		StopIdleShakeAndReset();
		if ((Object)(object)nview != (Object)null && nview.IsValid())
		{
			nview.InvokeRPC(ZNetView.Everybody, "RPC_Moonforged_WrappingBoxComplete", new object[0]);
		}
		else
		{
			StartCompletionAnimation();
		}
	}

	private void RPC_PlayCompletionAnimation(long sender)
	{
		StartCompletionAnimation();
	}

	private void StartCompletionAnimation()
	{
		if (completionAnimationCoroutine != null)
		{
			((MonoBehaviour)this).StopCoroutine(completionAnimationCoroutine);
			completionAnimationCoroutine = null;
		}
		if (idleShakeCoroutine != null)
		{
			((MonoBehaviour)this).StopCoroutine(idleShakeCoroutine);
			idleShakeCoroutine = null;
		}
		RestoreRestTransform();
		completionAnimationCoroutine = ((MonoBehaviour)this).StartCoroutine(CompletionAnimationRoutine());
	}

	private IEnumerator CompletionAnimationRoutine()
	{
		float elapsed = 0f;
		while (elapsed < 0.9f)
		{
			float normalized = Mathf.Clamp01(elapsed / 0.9f);
			float height = Mathf.Sin(normalized * (float)Math.PI) * 0.05f;
			float spinProgress = Mathf.SmoothStep(0f, 1f, normalized);
			float spin = spinProgress * 360f;
			((Component)this).transform.localPosition = restLocalPosition + Vector3.up * height;
			((Component)this).transform.localRotation = restLocalRotation * Quaternion.Euler(0f, spin, 0f);
			elapsed += Time.deltaTime;
			yield return null;
		}
		RestoreRestTransform();
		completionAnimationCoroutine = null;
		ScheduleNextIdleShake();
	}

	private void Wrap()
	{
		if ((Object)(object)ZNetScene.instance == (Object)null)
		{
			return;
		}
		Inventory inventory = container.GetInventory();
		ItemData val = null;
		ItemData val2 = null;
		foreach (ItemData allItem in inventory.GetAllItems())
		{
			if (IsWrappingPaper(allItem))
			{
				val = allItem;
			}
			else
			{
				val2 = allItem;
			}
		}
		if (val == null || val2 == null)
		{
			return;
		}
		string giftPrefabNameFromPaper = GetGiftPrefabNameFromPaper(((Object)val.m_dropPrefab).name);
		if (string.IsNullOrEmpty(giftPrefabNameFromPaper))
		{
			return;
		}
		GameObject prefab = ZNetScene.instance.GetPrefab(giftPrefabNameFromPaper);
		if (!((Object)(object)prefab == (Object)null))
		{
			Dictionary<string, string> customData = new Dictionary<string, string>
			{
				{
					"wrapped_prefab",
					((Object)val2.m_dropPrefab).name
				},
				{
					"wrapped_stack",
					val2.m_stack.ToString()
				},
				{
					"wrapped_quality",
					val2.m_quality.ToString()
				},
				{
					"wrapped_variant",
					val2.m_variant.ToString()
				},
				{
					"wrapped_durability",
					val2.m_durability.ToString(CultureInfo.InvariantCulture)
				}
			};
			ItemDrop component = prefab.GetComponent<ItemDrop>();
			if (!((Object)(object)component == (Object)null))
			{
				ItemData val3 = component.m_itemData.Clone();
				val3.m_dropPrefab = prefab;
				val3.m_stack = 1;
				val3.m_customData = customData;
				inventory.RemoveItem(val2);
				inventory.RemoveItem(val);
				inventory.AddItem(val3);
			}
		}
	}

	private IEnumerator BlinkRoutine(float duration)
	{
		Renderer[] renderers = ((Component)this).GetComponentsInChildren<Renderer>(true);
		float t = 0f;
		Dictionary<Material, Color> original = new Dictionary<Material, Color>();
		Renderer[] array = renderers;
		foreach (Renderer r in array)
		{
			if ((Object)(object)r != (Object)null && (Object)(object)r.material != (Object)null && r.material.HasProperty("_Color") && !original.ContainsKey(r.material))
			{
				original[r.material] = r.material.color;
			}
		}
		while (t < duration)
		{
			float pulse = Mathf.Sin(Time.time * 10f) * 0.7f + 1.7f;
			Renderer[] array2 = renderers;
			foreach (Renderer r2 in array2)
			{
				if ((Object)(object)r2 != (Object)null && (Object)(object)r2.material != (Object)null && r2.material.HasProperty("_Color"))
				{
					r2.material.color = original[r2.material] * pulse;
				}
			}
			t += Time.deltaTime;
			yield return null;
		}
		foreach (KeyValuePair<Material, Color> kv in original)
		{
			if ((Object)(object)kv.Key != (Object)null)
			{
				kv.Key.color = kv.Value;
			}
		}
	}

	private void SpawnBuildSmoke()
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: 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_0043: Unknown result type (might be due to invalid IL or missing references)
		ZNetScene instance = ZNetScene.instance;
		GameObject val = ((instance != null) ? instance.GetPrefab("vfx_PlacePiece") : null);
		if ((Object)(object)val != (Object)null)
		{
			Object.Instantiate<GameObject>(val, ((Component)this).transform.position + Vector3.up * 0.5f, Quaternion.identity);
		}
	}

	private void SpawnTamedFX()
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: 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_0043: Unknown result type (might be due to invalid IL or missing references)
		ZNetScene instance = ZNetScene.instance;
		GameObject val = ((instance != null) ? instance.GetPrefab("fx_creature_tamed") : null);
		if ((Object)(object)val != (Object)null)
		{
			Object.Instantiate<GameObject>(val, ((Component)this).transform.position + Vector3.up * 0.5f, Quaternion.identity);
		}
	}
}
public static class WrappingPaperRegistrar
{
	private struct PaperDef
	{
		public string PrefabName;

		public string DisplayName;

		public PaperDef(string prefabName, string displayName)
		{
			PrefabName = prefabName;
			DisplayName = displayName;
		}
	}

	private static bool registered;

	public static void Register(AssetBundle bundle)
	{
		//IL_0177: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0202: Expected O, but got Unknown
		//IL_0208: Unknown result type (might be due to invalid IL or missing references)
		//I