Decompiled source of DirtyMass v0.1.4

BepInEx/plugins/DirtyMass/DirtyMass.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("DirtyMass")]
[assembly: AssemblyDescription("Two cosmetic replacements for the rising mass in White Knuckle.")]
[assembly: AssemblyCompany("Ilylllk1n5")]
[assembly: AssemblyProduct("DirtyMass")]
[assembly: AssemblyFileVersion("0.1.4.0")]
[assembly: AssemblyVersion("0.1.4.0")]
namespace WhiteKnuckle.DirtyMass;

internal sealed class DirtyMassMenu : IDisposable
{
	private readonly DirtyMassPlugin plugin;

	private GameObject root;

	private GameObject ownedEventSystem;

	private GameObject previousSelection;

	private EventSystem events;

	private CL_GameManager manager;

	private Font font;

	private Text enabledText;

	private Text status;

	private readonly Image[] choices = (Image[])(object)new Image[2];

	private readonly Button[] choiceButtons = (Button[])(object)new Button[2];

	private bool openedInRun;

	private bool oldShowCursor;

	private bool capturedCursor;

	private CursorLockMode oldLock;

	private int openedScene;

	private float nextStatusRefresh;

	internal DirtyMassMenu(DirtyMassPlugin plugin)
	{
		this.plugin = plugin;
	}

	internal void Tick()
	{
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: 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_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)root != (Object)null)
		{
			Scene activeScene = SceneManager.GetActiveScene();
			if (((Scene)(ref activeScene)).handle != SceneHandle.op_Implicit(openedScene) || (openedInRun && ((Object)(object)manager == (Object)null || (Object)(object)manager != (Object)(object)CL_GameManager.gMan || !manager.isPaused)))
			{
				Close();
			}
		}
		if (Input.GetKeyDown(plugin.MenuKey.Value))
		{
			if ((Object)(object)root != (Object)null)
			{
				Close();
			}
			else
			{
				try
				{
					Open();
				}
				catch (Exception ex)
				{
					Close();
					plugin.Log("Could not open selector: " + ex.Message + ". Edit the BepInEx config to choose a mode.");
				}
			}
		}
		else if ((Object)(object)root != (Object)null && Input.GetKeyDown((KeyCode)27))
		{
			Close();
		}
		if ((Object)(object)root != (Object)null && Time.unscaledTime >= nextStatusRefresh)
		{
			nextStatusRefresh = Time.unscaledTime + 0.5f;
			Refresh();
		}
	}

	private void Open()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a1: Expected O, but got Unknown
		//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0216: Unknown result type (might be due to invalid IL or missing references)
		//IL_021b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0226: 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_023d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0242: Unknown result type (might be due to invalid IL or missing references)
		//IL_0243: Unknown result type (might be due to invalid IL or missing references)
		//IL_0249: Unknown result type (might be due to invalid IL or missing references)
		//IL_026d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0291: Unknown result type (might be due to invalid IL or missing references)
		//IL_0296: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_0300: Unknown result type (might be due to invalid IL or missing references)
		//IL_031e: Unknown result type (might be due to invalid IL or missing references)
		//IL_032d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0341: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Expected O, but got Unknown
		//IL_0453: Unknown result type (might be due to invalid IL or missing references)
		//IL_0462: Unknown result type (might be due to invalid IL or missing references)
		//IL_0467: Unknown result type (might be due to invalid IL or missing references)
		//IL_0487: Unknown result type (might be due to invalid IL or missing references)
		//IL_0496: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ae: Expected O, but got Unknown
		//IL_04cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_04db: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f3: Expected O, but got Unknown
		//IL_0506: Unknown result type (might be due to invalid IL or missing references)
		//IL_050b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0530: Unknown result type (might be due to invalid IL or missing references)
		//IL_053f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0553: Unknown result type (might be due to invalid IL or missing references)
		//IL_0388: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03bc: Expected O, but got Unknown
		//IL_03f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0412: Unknown result type (might be due to invalid IL or missing references)
		//IL_0426: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)CL_GameManager.gMan != (Object)null && CL_GameManager.IsLoading())
		{
			return;
		}
		Scene activeScene = SceneManager.GetActiveScene();
		openedScene = SceneHandle.op_Implicit(((Scene)(ref activeScene)).handle);
		manager = CL_GameManager.gMan;
		openedInRun = CL_GameManager.IsInGame();
		oldShowCursor = CL_GameManager.showCursor;
		oldLock = Cursor.lockState;
		if (openedInRun)
		{
			if (!manager.isPaused && !manager.canPause)
			{
				return;
			}
			if (!manager.isPaused)
			{
				manager.Pause();
			}
		}
		capturedCursor = true;
		Cursor.lockState = (CursorLockMode)0;
		CL_GameManager.showCursor = true;
		font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
		if ((Object)(object)font == (Object)null)
		{
			throw new InvalidOperationException("Built-in UI font is unavailable.");
		}
		events = EventSystem.current;
		if ((Object)(object)events == (Object)null)
		{
			ownedEventSystem = new GameObject("DirtyMass EventSystem", new Type[2]
			{
				typeof(EventSystem),
				typeof(StandaloneInputModule)
			});
			ownedEventSystem.transform.SetParent(((Component)plugin).transform, false);
			events = ownedEventSystem.GetComponent<EventSystem>();
		}
		previousSelection = events.currentSelectedGameObject;
		root = new GameObject("DirtyMass selector", new Type[4]
		{
			typeof(RectTransform),
			typeof(Canvas),
			typeof(CanvasScaler),
			typeof(GraphicRaycaster)
		});
		root.transform.SetParent(((Component)plugin).transform, false);
		Canvas component = root.GetComponent<Canvas>();
		component.renderMode = (RenderMode)0;
		component.sortingOrder = 32000;
		CanvasScaler component2 = root.GetComponent<CanvasScaler>();
		component2.uiScaleMode = (ScaleMode)1;
		component2.referenceResolution = new Vector2(1600f, 900f);
		component2.screenMatchMode = (ScreenMatchMode)1;
		RectTransform obj = Rect("Backdrop", root.transform, Vector2.zero, Vector2.zero);
		obj.anchorMin = Vector2.zero;
		obj.anchorMax = Vector2.one;
		Vector2 offsetMin = (obj.offsetMax = Vector2.zero);
		obj.offsetMin = offsetMin;
		((Graphic)((Component)obj).gameObject.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.82f);
		RectTransform val = Rect("Panel", root.transform, new Vector2(720f, 530f), Vector2.zero);
		((Graphic)((Component)val).gameObject.AddComponent<Image>()).color = new Color(0.055f, 0.045f, 0.025f, 1f);
		Label((Transform)(object)val, "DIRTY MASS", 48, new Vector2(660f, 80f), new Vector2(0f, 194f), new Color(0.92f, 0.86f, 0.63f));
		Label((Transform)(object)val, "WHAT'S RISING FROM BELOW?", 20, new Vector2(660f, 42f), new Vector2(0f, 140f), new Color(0.69f, 0.66f, 0.58f));
		for (int i = 0; i < 2; i++)
		{
			int index = i;
			Button val2 = Button((Transform)(object)val, (i == 0) ? "URINE" : "FECES", new Vector2(296f, 125f), new Vector2((float)((i == 0) ? (-162) : 162), 33f), (UnityAction)delegate
			{
				Select((MassType)index);
			}, 34);
			choiceButtons[i] = val2;
			choices[i] = ((Component)val2).GetComponent<Image>();
			Label((Transform)(object)val, (i == 0) ? "Liquid and foam" : "Thick sludge and lumps", 18, new Vector2(300f, 40f), new Vector2((float)((i == 0) ? (-162) : 162), -56f), new Color(0.78f, 0.76f, 0.67f));
		}
		status = Label((Transform)(object)val, "", 17, new Vector2(670f, 55f), new Vector2(0f, -105f), Color.white);
		Button val3 = Button((Transform)(object)val, "", new Vector2(295f, 56f), new Vector2(-162f, -163f), (UnityAction)delegate
		{
			plugin.ModeEnabled.Value = !plugin.ModeEnabled.Value;
			Refresh();
		}, 20);
		enabledText = ((Component)val3).GetComponentInChildren<Text>();
		Button((Transform)(object)val, "CLOSE", new Vector2(295f, 56f), new Vector2(162f, -163f), new UnityAction(Close), 20);
		Label((Transform)(object)val, "v0.1.4  ·  " + ((object)plugin.MenuKey.Value/*cast due to .constrained prefix*/).ToString() + " / ESC — close  ·  selection saved", 16, new Vector2(670f, 40f), new Vector2(0f, -221f), new Color(0.56f, 0.54f, 0.46f));
		Refresh();
		events.SetSelectedGameObject(((Component)choiceButtons[(plugin.Mode.Value == MassType.Feces) ? 1u : 0u]).gameObject);
	}

	private void Select(MassType mode)
	{
		plugin.Mode.Value = mode;
		plugin.ModeEnabled.Value = true;
		plugin.RetryVisuals();
		Refresh();
	}

	internal void Refresh()
	{
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: 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)
		if (!((Object)(object)root == (Object)null))
		{
			for (int i = 0; i < 2; i++)
			{
				bool flag = plugin.ModeEnabled.Value && plugin.Mode.Value == (MassType)i;
				((Graphic)choices[i]).color = (flag ? ((i == 0) ? new Color(0.66f, 0.46f, 0.06f) : new Color(0.38f, 0.21f, 0.095f)) : new Color(0.13f, 0.115f, 0.08f));
			}
			enabledText.text = (plugin.ModeEnabled.Value ? "MOD: ON" : "MOD: OFF");
			status.text = plugin.VisualStatus;
			((Graphic)status).color = (Color)((plugin.VisualsFailed && plugin.ModeEnabled.Value) ? new Color(1f, 0.43f, 0.3f) : Color.white);
		}
	}

	private static RectTransform Rect(string name, Transform parent, Vector2 size, Vector2 position)
	{
		//IL_0014: 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_0040: 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_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		RectTransform component = new GameObject(name, new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
		((Transform)component).SetParent(parent, false);
		Vector2 val = default(Vector2);
		((Vector2)(ref val))..ctor(0.5f, 0.5f);
		component.pivot = val;
		Vector2 anchorMin = (component.anchorMax = val);
		component.anchorMin = anchorMin;
		component.sizeDelta = size;
		component.anchoredPosition = position;
		return component;
	}

	private Text Label(Transform parent, string value, int size, Vector2 area, Vector2 position, Color color)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		Text obj = ((Component)Rect(value, parent, area, position)).gameObject.AddComponent<Text>();
		obj.font = font;
		obj.text = value;
		obj.fontSize = size;
		((Graphic)obj).color = color;
		obj.alignment = (TextAnchor)4;
		((Graphic)obj).raycastTarget = false;
		obj.horizontalOverflow = (HorizontalWrapMode)0;
		obj.verticalOverflow = (VerticalWrapMode)0;
		return obj;
	}

	private Button Button(Transform parent, string label, Vector2 area, Vector2 position, UnityAction action, int size)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: 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_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		RectTransform val = Rect(label, parent, area, position);
		Image val2 = ((Component)val).gameObject.AddComponent<Image>();
		((Graphic)val2).color = new Color(0.16f, 0.14f, 0.09f);
		Button obj = ((Component)val).gameObject.AddComponent<Button>();
		((Selectable)obj).targetGraphic = (Graphic)(object)val2;
		ColorBlock colors = ((Selectable)obj).colors;
		((ColorBlock)(ref colors)).normalColor = Color.white;
		((ColorBlock)(ref colors)).highlightedColor = new Color(1.25f, 1.25f, 1.25f);
		((ColorBlock)(ref colors)).selectedColor = ((ColorBlock)(ref colors)).highlightedColor;
		((ColorBlock)(ref colors)).pressedColor = new Color(0.7f, 0.7f, 0.7f);
		((ColorBlock)(ref colors)).colorMultiplier = 1f;
		((Selectable)obj).colors = colors;
		((UnityEvent)obj.onClick).AddListener(action);
		Label((Transform)(object)val, label, size, area - new Vector2(12f, 4f), Vector2.zero, new Color(0.97f, 0.94f, 0.85f));
		return obj;
	}

	internal void Close()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
		Scene activeScene = SceneManager.GetActiveScene();
		bool num = ((Scene)(ref activeScene)).handle == SceneHandle.op_Implicit(openedScene);
		if ((Object)(object)root != (Object)null)
		{
			root.SetActive(false);
			Object.Destroy((Object)(object)root);
			root = null;
		}
		if ((Object)(object)events != (Object)null && (Object)(object)previousSelection != (Object)null && previousSelection.activeInHierarchy)
		{
			events.SetSelectedGameObject(previousSelection);
		}
		if (num && capturedCursor)
		{
			if (openedInRun)
			{
				Cursor.lockState = (CursorLockMode)(!(CL_GameManager.showCursor = (Object)(object)manager != (Object)null && manager.isPaused));
			}
			else
			{
				CL_GameManager.showCursor = oldShowCursor;
				Cursor.lockState = oldLock;
			}
		}
		if ((Object)(object)ownedEventSystem != (Object)null)
		{
			ownedEventSystem.SetActive(false);
			Object.Destroy((Object)(object)ownedEventSystem);
		}
		ownedEventSystem = null;
		previousSelection = null;
		events = null;
		manager = null;
		openedInRun = false;
		capturedCursor = false;
	}

	public void Dispose()
	{
		Close();
	}
}
[BepInPlugin("ilya.whiteknuckle.dirtymass", "DirtyMass", "0.1.4")]
[DefaultExecutionOrder(1000)]
public sealed class DirtyMassPlugin : BaseUnityPlugin
{
	public const string Id = "ilya.whiteknuckle.dirtymass";

