Decompiled source of BLOODLAB v0.6.9

Mods/BloodLabMod.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text.Json;
using BloodLabMod.Core;
using MelonLoader;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(BloodLabMod.Core.BloodLabMod), "BloodLabMod", "1.0.0", "fxleons")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("BloodLabMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+5e16ae1fe7ffb66e8ea5b08c010a9eba18f1c329")]
[assembly: AssemblyProduct("BloodLabMod")]
[assembly: AssemblyTitle("BloodLabMod")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BloodLabMod.Core
{
	public class BloodDroplet : MonoBehaviour
	{
		private Rigidbody rb;

		public float Volume { get; private set; }

		public Vector3 LastNormal { get; private set; }

		public Vector3 Position => transform.position;

		public bool IsSettled { get; private set; }

		public void Initialize(Vector3 initialVelocity, float volume)
		{
			if (rb == null)
			{
				rb = gameObject.GetComponent<Rigidbody>();
			}
			if (rb == null)
			{
				rb = gameObject.AddComponent<Rigidbody>();
			}
			rb.useGravity = true;
			rb.velocity = initialVelocity;
			rb.mass = Mathf.Clamp(volume * 0.1f, 0.01f, 5f);
			Volume = Mathf.Clamp(volume, 0.001f, 1f);
			IsSettled = false;
			LastNormal = Vector3.up;
		}

		public void Simulate(float dt)
		{
			if (rb != null && !IsSettled && rb.velocity.sqrMagnitude < 0.01f && transform.position.y < 10f)
			{
				IsSettled = true;
				if (Physics.Raycast(transform.position, -Vector3.up, out var hit, 0.5f))
				{
					LastNormal = hit.normal;
				}
				rb.isKinematic = true;
			}
		}

		private void OnCollisionEnter(Collision collision)
		{
			if (collision.contacts.Length != 0)
			{
				LastNormal = collision.contacts[0].normal;
			}
			if (rb != null)
			{
				rb.velocity = rb.velocity * 0.3f + collision.contacts[0].normal * -0.2f;
			}
		}
	}
	public class BloodLabMod : MelonMod
	{
		private static bool initialized;

		public override void OnApplicationStart()
		{
			if (!initialized)
			{
				initialized = true;
				MelonLogger.Msg("BloodLabMod initializing...");
				ConfigManager.Load();
				PoolManager.Initialize();
				WoundManager.Initialize();
				DropletManager.Initialize();
				PuddleManager.Initialize();
				DecalManager.Initialize();
				WeaponBloodManager.Initialize();
				PlayerBloodManager.Initialize();
				HookManager.Initialize();
			}
		}

		public override void OnUpdate()
		{
			WoundManager.UpdateAll(Time.deltaTime);
			DropletManager.UpdateAll(Time.deltaTime);
			PuddleManager.UpdateAll(Time.deltaTime);
			WeaponBloodManager.UpdateAll(Time.deltaTime);
			PlayerBloodManager.UpdateAll(Time.deltaTime);
		}
	}
	public class BloodPuddle
	{
		private Vector3 normal;

		private float volume;

		private GameObject decalGO;

		private float age;

		public Vector3 Position { get; private set; }

		public bool IsExpired => age > ConfigManager.Settings.DecalLifetime * 2f;

		public BloodPuddle(Vector3 position, Vector3 normal, float initialVolume)
		{
			Position = position;
			this.normal = normal;
			volume = initialVolume;
			age = 0f;
			SpawnDecal();
		}

		private void SpawnDecal()
		{
			GameObject gameObject = Resources.Load<GameObject>("BloodPrefabs/BloodPuddle");
			if (gameObject != null)
			{
				decalGO = GameObject.Instantiate(gameObject);
				decalGO.transform.position = Position + normal * 0.01f;
				decalGO.transform.rotation = Quaternion.LookRotation(normal);
				UpdateVisual();
			}
		}

		public void AddVolume(float v)
		{
			volume += v;
			UpdateVisual();
		}

		public void Update(float dt)
		{
			age += dt;
			if (decalGO != null)
			{
				Renderer component = decalGO.GetComponent<Renderer>();
				if (component != null && component.material != null)
				{
					Color bloodColor = ConfigManager.Settings.BloodColor;
					float t = Mathf.Clamp01(age * ConfigManager.Settings.BloodDryingSpeed);
					component.material.color = Color.Lerp(bloodColor, Color.black, t);
				}
			}
		}

		private void UpdateVisual()
		{
			if (decalGO != null)
			{
				float num = Mathf.Clamp(0.1f + volume * 0.5f, 0.1f, 5f);
				decalGO.transform.localScale = new Vector3(num, 1f, num);
			}
		}

		public void Destroy()
		{
			if (decalGO != null)
			{
				GameObject.Destroy(decalGO);
			}
		}
	}
	public class BloodWound
	{
		private float bleedIntensity;

		private float lifeTimer;

		private float maxLife;

		public Transform Parent { get; private set; }

		public Vector3 LocalPosition { get; private set; }

		public Vector3 Normal { get; private set; }

		public float Damage { get; private set; }

		public string BodyPart { get; private set; }

		public bool IsFinished
		{
			get
			{
				if (bleedIntensity <= 0f)
				{
					return lifeTimer > maxLife;
				}
				return false;
			}
		}

		public BloodWound(Transform parent, Vector3 localPos, Vector3 normal, float damage, string bodyPart)
		{
			Parent = parent;
			LocalPosition = localPos;
			Normal = normal;
			Damage = damage;
			BodyPart = bodyPart;
			bleedIntensity = Mathf.Clamp01(damage * 0.1f);
			maxLife = Mathf.Max(30f, damage * 10f) * ConfigManager.Settings.BleedingDurationMultiplier;
			lifeTimer = 0f;
			DropletManager.SpawnGore(Parent.TransformPoint(LocalPosition), Normal, Mathf.Clamp01(bleedIntensity));
		}

		public void Update(float dt)
		{
			lifeTimer += dt;
			if (bleedIntensity > 0f)
			{
				float amount = bleedIntensity * dt * (1f - lifeTimer / maxLife);
				DropletManager.SpawnDrip(Parent.TransformPoint(LocalPosition), Normal, amount);
				bleedIntensity = Mathf.Max(0f, bleedIntensity - dt * 0.01f);
			}
		}
	}
	public static class BodyPartIdentifier
	{
		public static string Identify(Transform root, Transform hitTransform)
		{
			if (hitTransform == null)
			{
				return "unknown";
			}
			string text = hitTransform.name.ToLower();
			if (text.Contains("head") || text.Contains("skull"))
			{
				return "head";
			}
			if (text.Contains("spine") || text.Contains("chest") || text.Contains("torso"))
			{
				return "torso";
			}
			if (text.Contains("arm") || text.Contains("hand") || text.Contains("shoulder"))
			{
				return "arm";
			}
			if (text.Contains("leg") || text.Contains("thigh") || text.Contains("foot"))
			{
				return "leg";
			}
			return "limb";
		}
	}
	public static class ConfigManager
	{
		public class Config
		{
			public float BloodMultiplier = 1f;

			public float PlayerBloodMultiplier = 1f;

			public float NPCBloodMultiplier = 1f;

			public float BleedingDurationMultiplier = 1f;

			public int MaxDroplets = 500;

			public int MaxPuddles = 200;

			public bool PerformanceMode;

			public float DecalLifetime = 300f;

			public Color BloodColor = new Color(0.6f, 0.05f, 0.03f, 1f);

			public float DripFrequency = 1f;

			public float BloodDryingSpeed = 0.01f;
		}

		public static Config Settings = new Config();

		private static string configPath = Path.Combine(Application.dataPath, "BloodLabModConfig.json");

		public static void Load()
		{
			if (File.Exists(configPath))
			{
				try
				{
					Settings = JsonUtility.FromJson<Config>(File.ReadAllText(configPath)) ?? new Config();
					return;
				}
				catch
				{
					Settings = new Config();
					return;
				}
			}
			Save();
		}

		public static void Save()
		{
			try
			{
				string contents = JsonUtility.ToJson(Settings, pretty: true);
				File.WriteAllText(configPath, contents);
			}
			catch
			{
			}
		}
	}
	public struct DamageInfo
	{
		public Transform Target;

		public Vector3 HitPoint;

		public Vector3 HitNormal;

		public float Damage;

		public string BodyPart;

		public GameObject Source;
	}
	public static class DecalManager
	{
		public static void Initialize()
		{
		}

		public static void SpawnWallSplat(Vector3 pos, Vector3 normal, float size, float intensity)
		{
			GameObject gameObject = Resources.Load<GameObject>("BloodPrefabs/BloodDecal");
			if (gameObject != null)
			{
				GameObject gameObject2 = GameObject.Instantiate(gameObject);
				gameObject2.transform.position = pos + normal * 0.01f;
				gameObject2.transform.rotation = Quaternion.LookRotation(normal);
				gameObject2.transform.localScale = Vector3.one * Mathf.Clamp(size * intensity, 0.2f, 6f);
				Renderer component = gameObject2.GetComponent<Renderer>();
				if (component != null && component.material != null)
				{
					component.material.color = ConfigManager.Settings.BloodColor;
				}
				GameObject.Destroy(gameObject2, ConfigManager.Settings.DecalLifetime);
			}
		}
	}
	public static class DropletManager
	{
		private static List<BloodDroplet> droplets = new List<BloodDroplet>();

		public static void Initialize()
		{
		}

		public static void SpawnGore(Vector3 pos, Vector3 normal, float intensity)
		{
			int num = Mathf.CeilToInt(Mathf.Clamp(5f * intensity * ConfigManager.Settings.BloodMultiplier, 1f, 50f));
			for (int i = 0; i < num; i++)
			{
				SpawnDroplet(pos + UnityEngine.Random.insideUnitSphere * 0.05f, UnityEngine.Random.onUnitSphere * 0.5f + -normal * 1f, intensity);
			}
		}

		public static void SpawnDrip(Vector3 pos, Vector3 normal, float amount)
		{
			if (droplets.Count <= ConfigManager.Settings.MaxDroplets && !(amount <= 0.0001f))
			{
				SpawnDroplet(pos + normal * 0.01f, -normal * UnityEngine.Random.Range(0.1f, 0.3f), amount);
			}
		}

		private static void SpawnDroplet(Vector3 pos, Vector3 velocity, float volume)
		{
			GameObject gameObject = PoolManager.Get("BloodPrefabs/BloodDroplet");
			if (gameObject != null)
			{
				gameObject.transform.position = pos;
				gameObject.transform.rotation = UnityEngine.Random.rotation;
				gameObject.SetActive(v: true);
				BloodDroplet bloodDroplet = gameObject.GetComponent<BloodDroplet>();
				if (bloodDroplet == null)
				{
					bloodDroplet = gameObject.AddComponent<BloodDroplet>();
				}
				bloodDroplet.Initialize(velocity, volume);
				droplets.Add(bloodDroplet);
			}
		}

		public static void UpdateAll(float dt)
		{
			for (int num = droplets.Count - 1; num >= 0; num--)
			{
				BloodDroplet bloodDroplet = droplets[num];
				bloodDroplet.Simulate(dt);
				if (bloodDroplet.IsSettled)
				{
					droplets.RemoveAt(num);
					PuddleManager.SeedPuddle(bloodDroplet.Position, bloodDroplet.Volume, bloodDroplet.LastNormal);
					PoolManager.Release("BloodPrefabs/BloodDroplet", bloodDroplet.gameObject);
				}
			}
		}
	}
	public class ExampleDamageReceiver : MonoBehaviour
	{
		public Transform target;

		public void SimulateHit(Vector3 worldPos, Vector3 normal, float damage)
		{
			if (target != null)
			{
				string bodyPart = BodyPartIdentifier.Identify(target, transform);
				HookManager.OnEntityHit(target, worldPos, normal, damage, bodyPart, gameObject);
			}
		}
	}
	public static class HookManager
	{
		public static void Initialize()
		{
		}

		public static void OnEntityHit(Transform entity, Vector3 hitWorldPos, Vector3 hitNormal, float damage, string bodyPart, GameObject hitSource)
		{
			Vector3 localPos = entity.InverseTransformPoint(hitWorldPos);
			WoundManager.CreateWound(entity, localPos, hitNormal, damage, bodyPart);
			DropletManager.SpawnGore(hitWorldPos, hitNormal, damage * ConfigManager.Settings.BloodMultiplier);
			if (hitSource == null)
			{
				DecalManager.SpawnWallSplat(hitWorldPos, hitNormal, 1f + damage * 0.5f, Mathf.Clamp01(damage * 0.2f));
			}
			if (hitSource != null)
			{
				WeaponBloodManager.AddBloodToWeapon(hitSource.transform, damage * 0.1f);
			}
		}
	}
	public static class PlayerBloodManager
	{
		private static Dictionary<Transform, List<BloodWound>> playerWounds = new Dictionary<Transform, List<BloodWound>>();

		public static void Initialize()
		{
		}

		public static void RegisterPlayer(Transform player)
		{
			if (!playerWounds.ContainsKey(player))
			{
				playerWounds[player] = new List<BloodWound>();
			}
		}

		public static void AddWound(Transform player, Vector3 localPos, Vector3 normal, float damage, string bodyPart)
		{
			BloodWound item = WoundManager.CreateWound(player, localPos, normal, damage, bodyPart);
			if (!playerWounds.ContainsKey(player))
			{
				playerWounds[player] = new List<BloodWound>();
			}
			playerWounds[player].Add(item);
		}

		public static void UpdateAll(float dt)
		{
		}
	}
	public static class PoolManager
	{
		private static Dictionary<string, Queue<GameObject>> pools = new Dictionary<string, Queue<GameObject>>();

		private static GameObject root;

		public static void Initialize()
		{
			root = new GameObject("BloodLab_Pools");
			UnityEngine.Object.DontDestroyOnLoad(root);
		}

		public static GameObject Get(string resourcePath, int initialSize = 10)
		{
			if (!pools.ContainsKey(resourcePath))
			{
				pools[resourcePath] = new Queue<GameObject>();
			}
			Queue<GameObject> queue = pools[resourcePath];
			if (queue.Count == 0)
			{
				GameObject gameObject = Resources.Load<GameObject>(resourcePath);
				if (gameObject == null)
				{
					return null;
				}
				GameObject gameObject2 = UnityEngine.Object.Instantiate(gameObject, root.transform);
				gameObject2.SetActive(v: false);
				return gameObject2;
			}
			return queue.Dequeue();
		}

		public static void Release(string resourcePath, GameObject obj)
		{
			if (obj != null)
			{
				obj.SetActive(v: false);
				if (!pools.ContainsKey(resourcePath))
				{
					pools[resourcePath] = new Queue<GameObject>();
				}
				pools[resourcePath].Enqueue(obj);
				obj.transform.SetParent(root.transform, worldPositionStays: false);
			}
		}
	}
	public static class PuddleManager
	{
		private static List<BloodPuddle> puddles = new List<BloodPuddle>();

		public static void Initialize()
		{
		}

		public static void SeedPuddle(Vector3 worldPos, float volume, Vector3 normal)
		{
			float num = 1f;
			BloodPuddle bloodPuddle = null;
			float num2 = float.MaxValue;
			foreach (BloodPuddle puddle in puddles)
			{
				float num3 = Vector3.Distance(puddle.Position, worldPos);
				if (num3 < num2 && num3 < num)
				{
					num2 = num3;
					bloodPuddle = puddle;
				}
			}
			if (bloodPuddle != null)
			{
				bloodPuddle.AddVolume(volume);
			}
			else if (puddles.Count <= ConfigManager.Settings.MaxPuddles)
			{
				BloodPuddle item = new BloodPuddle(worldPos, normal, volume);
				puddles.Add(item);
			}
		}

		public static void UpdateAll(float dt)
		{
			for (int num = puddles.Count - 1; num >= 0; num--)
			{
				BloodPuddle bloodPuddle = puddles[num];
				bloodPuddle.Update(dt);
				if (bloodPuddle.IsExpired)
				{
					bloodPuddle.Destroy();
					puddles.RemoveAt(num);
				}
			}
		}
	}
	public static class WeaponBloodManager
	{
		private static Dictionary<Transform, float> weaponBlood = new Dictionary<Transform, float>();

		public static void Initialize()
		{
		}

		public static void AddBloodToWeapon(Transform weapon, float amount)
		{
			if (!weaponBlood.ContainsKey(weapon))
			{
				weaponBlood[weapon] = 0f;
			}
			weaponBlood[weapon] += amount;
		}

		public static void UpdateAll(float dt)
		{
			foreach (Transform item in new List<Transform>(weaponBlood.Keys))
			{
				weaponBlood[item] = Mathf.Max(0f, weaponBlood[item] - dt * 0.001f * ConfigManager.Settings.BloodDryingSpeed);
			}
		}
	}
	public static class WoundManager
	{
		private static List<BloodWound> wounds = new List<BloodWound>();

		public static void Initialize()
		{
		}

		public static BloodWound CreateWound(Transform parent, Vector3 localPos, Vector3 normal, float damage, string bodyPart)
		{
			BloodWound bloodWound = new BloodWound(parent, localPos, normal, damage, bodyPart);
			wounds.Add(bloodWound);
			return bloodWound;
		}

		public static void UpdateAll(float dt)
		{
			for (int num = wounds.Count - 1; num >= 0; num--)
			{
				BloodWound bloodWound = wounds[num];
				bloodWound.Update(dt);
				if (bloodWound.IsFinished)
				{
					wounds.RemoveAt(num);
				}
			}
		}

		public static IEnumerable<BloodWound> GetWoundsFor(Transform t)
		{
			foreach (BloodWound wound in wounds)
			{
				if (wound.Parent == t)
				{
					yield return wound;
				}
			}
		}
	}
}
namespace UnityEngine
{
	public struct Vector3
	{
		public float x;

		public float y;

		public float z;

		public static Vector3 zero => new Vector3(0f, 0f, 0f);

		public static Vector3 one => new Vector3(1f, 1f, 1f);

		public static Vector3 up => new Vector3(0f, 1f, 0f);

		public float sqrMagnitude => x * x + y * y + z * z;

		public Vector3(float x, float y, float z)
		{
			this.x = x;
			this.y = y;
			this.z = z;
		}

		public static Vector3 operator -(Vector3 a)
		{
			return new Vector3(0f - a.x, 0f - a.y, 0f - a.z);
		}

		public static Vector3 operator +(Vector3 a, Vector3 b)
		{
			return new Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
		}

		public static Vector3 operator -(Vector3 a, Vector3 b)
		{
			return new Vector3(a.x - b.x, a.y - b.y, a.z - b.z);
		}

		public static Vector3 operator *(Vector3 a, float s)
		{
			return new Vector3(a.x * s, a.y * s, a.z * s);
		}

		public static float Distance(Vector3 a, Vector3 b)
		{
			float num = a.x - b.x;
			float num2 = a.y - b.y;
			float num3 = a.z - b.z;
			return (float)Math.Sqrt(num * num + num2 * num2 + num3 * num3);
		}
	}
	[StructLayout(LayoutKind.Sequential, Size = 1)]
	public struct Quaternion
	{
		public static Quaternion identity => default(Quaternion);

		public static Quaternion LookRotation(Vector3 v)
		{
			return identity;
		}
	}
	public class Object
	{
		public string name = "Object";

		public static void DontDestroyOnLoad(Object obj)
		{
		}

		public static GameObject Instantiate(GameObject prefab, Transform parent)
		{
			return GameObject.Instantiate(prefab, parent);
		}
	}
	public static class Application
	{
		public static string dataPath => Directory.GetCurrentDirectory();
	}
	public static class ObjectEx
	{
		public static void DontDestroyOnLoad(Object obj)
		{
		}

		public static GameObject Instantiate(GameObject prefab, Transform parent)
		{
			return GameObject.Instantiate(prefab, parent);
		}
	}
	public class Component : Object
	{
		public Transform transform = new Transform();

		public GameObject gameObject = new GameObject();
	}
	public class GameObject : Object
	{
		public Transform transform = new Transform();

		public bool activeSelf = true;

		private List<Component> components = new List<Component>();

		public GameObject()
		{
			transform = new Transform();
			transform.parent = null;
			transform.gameObject = this;
		}

		public GameObject(string name)
		{
			base.name = name;
			transform = new Transform();
			transform.gameObject = this;
		}

		public void SetActive(bool v)
		{
			activeSelf = v;
		}

		public T GetComponent<T>() where T : Component
		{
			foreach (Component component in components)
			{
				if (component as T != null)
				{
					return (T)component;
				}
			}
			return null;
		}

		public T AddComponent<T>() where T : Component, new()
		{
			T val = new T
			{
				gameObject = this,
				transform = transform
			};
			components.Add(val);
			return val;
		}

		public static T Instantiate<T>(T prefab) where T : GameObject
		{
			return (T)Activator.CreateInstance(typeof(T));
		}

		public static GameObject Instantiate(GameObject prefab)
		{
			return new GameObject(prefab?.name ?? "GO");
		}

		public new static GameObject Instantiate(GameObject prefab, Transform parent)
		{
			return new GameObject(prefab?.name ?? "GO")
			{
				transform = 
				{
					parent = parent
				}
			};
		}

		public static void Destroy(GameObject go)
		{
		}

		public static void Destroy(GameObject go, float t)
		{
		}
	}
	public class Transform : Object
	{
		public Vector3 position = Vector3.zero;

		public Quaternion rotation = Quaternion.identity;

		public Transform parent;

		public Vector3 localScale = new Vector3(1f, 1f, 1f);

		public GameObject gameObject;

		public Vector3 TransformPoint(Vector3 p)
		{
			return position + p;
		}

		public Vector3 InverseTransformPoint(Vector3 p)
		{
			return new Vector3(p.x - position.x, p.y - position.y, p.z - position.z);
		}

		public void SetParent(Transform p, bool worldPositionStays = true)
		{
			parent = p;
		}
	}
	public class MonoBehaviour : Component
	{
	}
	public class Rigidbody : Component
	{
		public bool useGravity;

		public bool isKinematic;

		public Vector3 velocity;

		public float mass;
	}
	public class Renderer : Component
	{
		public Material material = new Material();
	}
	public class Material
	{
		public Color color = new Color(1f, 0f, 0f, 1f);
	}
	public struct Color
	{
		public float r;

		public float g;

		public float b;

		public float a;

		public static Color black => new Color(0f, 0f, 0f, 1f);

		public Color(float r, float g, float b, float a)
		{
			this.r = r;
			this.g = g;
			this.b = b;
			this.a = a;
		}

		public static Color Lerp(Color a, Color b, float t)
		{
			return new Color(a.r * (1f - t) + b.r * t, a.g * (1f - t) + b.g * t, a.b * (1f - t) + b.b * t, a.a * (1f - t) + b.a * t);
		}
	}
	public static class Resources
	{
		public static T Load<T>(string path) where T : class
		{
			return null;
		}
	}
	public static class Time
	{
		public static float deltaTime => 0.016f;
	}
	public static class Random
	{
		private static readonly System.Random rnd = new System.Random(0);

		public static Vector3 insideUnitSphere => new Vector3((float)(rnd.NextDouble() - 0.5), (float)(rnd.NextDouble() - 0.5), (float)(rnd.NextDouble() - 0.5));

		public static Vector3 onUnitSphere => insideUnitSphere;

		public static Quaternion rotation => Quaternion.identity;

		public static float Range(float a, float b)
		{
			return a + (float)rnd.NextDouble() * (b - a);
		}
	}
	public static class Mathf
	{
		public static int CeilToInt(float v)
		{
			return (int)Math.Ceiling(v);
		}

		public static float Clamp01(float v)
		{
			if (!(v < 0f))
			{
				if (!(v > 1f))
				{
					return v;
				}
				return 1f;
			}
			return 0f;
		}

		public static float Clamp(float v, float a, float b)
		{
			if (!(v < a))
			{
				if (!(v > b))
				{
					return v;
				}
				return b;
			}
			return a;
		}

		public static float Max(float a, float b)
		{
			if (!(a > b))
			{
				return b;
			}
			return a;
		}

		public static float Lerp(float a, float b, float t)
		{
			return a + (b - a) * t;
		}
	}
	public class Collision
	{
		public ContactPoint[] contacts = new ContactPoint[0];
	}
	public struct ContactPoint
	{
		public Vector3 normal;
	}
	public struct RaycastHit
	{
		public Vector3 point;

		public Vector3 normal;
	}
	public static class Physics
	{
		public static bool Raycast(Vector3 origin, Vector3 dir, out RaycastHit hit, float max)
		{
			hit = default(RaycastHit);
			return false;
		}
	}
	public static class JsonUtility
	{
		public static T FromJson<T>(string json)
		{
			return JsonSerializer.Deserialize<T>(json);
		}

		public static string ToJson<T>(T obj, bool pretty = false)
		{
			return JsonSerializer.Serialize(obj);
		}
	}
}
namespace MelonLoader
{
	[AttributeUsage(AttributeTargets.Assembly)]
	public sealed class MelonInfoAttribute : Attribute
	{
		public MelonInfoAttribute(Type t, string name, string version, string author)
		{
		}
	}
	public class MelonMod
	{
		public virtual void OnApplicationStart()
		{
		}

		public virtual void OnUpdate()
		{
		}
	}
	public static class MelonLogger
	{
		public static void Msg(string s)
		{
			Console.WriteLine(s);
		}
	}
}