	public const string Version = "0.1.4";

	internal ConfigEntry<bool> ModeEnabled;

	internal ConfigEntry<MassType> Mode;

	internal ConfigEntry<KeyCode> MenuKey;

	private MassVisuals visuals;

	private DirtyMassMenu menu;

	private volatile bool settingsChanged;

	private bool failed;

	internal bool VisualsFailed => failed;

	internal string VisualStatus
	{
		get
		{
			if (!ModeEnabled.Value)
			{
				return "Original mass appearance";
			}
			if (failed)
			{
				return "Could not apply. Select a mode to retry.\nIf it fails again, check LogOutput.log.";
			}
			string text = ((Mode.Value == MassType.Feces) ? "FECES" : "URINE");
			if (visuals != null && visuals.HasApplied)
			{
				return text + " — appearance applied";
			}
			return text + " — waiting for the mass";
		}
	}

	private void Awake()
	{
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		ModeEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Replace the rising mass visuals. Disabling restores the original materials.");
		Mode = ((BaseUnityPlugin)this).Config.Bind<MassType>("General", "MassType", MassType.Urine, "Urine = yellow liquid with foam; Feces = brown sludge with floating lumps. Applies immediately.");
		MenuKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "MenuKey", (KeyCode)287, "Open the DirtyMass selector. During a run, this opens the native pause menu first.");
		ModeEnabled.SettingChanged += Changed;
		Mode.SettingChanged += Changed;
		visuals = new MassVisuals(this);
		menu = new DirtyMassMenu(this);
		((BaseUnityPlugin)this).Logger.LogInfo((object)("DirtyMass 0.1.4 loaded. " + ((object)MenuKey.Value/*cast due to .constrained prefix*/).ToString() + " opens the selector. Built for the supplied Beta 0.61 assemblies."));
	}

	private void Changed(object sender, EventArgs args)
	{
		settingsChanged = true;
	}

	private void Update()
	{
		if (menu != null)
		{
			menu.Tick();
		}
		if (settingsChanged)
		{
			settingsChanged = false;
			failed = false;
			if (menu != null)
			{
				menu.Refresh();
			}
		}
	}

	private void LateUpdate()
	{
		if (visuals == null || failed)
		{
			return;
		}
		try
		{
			visuals.Tick(ModeEnabled.Value, Mode.Value);
		}
		catch (Exception ex)
		{
			failed = true;
			visuals.Restore();
			((BaseUnityPlugin)this).Logger.LogError((object)("DirtyMass could not apply its visuals; originals restored. " + ex));
			if (menu != null)
			{
				menu.Refresh();
			}
		}
	}

	internal void Log(string message)
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)message);
	}

	internal void RetryVisuals()
	{
		failed = false;
		if (visuals != null)
		{
			visuals.Restore();
		}
		settingsChanged = true;
	}

	private void OnDisable()
	{
		if (menu != null)
		{
			menu.Close();
		}
		if (visuals != null)
		{
			visuals.Restore();
		}
	}

	private void OnDestroy()
	{
		if (ModeEnabled != null)
		{
			ModeEnabled.SettingChanged -= Changed;
		}
		if (Mode != null)
		{
			Mode.SettingChanged -= Changed;
		}
		if (menu != null)
		{
			menu.Dispose();
		}
		if (visuals != null)
		{
			visuals.Dispose();
		}
	}
}
internal sealed class FloatingDetails : IDisposable
{
	private struct Span
	{
		internal DetailPiece Piece;

		internal int Start;

		internal int Count;
	}

	private readonly MassType mode;

	private readonly List<Span> spans = new List<Span>();

	private GameObject root;

	private Mesh mesh;

	private Material material;

	private Material distanceColor;

	private Vector3[] baseline;

	private Vector3[] animated;

	private int cellX = int.MinValue;

	private int cellZ = int.MinValue;

	private Vector3 sourceSize;

	private float nextAnimation;

	private const int RippleSegments = 24;

	internal FloatingDetails(Transform parent, int layer, Shader shader, Texture2D texture, MassType mode)
	{
		//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_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Expected O, but got Unknown
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: 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_00a8: Expected O, but got Unknown
		this.mode = mode;
		try
		{
			root = new GameObject("DirtyMass world-anchored details")
			{
				hideFlags = (HideFlags)52,
				layer = layer
			};
			root.transform.SetParent(parent, false);
			material = SurfaceMaterialFactory.Create(shader, texture, Vector2.one, "DirtyMass floating details material");
			distanceColor = FoglessMaterialFactory.TryCreate(texture, Vector2.one);
			mesh = new Mesh
			{
				name = "DirtyMass world detail mesh",
				hideFlags = (HideFlags)52
			};
			if (mode == MassType.Urine)
			{
				mesh.MarkDynamic();
			}
			root.AddComponent<MeshFilter>().sharedMesh = mesh;
			MeshRenderer obj = root.AddComponent<MeshRenderer>();
			((Renderer)obj).sharedMaterial = material;
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)obj).receiveShadows = false;
			((Renderer)obj).lightProbeUsage = (LightProbeUsage)0;
			((Renderer)obj).reflectionProbeUsage = (ReflectionProbeUsage)0;
		}
		catch
		{
			Dispose();
			throw;
		}
	}

	internal void Tick(Renderer source, float height, Vector3 viewer, float clock, bool visible)
	{
		//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_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		root.SetActive(visible);
		if (!visible)
		{
			return;
		}
		Bounds bounds = source.bounds;
		int num = WorldDetailLayout.Cell(Mathf.Clamp(viewer.x, ((Bounds)(ref bounds)).min.x, ((Bounds)(ref bounds)).max.x));
		int num2 = WorldDetailLayout.Cell(Mathf.Clamp(viewer.z, ((Bounds)(ref bounds)).min.z, ((Bounds)(ref bounds)).max.z));
		if (cellX == num && cellZ == num2)
		{
			Vector3 val = sourceSize - ((Bounds)(ref bounds)).size;
			if (!(((Vector3)(ref val)).sqrMagnitude > 0.01f))
			{
				goto IL_00cb;
			}
		}
		cellX = num;
		cellZ = num2;
		sourceSize = ((Bounds)(ref bounds)).size;
		Rebuild(bounds);
		nextAnimation = 0f;
		goto IL_00cb;
		IL_00cb:
		root.transform.position = new Vector3(0f, height + 0.025f, 0f);
		root.transform.rotation = Quaternion.identity;
		if (mode == MassType.Urine && clock >= nextAnimation)
		{
			Animate(clock);
			nextAnimation = clock + 1f / 24f;
		}
		if ((Object)(object)distanceColor != (Object)null && mesh.vertexCount > 0)
		{
			Graphics.DrawMesh(mesh, root.transform.localToWorldMatrix, distanceColor, root.layer, (Camera)null, 0, (MaterialPropertyBlock)null, (ShadowCastingMode)0, false, (Transform)null, (LightProbeUsage)0);
		}
	}

	private void Rebuild(Bounds bounds)
	{
		//IL_0014: 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_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		List<DetailPiece> list = WorldDetailLayout.Generate(mode, cellX, cellZ, ((Bounds)(ref bounds)).min.x, ((Bounds)(ref bounds)).max.x, ((Bounds)(ref bounds)).min.z, ((Bounds)(ref bounds)).max.z);
		List<Vector3> list2 = new List<Vector3>();
		List<Vector2> list3 = new List<Vector2>();
		List<int> list4 = new List<int>();
		spans.Clear();
		foreach (DetailPiece item in list)
		{
			int count = list2.Count;
			if (item.Kind == DetailKind.Ripple)
			{
				AddRipple(item, list2, list3, list4);
			}
			else
			{
				AddBlob(item, list2, list3, list4);
			}
			spans.Add(new Span
			{
				Piece = item,
				Start = count,
				Count = list2.Count - count
			});
		}
		mesh.Clear();
		mesh.SetVertices(list2);
		mesh.SetUVs(0, list3);
		mesh.SetTriangles(list4, 0);
		Color32[] array = (Color32[])(object)new Color32[list2.Count];
		for (int i = 0; i < array.Length; i++)
		{
			array[i] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
		}
		mesh.colors32 = array;
		mesh.RecalculateNormals();
		mesh.RecalculateBounds();
		Bounds bounds2 = mesh.bounds;
		((Bounds)(ref bounds2)).Expand(new Vector3(2.6f, 0.1f, 2.6f));
		mesh.bounds = bounds2;
		baseline = list2.ToArray();
		animated = (Vector3[])baseline.Clone();
	}

	private static void AddBlob(DetailPiece piece, List<Vector3> vertices, List<Vector2> uvs, List<int> triangles)
	{
		//IL_0120: 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)
		int num = ((piece.Kind == DetailKind.Lump) ? 10 : 8);
		int num2 = ((piece.Kind == DetailKind.Lump) ? 6 : 4);
		int count = vertices.Count;
		float num3 = Mathf.Cos(piece.Angle);
		float num4 = Mathf.Sin(piece.Angle);
		for (int i = 0; i <= num2; i++)
		{
			float num5 = (float)i / (float)num2;
			float num6 = num5 * MathF.PI;
			for (int j = 0; j <= num; j++)
			{
				float num7 = (float)j / (float)num;
				float num8 = num7 * MathF.PI * 2f;
				float num9 = ((piece.Kind == DetailKind.Lump) ? (1f + 0.1f * Mathf.Sin(num8 * 3f + num6 * 4f)) : 1f);
				float num10 = Mathf.Sin(num6) * Mathf.Cos(num8) * piece.Length * num9;
				float num11 = Mathf.Sin(num6) * Mathf.Sin(num8) * piece.Radius * num9;
				vertices.Add(new Vector3(piece.X + num10 * num3 - num11 * num4, (0f - Mathf.Cos(num6)) * piece.Height + piece.Height * 0.1f, piece.Z + num10 * num4 + num11 * num3));
				uvs.Add(new Vector2(num7, num5));
				if (i < num2 && j < num)
				{
					int num12 = count + i * (num + 1) + j;
					int num13 = num12 + num + 1;
					triangles.Add(num12);
					triangles.Add(num13);
					triangles.Add(num13 + 1);
					triangles.Add(num12);
					triangles.Add(num13 + 1);
					triangles.Add(num12 + 1);
				}
			}
		}
	}

	private static void AddRipple(DetailPiece piece, List<Vector3> vertices, List<Vector2> uvs, List<int> triangles)
	{
		//IL_0062: 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)
		int count = vertices.Count;
		for (int i = 0; i <= 24; i++)
		{
			float num = (float)i / 24f;
			float num2 = num * MathF.PI * 2f;
			for (int j = 0; j < 2; j++)
			{
				float num3 = piece.Radius + (float)j * 0.02f;
				vertices.Add(new Vector3(piece.X + Mathf.Cos(num2) * num3, -0.012f, piece.Z + Mathf.Sin(num2) * num3));
				uvs.Add(new Vector2(num, (j == 0) ? 0.48f : 0.7f));
			}
			if (i < 24)
			{
				int num4 = count + i * 2;
				triangles.Add(num4);
				triangles.Add(num4 + 3);
				triangles.Add(num4 + 1);
				triangles.Add(num4);
				triangles.Add(num4 + 2);
				triangles.Add(num4 + 3);
			}
		}
	}

	private void Animate(float clock)
	{
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		foreach (Span span in spans)
		{
			DetailPiece piece = span.Piece;
			if (piece.Kind == DetailKind.Ripple)
			{
				float num = Mathf.Repeat(clock * piece.Speed + piece.Phase, 1f);
				float num2 = 0.06f + (piece.Radius - 0.06f) * num;
				float num3 = 0.022f * Mathf.Sin(num * MathF.PI);
				for (int i = 0; i <= 24; i++)
				{
					float num4 = (float)i / 24f * MathF.PI * 2f;
					for (int j = 0; j < 2; j++)
					{
						float num5 = num2 + (float)j * num3;
						animated[span.Start + i * 2 + j] = new Vector3(piece.X + Mathf.Cos(num4) * num5, -0.012f, piece.Z + Mathf.Sin(num4) * num5);
					}
				}
			}
			else
			{
				float num6 = Mathf.Sin(clock * (1.1f + piece.Speed) + piece.Phase * MathF.PI * 2f) * 0.012f;
				for (int k = span.Start; k < span.Start + span.Count; k++)
				{
					animated[k] = baseline[k];
					animated[k].y += num6;
				}
			}
		}
		mesh.vertices = animated;
	}

	public void Dispose()
	{
		if ((Object)(object)root != (Object)null)
		{
			root.SetActive(false);
			Object.Destroy((Object)(object)root);
		}
		if ((Object)(object)mesh != (Object)null)
		{
			Object.Destroy((Object)(object)mesh);
		}
		if ((Object)(object)material != (Object)null)
		{
			Object.Destroy((Object)(object)material);
		}
		if ((Object)(object)distanceColor != (Object)null)
		{
			Object.Destroy((Object)(object)distanceColor);
		}
		root = null;
		mesh = null;
		material = null;
		distanceColor = null;
		baseline = null;
		animated = null;
		spans.Clear();
	}
}
internal static class FoglessMaterialFactory
{
	internal static Material TryCreate(Texture2D texture, Vector2 scale)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Expected O, but got Unknown
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: 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)
		Shader val = Shader.Find("UI/Default");
		if ((Object)(object)val == (Object)null || !val.isSupported)
		{
			return null;
		}
		Material val2 = new Material(val);
		try
		{
			((Object)val2).name = "DirtyMass distance colour";
			((Object)val2).hideFlags = (HideFlags)52;
			val2.shaderKeywords = new string[0];
			val2.renderQueue = 2010;
			val2.SetTexture("_MainTex", (Texture)(object)texture);
			val2.SetTextureScale("_MainTex", scale);
			val2.SetTextureOffset("_MainTex", Vector2.zero);
			val2.SetColor("_Color", Color.white);
			val2.SetColor("_TextureSampleAdd", new Color(0f, 0f, 0f, 0f));
			val2.SetInt("unity_GUIZTestMode", 4);
			val2.SetFloat("_StencilComp", 8f);
			val2.SetFloat("_StencilOp", 0f);
			val2.SetFloat("_StencilWriteMask", 0f);
			val2.SetFloat("_ColorMask", 15f);
			val2.SetFloat("_UseUIAlphaClip", 0f);
			return val2;
		}
		catch
		{
			Object.Destroy((Object)(object)val2);
			throw;
		}
	}
}
internal sealed class MassVisuals : IDisposable
{
	private sealed class Binding
	{
		internal Renderer Renderer;

		internal Material[] Original;

		internal Material[] Owned;

		internal Material[] DistanceColors;

		internal Vector2[] Offsets;

		internal bool Particle;

		internal MeshFilter Filter;

		internal Mesh OriginalMesh;

		internal Mesh OwnedMesh;

		internal Vector3 MappingOrigin;

		internal void Release()
		{
			if ((Object)(object)Renderer != (Object)null)
			{
				Material[] sharedMaterials = Renderer.sharedMaterials;
				if (MaterialOwnership.Restore(sharedMaterials, Owned, Original))
				{
					Renderer.sharedMaterials = sharedMaterials;
				}
			}
			if ((Object)(object)Filter != (Object)null && (Object)(object)Filter.sharedMesh == (Object)(object)OwnedMesh && (Object)(object)OwnedMesh != (Object)null)
			{
				Filter.sharedMesh = OriginalMesh;
			}
			if ((Object)(object)OwnedMesh != (Object)null)
			{
				Object.Destroy((Object)(object)OwnedMesh);
			}
			Material[] owned = Owned;
			foreach (Material val in owned)
			{
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
				}
			}
			owned = DistanceColors;
			foreach (Material val2 in owned)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					Object.Destroy((Object)(object)val2);
				}
			}
		}
	}

	private readonly DirtyMassPlugin plugin;

	private readonly List<Binding> bindings = new List<Binding>();

	private readonly HashSet<Renderer> desired = new HashSet<Renderer>();

	private readonly Texture2D[] surfaces = (Texture2D[])(object)new Texture2D[2];

	private readonly Texture2D[] details = (Texture2D[])(object)new Texture2D[2];

	private DEN_DeathFloor mass;

	private UT_GooVisualOverride visualOverride;

	private MassType mode;

	private float nextScan;

	private Shader surfaceShader;

	private FloatingDetails floating;

	private Renderer detailSource;

	private Texture originalCorruption;

	private Texture ownedCorruption;

	private int loggedMass;

	private bool loggedDistance;

	private float nextDistanceCheck;

	private static readonly string[] TextureSlots = new string[4] { "_MainTex", "_BaseMap", "_BaseColorMap", "_EmissionMap" };

	internal bool HasApplied
	{
		get
		{
			if ((Object)(object)mass != (Object)null)
			{
				return bindings.Count > 0;
			}
			return false;
		}
	}

	internal MassVisuals(DirtyMassPlugin plugin)
	{
		this.plugin = plugin;
	}

	internal void Tick(bool enabled, MassType selected)
	{
		//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_028e: Unknown result type (might be due to invalid IL or missing references)
		//IL_029e: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0242: Unknown result type (might be due to invalid IL or missing references)
		//IL_0257: Unknown result type (might be due to invalid IL or missing references)
		//IL_0261: Unknown result type (might be due to invalid IL or missing references)
		//IL_0271: Unknown result type (might be due to invalid IL or missing references)
		//IL_0276: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
		if (!enabled || (Object)(object)DEN_DeathFloor.instance == (Object)null)
		{
			if ((Object)(object)mass != (Object)null || bindings.Count > 0 || floating != null)
			{
				Restore();
			}
			return;
		}
		DEN_DeathFloor instance = DEN_DeathFloor.instance;
		UT_GooVisualOverride currentGooVisualOverride = DEN_DeathFloor.currentGooVisualOverride;
		selected = ((selected == MassType.Feces) ? MassType.Feces : MassType.Urine);
		if ((Object)(object)mass != (Object)(object)instance || (Object)(object)visualOverride != (Object)(object)currentGooVisualOverride || mode != selected)
		{
			Restore();
			mass = instance;
			visualOverride = currentGooVisualOverride;
			mode = selected;
			EnsureTextures();
			Scan();
			nextScan = Time.unscaledTime + 1f;
		}
		else if (Time.unscaledTime >= nextScan)
		{
			Scan();
			nextScan = Time.unscaledTime + 1f;
		}
		if ((Object)(object)ownedCorruption == (Object)null && (Object)(object)mass.corruptionTexture != (Object)null && (Object)(object)Shader.GetGlobalTexture("_CORRUPTTEXTURE") == (Object)(object)mass.corruptionTexture)
		{
			originalCorruption = (Texture)(object)mass.corruptionTexture;
			ownedCorruption = (Texture)(object)surfaces[(int)mode];
			Shader.SetGlobalTexture("_CORRUPTTEXTURE", ownedCorruption);
		}
		float time = Time.time;
		foreach (Binding binding in bindings)
		{
			if ((Object)(object)binding.Renderer == (Object)null || binding.Particle)
			{
				continue;
			}
			for (int i = 0; i < binding.Owned.Length; i++)
			{
				Material val = binding.Owned[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Vector2 val2 = binding.Offsets[i];
				if ((Object)(object)binding.OwnedMesh != (Object)null)
				{
					Vector3 val3 = ((Component)binding.Renderer).transform.position - binding.MappingOrigin;
					val2 = new Vector2(val3.z, val3.x) / 6f;
				}
				else if ((Object)(object)binding.Renderer == (Object)(object)mass.deathFloorRenderer && i == 0 && Math.Abs(mass.offsetScale) > 0.001f)
				{
					val2 = new Vector2(((Component)mass).transform.position.z, ((Component)mass).transform.position.x) / mass.offsetScale;
				}
				float num = ((mode == MassType.Urine) ? 0.013f : 0.0035f);
				Vector2 val4 = val2 + new Vector2(time * num, time * num * 0.37f);
				string[] textureSlots = TextureSlots;
				foreach (string text in textureSlots)
				{
					if (val.HasProperty(text))
					{
						val.SetTextureOffset(text, val4);
					}
				}
				Material val5 = binding.DistanceColors[i];
				if ((Object)(object)val5 != (Object)null)
				{
					val5.SetTextureOffset("_MainTex", val4);
				}
			}
			if (binding.DistanceColors.Length == 0 || !((Object)(object)binding.Filter != (Object)null) || !((Object)(object)binding.Filter.sharedMesh != (Object)null) || !binding.Renderer.enabled || !((Component)binding.Renderer).gameObject.activeInHierarchy || binding.Renderer.forceRenderingOff)
			{
				continue;
			}
			Mesh sharedMesh = binding.Filter.sharedMesh;
			for (int k = 0; k < sharedMesh.subMeshCount; k++)
			{
				Material val6 = binding.DistanceColors[Math.Min(k, binding.DistanceColors.Length - 1)];
				if ((Object)(object)val6 != (Object)null)
				{
					Graphics.DrawMesh(sharedMesh, binding.Renderer.localToWorldMatrix, val6, ((Component)binding.Renderer).gameObject.layer, (Camera)null, k, (MaterialPropertyBlock)null, (ShadowCastingMode)0, false, (Transform)null, (LightProbeUsage)0);
				}
			}
		}
		AnimateDetails(time);
		LogDistance();
	}

	private void EnsureTextures()
	{
		int num = (int)mode;
		if ((Object)(object)surfaces[num] == (Object)null)
		{
			surfaces[num] = TextureFactory.Create(TexturePixels.Surface(mode, 256), 256, "DirtyMass " + mode.ToString() + " surface");
		}
		if ((Object)(object)details[num] == (Object)null)
		{
			details[num] = TextureFactory.Create(TexturePixels.Detail(mode, 64), 64, "DirtyMass " + mode.ToString() + " details");
		}
		if ((Object)(object)surfaceShader == (Object)null)
		{
			surfaceShader = SurfaceMaterialFactory.Resolve();
		}
	}

	private void Collect(GameObject root)
	{
		if ((Object)(object)root == (Object)null)
		{
			return;
		}
		Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
		foreach (Renderer val in componentsInChildren)
		{
			if (val is MeshRenderer || val is SkinnedMeshRenderer || val is ParticleSystemRenderer)
			{
				desired.Add(val);
			}
		}
	}

	private void Scan()
	{
		desired.Clear();
		if ((Object)(object)mass.deathFloorRenderer != (Object)null)
		{
			desired.Add((Renderer)(object)mass.deathFloorRenderer);
		}
		Collect(mass.visualRoot);
		if ((Object)(object)visualOverride != (Object)null)
		{
			Collect(((Component)visualOverride).gameObject);
		}
		for (int num = bindings.Count - 1; num >= 0; num--)
		{
			Binding binding = bindings[num];
			bool flag = (Object)(object)binding.Renderer != (Object)null && desired.Contains(binding.Renderer);
			if (flag)
			{
				Material[] sharedMaterials = binding.Renderer.sharedMaterials;
				flag = sharedMaterials.Length == binding.Owned.Length;
				int num2 = 0;
				while (flag && num2 < sharedMaterials.Length)
				{
					flag = sharedMaterials[num2] == binding.Owned[num2];
					num2++;
				}
				if (flag && (Object)(object)binding.OwnedMesh != (Object)null)
				{
					flag = (Object)(object)binding.Filter != (Object)null && (Object)(object)binding.Filter.sharedMesh == (Object)(object)binding.OwnedMesh;
				}
			}
			if (flag)
			{
				desired.Remove(binding.Renderer);
			}
			else
			{
				binding.Release();
				bindings.RemoveAt(num);
			}
		}
		foreach (Renderer item in desired)
		{
			Add(item);
		}
		Renderer val = ChooseDetailSource();
		if ((Object)(object)detailSource != (Object)(object)val)
		{
			ClearDetails();
			detailSource = val;
			if ((Object)(object)detailSource != (Object)null)
			{
				BuildDetails();
			}
		}
		if (((Object)mass).GetInstanceID() == loggedMass || bindings.Count <= 0)
		{
			return;
		}
		loggedMass = ((Object)mass).GetInstanceID();
		string text = (((Object)(object)surfaceShader != (Object)null) ? ((Object)surfaceShader).name : "unavailable");
		string text2 = (((Object)(object)surfaceShader != (Object)null && SurfaceMaterialFactory.IsStandard(surfaceShader)) ? "emission texture, black albedo, no scene-light dependency" : "unlit texture");
		plugin.Log("Styled " + bindings.Count + " mass renderers as " + mode.ToString() + "; surface shader: " + text + "; " + text2);
		foreach (Binding binding2 in bindings)
		{
			if ((Object)(object)binding2.Renderer != (Object)null && !binding2.Particle)
			{
				plugin.Log("Mass renderer: " + ((Object)binding2.Renderer).name + "; active=" + ((Component)binding2.Renderer).gameObject.activeInHierarchy + "; enabled=" + binding2.Renderer.enabled + "; slots=" + binding2.Owned.Length + "; world UV=" + ((Object)(object)binding2.OwnedMesh != (Object)null) + "; fog-free colour=" + (binding2.DistanceColors.Length != 0 && (Object)(object)binding2.DistanceColors[0] != (Object)null));
			}
		}
	}

	private void Add(Renderer renderer)
	{
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: 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_0097: Expected O, but got Unknown
		//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: 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_0141: Unknown result type (might be due to invalid IL or missing references)
		Material[] sharedMaterials = renderer.sharedMaterials;
		Binding binding = new Binding
		{
			Renderer = renderer,
			Original = sharedMaterials,
			Owned = (Material[])(object)new Material[sharedMaterials.Length],
			DistanceColors = (Material[])(object)new Material[sharedMaterials.Length],
			Offsets = (Vector2[])(object)new Vector2[sharedMaterials.Length],
			Particle = (renderer is ParticleSystemRenderer)
		};
		bindings.Add(binding);
		if (!binding.Particle)
		{
			MapSurface(binding);
		}
		for (int i = 0; i < sharedMaterials.Length; i++)
		{
			if ((Object)(object)sharedMaterials[i] == (Object)null)
			{
				continue;
			}
			if (binding.Particle)
			{
				Material val = new Material(sharedMaterials[i]);
				binding.Owned[i] = val;
				((Object)val).name = "DirtyMass " + ((Object)sharedMaterials[i]).name;
				((Object)val).hideFlags = (HideFlags)52;
				Color val2 = ((mode == MassType.Urine) ? new Color(0.8f, 0.63f, 0.15f) : new Color(0.38f, 0.2f, 0.07f));
				string[] array = new string[3] { "_Color", "_TintColor", "_BaseColor" };
				foreach (string text in array)
				{
					if (val.HasProperty(text))
					{
						val2.a = val.GetColor(text).a;
						val.SetColor(text, val2);
					}
				}
			}
			else
			{
				Vector2 scale = Vector2.one;
				if ((Object)(object)binding.OwnedMesh == (Object)null && sharedMaterials[i].HasProperty("_MainTex"))
				{
					binding.Offsets[i] = sharedMaterials[i].GetTextureOffset("_MainTex");
					scale = sharedMaterials[i].GetTextureScale("_MainTex");
				}
				binding.Owned[i] = SurfaceMaterialFactory.Create(surfaceShader, surfaces[(int)mode], scale, "DirtyMass " + ((Object)sharedMaterials[i]).name);
				if ((Object)(object)binding.Filter != (Object)null)
				{
					binding.DistanceColors[i] = FoglessMaterialFactory.TryCreate(surfaces[(int)mode], scale);
				}
			}
		}
		renderer.sharedMaterials = binding.Owned;
	}

	private static void MapSurface(Binding binding)
	{
		//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)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: 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)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_0166: Unknown result type (might be due to invalid IL or missing references)
		//IL_016b: Unknown result type (might be due to invalid IL or missing references)
		MeshFilter val = (binding.Filter = ((Component)binding.Renderer).GetComponent<MeshFilter>());
		if ((Object)(object)val == (Object)null || (Object)(object)val.sharedMesh == (Object)null || !val.sharedMesh.isReadable)
		{
			return;
		}
		Bounds bounds = binding.Renderer.bounds;
		Vector3 size = ((Bounds)(ref bounds)).size;
		if (!(size.y > Mathf.Max(size.x, size.z) * 0.25f))
		{
			binding.OriginalMesh = val.sharedMesh;
			binding.OwnedMesh = Object.Instantiate<Mesh>(binding.OriginalMesh);
			((Object)binding.OwnedMesh).name = "DirtyMass world-mapped " + ((Object)binding.OriginalMesh).name;
			((Object)binding.OwnedMesh).hideFlags = (HideFlags)52;
			binding.MappingOrigin = ((Component)binding.Renderer).transform.position;
			Vector3[] vertices = binding.OwnedMesh.vertices;
			Vector2[] array = (Vector2[])(object)new Vector2[vertices.Length];
			for (int i = 0; i < vertices.Length; i++)
			{
				Vector3 val2 = ((Component)binding.Renderer).transform.TransformPoint(vertices[i]);
				array[i] = new Vector2(val2.z, val2.x) / 6f;
			}
			binding.OwnedMesh.uv = array;
			Color32[] array2 = (Color32[])(object)new Color32[vertices.Length];
			for (int j = 0; j < array2.Length; j++)
			{
				array2[j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
			}
			binding.OwnedMesh.colors32 = array2;
			val.sharedMesh = binding.OwnedMesh;
		}
	}

	private void LogDistance()
	{
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: Unknown result type (might be due to invalid IL or missing references)
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		if (loggedDistance || (Object)(object)detailSource == (Object)null || Time.unscaledTime < nextDistanceCheck)
		{
			return;
		}
		nextDistanceCheck = Time.unscaledTime + 2f;
		Camera main = Camera.main;
		if (!((Object)(object)main == (Object)null))
		{
			float num = Mathf.Abs(((Component)main).transform.position.y - ((Component)mass).transform.position.y);
			if (!(num < 35f))
			{
				loggedDistance = true;
				float[] layerCullDistances = main.layerCullDistances;
				plugin.Log("Distant mass: height gap=" + num + "; camera far clip=" + main.farClipPlane + "; layer cull=" + layerCullDistances[((Component)detailSource).gameObject.layer] + "; visible=" + detailSource.isVisible + "; active=" + ((Component)detailSource).gameObject.activeInHierarchy + "; fog=" + RenderSettings.fog + "; fog mode=" + ((object)RenderSettings.fogMode/*cast due to .constrained prefix*/).ToString() + "; fog density=" + RenderSettings.fogDensity + "; fog range=" + RenderSettings.fogStartDistance + ".." + RenderSettings.fogEndDistance);
			}
		}
	}

	private Renderer ChooseDetailSource()
	{
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)visualOverride == (Object)null)
		{
			return (Renderer)(object)mass.deathFloorRenderer;
		}
		Renderer result = null;
		float num = 0f;
		MeshRenderer[] componentsInChildren = ((Component)visualOverride).GetComponentsInChildren<MeshRenderer>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			Renderer val = (Renderer)(object)componentsInChildren[i];
			Bounds bounds = val.bounds;
			Vector3 size = ((Bounds)(ref bounds)).size;
			if (size.x * size.z > num)
			{
				num = size.x * size.z;
				result = val;
			}
		}
		return result;
	}

	private void BuildDetails()
	{
		if (!((Object)(object)detailSource.sharedMaterial == (Object)null))
		{
			floating = new FloatingDetails(((Component)plugin).transform, ((Component)detailSource).gameObject.layer, surfaceShader, details[(int)mode], mode);
		}
	}

	private void AnimateDetails(float clock)
	{
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		if (floating != null && !((Object)(object)detailSource == (Object)null) && !((Object)(object)mass == (Object)null))
		{
			bool visible = ((Component)mass).gameObject.activeInHierarchy && ((Component)detailSource).gameObject.activeInHierarchy && detailSource.enabled && !detailSource.forceRenderingOff;
			Vector3 val;
			if (!((Object)(object)ENT_Player.playerObject != (Object)null))
			{
				Bounds bounds = detailSource.bounds;
				val = ((Bounds)(ref bounds)).center;
			}
			else
			{
				val = ((Component)ENT_Player.playerObject).transform.position;
			}
			Vector3 viewer = val;
			floating.Tick(detailSource, ((Component)mass).transform.position.y, viewer, clock, visible);
		}
	}

	private void ClearDetails()
	{
		if (floating != null)
		{
			floating.Dispose();
		}
		floating = null;
		detailSource = null;
	}

	internal void Restore()
	{
		ClearDetails();
		if ((Object)(object)ownedCorruption != (Object)null && (Object)(object)Shader.GetGlobalTexture("_CORRUPTTEXTURE") == (Object)(object)ownedCorruption)
		{
			Shader.SetGlobalTexture("_CORRUPTTEXTURE", originalCorruption);
		}
		originalCorruption = null;
		ownedCorruption = null;
		foreach (Binding binding in bindings)
		{
			binding.Release();
		}
		bindings.Clear();
		desired.Clear();
		mass = null;
		visualOverride = null;
		nextScan = 0f;
		loggedMass = 0;
		loggedDistance = false;
		nextDistanceCheck = 0f;
	}

	public void Dispose()
	{
		Restore();
		Texture2D[] array = surfaces;
		foreach (Texture2D val in array)
		{
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)val);
			}
		}
		array = details;
		foreach (Texture2D val2 in array)
		{
			if ((Object)(object)val2 != (Object)null)
			{
				Object.Destroy((Object)(object)val2);
			}
		}
	}
}
internal static class MaterialOwnership
{
	internal static bool Restore<T>(T[] current, T[] owned, T[] original) where T : class
	{
		bool result = false;
		for (int i = 0; i < current.Length && i < owned.Length && i < original.Length; i++)
		{
			if (owned[i] != null && current[i] == owned[i])
			{
				current[i] = original[i];
				result = true;
			}
		}
		return result;
	}
}
internal static class SurfaceMaterialFactory
{
	internal static bool IsStandard(Shader shader)
	{
		if (!(((Object)shader).name == "Standard"))
		{
			return ((Object)shader).name == "Standard (Specular setup)";
		}
		return true;
	}

	internal static Shader Resolve()
	{
		string[] array = new string[4] { "Unlit/Texture", "Legacy Shaders/Unlit/Texture", "Standard", "Standard (Specular setup)" };
		for (int i = 0; i < array.Length; i++)
		{
			Shader val = Shader.Find(array[i]);
			if ((Object)(object)val != (Object)null && val.isSupported)
			{
				return val;
			}
		}
		throw new InvalidOperationException("No supported unlit or emissive surface shader is available. Please provide BepInEx/LogOutput.log.");
	}

	internal static Material Create(Shader shader, Texture2D texture, Vector2 scale, string name)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected O, but got Unknown
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0172: Unknown result type (might be due to invalid IL or missing references)
		Material val = new Material(shader);
		try
		{
			((Object)val).name = name;
			((Object)val).hideFlags = (HideFlags)52;
			val.shaderKeywords = new string[0];
			if (!val.HasProperty("_MainTex"))
			{
				throw new InvalidOperationException("Surface shader has no _MainTex: " + ((Object)shader).name);
			}
			val.SetTexture("_MainTex", (Texture)(object)texture);
			val.SetTextureScale("_MainTex", scale);
			val.SetTextureOffset("_MainTex", Vector2.zero);
			val.renderQueue = 2000;
			if (IsStandard(shader))
			{
				if (!val.HasProperty("_EmissionMap") || !val.HasProperty("_EmissionColor"))
				{
					throw new InvalidOperationException("Standard fallback has no emission texture support.");
				}
				val.SetColor("_Color", new Color(0f, 0f, 0f, 1f));
				val.SetTexture("_EmissionMap", (Texture)(object)texture);
				val.SetTextureScale("_EmissionMap", scale);
				val.SetTextureOffset("_EmissionMap", Vector2.zero);
				val.SetColor("_EmissionColor", Color.white);
				val.EnableKeyword("_EMISSION");
				SetFloat(val, "_Metallic", 0f);
				SetFloat(val, "_Glossiness", 0f);
				SetFloat(val, "_GlossMapScale", 0f);
				SetFloat(val, "_SpecularHighlights", 0f);
				SetFloat(val, "_GlossyReflections", 0f);
				if (val.HasProperty("_SpecColor"))
				{
					val.SetColor("_SpecColor", Color.black);
				}
				val.EnableKeyword("_SPECULARHIGHLIGHTS_OFF");
				val.EnableKeyword("_GLOSSYREFLECTIONS_OFF");
				val.globalIlluminationFlags = (MaterialGlobalIlluminationFlags)0;
				SetFloat(val, "_Mode", 0f);
				SetFloat(val, "_SrcBlend", 1f);
				SetFloat(val, "_DstBlend", 0f);
				SetFloat(val, "_ZWrite", 1f);
				val.SetOverrideTag("RenderType", "Opaque");
			}
			else if (val.HasProperty("_Color"))
			{
				val.SetColor("_Color", Color.white);
			}
			return val;
		}
		catch
		{
			Object.Destroy((Object)(object)val);
			throw;
		}
	}

	private static void SetFloat(Material material, string name, float value)
	{
		if (material.HasProperty(name))
		{
			material.SetFloat(name, value);
		}
	}
}
internal static class TextureFactory
{
	internal static Texture2D Create(byte[] pixels, int size, string name)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Expected O, but got Unknown
		if (size <= 0 || pixels == null || pixels.Length != checked(size * size * 4))
		{
			throw new ArgumentException("Expected one complete RGBA32 base mip.");
		}
		Texture2D val = new Texture2D(size, size, (TextureFormat)4, true, false);
		try
		{
			((Object)val).name = name;
			((Object)val).hideFlags = (HideFlags)52;
			((Texture)val).wrapMode = (TextureWrapMode)0;
			((Texture)val).filterMode = (FilterMode)0;
			((Texture)val).anisoLevel = 2;
			val.SetPixelData<byte>(pixels, 0, 0);
			val.Apply(true, true);
			return val;
		}
		catch
		{
			Object.Destroy((Object)(object)val);
			throw;
		}
	}
}
public enum MassType
{
	Urine,
	Feces
}
internal static class TexturePixels
{
	internal static byte[] Surface(MassType mode, int size)
	{
		if (size < 32 || size > 1024)
		{
			throw new ArgumentOutOfRangeException("size");
		}
		byte[] array = new byte[size * size * 4];
		for (int i = 0; i < size; i++)
		{
			for (int j = 0; j < size; j++)
			{
				double num = (double)j / (double)size;
				double num2 = (double)i / (double)size;
				double num3 = Noise(num * 8.0, num2 * 8.0, 8);
				double num4 = Noise(num * 32.0, num2 * 32.0, 32);
				double num5 = (double)(Hash(j, i, 773) & 0xFF) / 255.0;
				if (mode == MassType.Urine)
				{
					double num6 = Noise(num * 4.0, num2 * 4.0, 4);
					double num7 = Math.Pow(0.5 + 0.5 * Math.Sin((num * 4.0 + num2 * 2.0 + num3 * 0.9) * Math.PI * 2.0), 9.0);
					double t = 0.1 + num6 * 0.57 + num4 * 0.1 + num7 * 0.32 + num5 * 0.025;
					Paint(array, (i * size + j) * 4, 99, 58, 3, 235, 181, 36, t);
				}
				else
				{
					double t = 0.12 + num3 * 0.64 + num4 * 0.17 + num5 * 0.045;
					Paint(array, (i * size + j) * 4, 39, 20, 9, 112, 69, 27, t);
				}
			}
		}
		Random random = new Random((mode == MassType.Urine) ? 19731 : 95371);
		int num8 = ((mode == MassType.Urine) ? 125 : 80);
		for (int k = 0; k < num8; k++)
		{
			int num9 = random.Next(size);
			int num10 = random.Next(size);
			int num11 = Math.Max(1, (int)((double)size * ((mode == MassType.Urine) ? (0.004 + random.NextDouble() * 0.012) : (0.008 + random.NextDouble() * 0.035))));
			int num12 = ((mode == MassType.Urine) ? num11 : Math.Max(2, (int)((double)num11 * (0.35 + random.NextDouble() * 0.6))));
			for (int l = -num12; l <= num12; l++)
			{
				for (int m = -num11; m <= num11; m++)
				{
					double num13 = (double)(m * m) / (double)(num11 * num11) + (double)(l * l) / (double)(num12 * num12);
					if (num13 > 1.0)
					{
						continue;
					}
					int i2 = (Wrap(num10 + l, size) * size + Wrap(num9 + m, size)) * 4;
					if (mode == MassType.Urine)
					{
						if (num13 > 0.45 || ((double)l < (double)(-num12) * 0.25 && m < 0))
						{
							Paint(array, i2, 176, 150, 70, 239, 224, 167, 0.4 + (1.0 - num13) * 0.4);
						}
					}
					else
					{
						double t2 = Math.Sqrt(1.0 - num13) * 0.7 - (double)l / (double)num12 * 0.2;
						Paint(array, i2, 35, 17, 7, 128, 80, 34, t2);
					}
				}
			}
		}
		return array;
	}

	internal static byte[] Detail(MassType mode, int size)
	{
		byte[] array = new byte[size * size * 4];
		for (int i = 0; i < size; i++)
		{
			for (int j = 0; j < size; j++)
			{
				double num = (double)j / (double)size;
				double num2 = (double)i / (double)size;
				double num3 = 0.2 + num2 * 0.55 + Math.Cos(num * Math.PI * 2.0) * 0.09;
				num3 += Noise(num * 8.0, num2 * 8.0, 8) * 0.14;
				if (mode == MassType.Urine)
				{
					Paint(array, (i * size + j) * 4, 153, 115, 32, 243, 228, 168, num3);
				}
				else
				{
					Paint(array, (i * size + j) * 4, 34, 16, 7, 115, 71, 28, num3);
				}
			}
		}
		return array;
	}

	private static void Paint(byte[] pixels, int i, int ar, int ag, int ab, int br, int bg, int bb, double t)
	{
		t = Math.Max(0.0, Math.Min(1.0, Math.Round(t * 10.0) / 10.0));
		pixels[i] = (byte)((double)ar + (double)(br - ar) * t);
		pixels[i + 1] = (byte)((double)ag + (double)(bg - ag) * t);
		pixels[i + 2] = (byte)((double)ab + (double)(bb - ab) * t);
		pixels[i + 3] = byte.MaxValue;
	}

	private static int Wrap(int n, int period)
	{
		return (n % period + period) % period;
	}

	private static uint Hash(int x, int y, int seed)
	{
		int num = x * 374761393 + y * 668265263 + seed * 1274126177;
		int num2 = (num ^ (num >>> 13)) * 1274126177;
		return (uint)(num2 ^ (num2 >>> 16));
	}

	private static double Noise(double x, double y, int period)
	{
		int num = (int)Math.Floor(x);
		int num2 = (int)Math.Floor(y);
		double num3 = x - (double)num;
		double num4 = y - (double)num2;
		num3 = num3 * num3 * (3.0 - 2.0 * num3);
		num4 = num4 * num4 * (3.0 - 2.0 * num4);
		double num5 = (double)(Hash(Wrap(num, period), Wrap(num2, period), 511) & 0xFFFF) / 65535.0;
		double num6 = (double)(Hash(Wrap(num + 1, period), Wrap(num2, period), 511) & 0xFFFF) / 65535.0;
		double num7 = (double)(Hash(Wrap(num, period), Wrap(num2 + 1, period), 511) & 0xFFFF) / 65535.0;
		double num8 = (double)(Hash(Wrap(num + 1, period), Wrap(num2 + 1, period), 511) & 0xFFFF) / 65535.0;
		return (num5 + (num6 - num5) * num3) * (1.0 - num4) + (num7 + (num8 - num7) * num3) * num4;
	}
}
internal enum DetailKind
{
	Foam,
	Lump,
	Ripple
}
internal struct DetailPiece
{
	internal int CellX;

	internal int CellZ;

	internal int Index;

	internal DetailKind Kind;

	internal float X;

	internal float Z;

	internal float Radius;

	internal float Length;

	internal float Height;

	internal float Angle;

	internal float Phase;

	internal float Speed;
}
internal static class WorldDetailLayout
{
	internal const float CellSize = 8f;

	internal const int ViewRadius = 3;

	internal const float TextureRepeat = 6f;

	internal static int Cell(float coordinate)
	{
		return (int)Math.Floor(coordinate / 8f);
	}

	internal static List<DetailPiece> Generate(MassType mode, int centerX, int centerZ, float minX, float maxX, float minZ, float maxZ)
	{
		List<DetailPiece> list = new List<DetailPiece>();
		for (int i = centerZ - 3; i <= centerZ + 3; i++)
		{
			for (int j = centerX - 3; j <= centerX + 3; j++)
			{
				if ((float)(j + 1) * 8f < minX || (float)j * 8f > maxX || (float)(i + 1) * 8f < minZ || (float)i * 8f > maxZ)
				{
					continue;
				}
				Random random = new Random((j * 73856093) ^ (i * 19349663) ^ ((mode == MassType.Urine) ? 24719 : 95371));
				int num = 0;
				int num2 = ((mode == MassType.Urine) ? 3 : (3 + random.Next(2)));
				for (int k = 0; k < num2; k++)
				{
					float num3 = (float)j * 8f + Range(random, 1.1f, 6.9f);
					float num4 = (float)i * 8f + Range(random, 1.1f, 6.9f);
					int num5 = ((mode != MassType.Urine) ? 1 : (3 + random.Next(3)));
					for (int l = 0; l < num5; l++)
					{
						float num6 = ((mode == MassType.Urine) ? Range(random, 0.05f, 0.16f) : Range(random, 0.18f, 0.52f));
						DetailPiece piece = new DetailPiece
						{
							CellX = j,
							CellZ = i,
							Index = num++,
							Kind = ((mode != MassType.Urine) ? DetailKind.Lump : DetailKind.Foam),
							X = num3 + ((l == 0) ? 0f : Range(random, -0.4f, 0.4f)),
							Z = num4 + ((l == 0) ? 0f : Range(random, -0.4f, 0.4f)),
							Radius = num6,
							Length = num6 * ((mode == MassType.Urine) ? 1f : Range(random, 1.6f, 2.6f)),
							Height = num6 * ((mode == MassType.Urine) ? 0.38f : 0.6f),
							Angle = Range(random, 0f, MathF.PI * 2f),
							Phase = Range(random, 0f, 1f),
							Speed = Range(random, 0.12f, 0.22f)
						};
						Add(list, piece, minX, maxX, minZ, maxZ);
					}
					if (mode == MassType.Urine)
					{
						DetailPiece piece2 = new DetailPiece
						{
							CellX = j,
							CellZ = i,
							Index = num++,
							Kind = DetailKind.Ripple,
							X = num3,
							Z = num4,
							Radius = Range(random, 0.65f, 1.25f),
							Phase = Range(random, 0f, 1f),
							Speed = Range(random, 0.14f, 0.23f)
						};
						Add(list, piece2, minX, maxX, minZ, maxZ);
					}
				}
			}
		}
		return list;
	}

	private static void Add(List<DetailPiece> pieces, DetailPiece piece, float minX, float maxX, float minZ, float maxZ)
	{
		float num = Math.Max(piece.Radius, piece.Length) * ((piece.Kind == DetailKind.Lump) ? 1.1f : 1f);
		if (piece.X - num >= minX && piece.X + num <= maxX && piece.Z - num >= minZ && piece.Z + num <= maxZ)
		{
			pieces.Add(piece);
		}
	}

	private static float Range(Random random, float low, float high)
	{
		return low + (float)random.NextDouble() * (high - low);
	}
}