Decompiled source of BuceesStation v1.0.4

BuceesTextures.dll

Decompiled 2 months ago
using System;
using System.Collections;
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 BepInEx;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("BuceesFix3")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("BuceesFix3")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("041a1648-997a-4121-a82d-24ef27ea1368")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace BuceesTextures;

[BepInPlugin("rebecca.repo.buceestextures", "Bucees Texture Swaps", "1.0.5")]
public class BuceesTexturesPlugin : BaseUnityPlugin
{
	private enum SwapKind
	{
		BaseColor,
		Emissive
	}

	private struct SwapSpec
	{
		public string PngStem;

		public SwapKind Kind;

		public SwapSpec(string stem, SwapKind kind)
		{
			PngStem = stem;
			Kind = kind;
		}
	}

	[CompilerGenerated]
	private sealed class <SwapWorker>d__20 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public BuceesTexturesPlugin <>4__this;

		private int <i>5__1;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <SwapWorker>d__20(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = null;
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				<>2__current = null;
				<>1__state = 2;
				return true;
			case 2:
				<>1__state = -1;
				goto IL_01c2;
			case 3:
				<>1__state = -1;
				goto IL_01c2;
			case 4:
				<>1__state = -1;
				goto IL_0170;
			case 5:
				{
					<>1__state = -1;
					goto IL_01c2;
				}
				IL_01c2:
				if (<>4__this._pngTextures.Count == 0)
				{
					<>2__current = (object)new WaitForSeconds(2f);
					<>1__state = 3;
					return true;
				}
				if (<>4__this._forceRefresh || Time.time >= <>4__this._nextCacheRefreshTime || <>4__this._materialCache.Count == 0)
				{
					<>4__this.RefreshMaterialCache();
					<>4__this._forceRefresh = false;
					<>4__this._nextCacheRefreshTime = Time.time + 5f;
				}
				<i>5__1 = 0;
				goto IL_0183;
				IL_0183:
				if (<i>5__1 < <>4__this._materialCache.Count)
				{
					<>4__this.ApplyToMaterial(<>4__this._materialCache[<i>5__1]);
					if (<i>5__1 % 70 == 0)
					{
						<>2__current = null;
						<>1__state = 4;
						return true;
					}
					goto IL_0170;
				}
				<>2__current = (object)new WaitForSeconds(1.25f);
				<>1__state = 5;
				return true;
				IL_0170:
				<i>5__1++;
				goto IL_0183;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	public const string PluginGuid = "rebecca.repo.buceestextures";

	public const string PluginName = "Bucees Texture Swaps";

	public const string PluginVersion = "1.0.5";

	private readonly Dictionary<string, SwapSpec> _replacements = new Dictionary<string, SwapSpec>(StringComparer.OrdinalIgnoreCase)
	{
		{
			"painting board",
			new SwapSpec("bucees_paintingBoard", SwapKind.BaseColor)
		},
		{
			"painting aurora",
			new SwapSpec("bucees_AuroraPainting", SwapKind.BaseColor)
		},
		{
			"Painting McJannek",
			new SwapSpec("bucees_painting", SwapKind.BaseColor)
		},
		{
			"Painting McJannek Outside",
			new SwapSpec("bucees_paintingOutside", SwapKind.BaseColor)
		},
		{
			"painting calendar",
			new SwapSpec("bucees_calendar", SwapKind.BaseColor)
		},
		{
			"shop props_DefaultMaterial_BaseColor",
			new SwapSpec("bucees_shopprops", SwapKind.BaseColor)
		},
		{
			"centrifuge_Arctic Valuable Centrifuge_BaseColor",
			new SwapSpec("bucees_centrifuge", SwapKind.BaseColor)
		},
		{
			"arctic valuable big crate_DefaultMaterial_BaseColor",
			new SwapSpec("bucees_crate", SwapKind.BaseColor)
		},
		{
			"heavy water_DefaultMaterial_BaseColor",
			new SwapSpec("bucees_heavywater", SwapKind.BaseColor)
		},
		{
			"arctic small valuables_DefaultMaterial_BaseColor",
			new SwapSpec("bucees_mug", SwapKind.BaseColor)
		},
		{
			"new valaubles_Valuable Arctic Calculator_BaseColor",
			new SwapSpec("bucees_calculator", SwapKind.BaseColor)
		},
		{
			"cryo pod_Arctic Valuable Cryo Pod_BaseColor",
			new SwapSpec("bucees_cryopod", SwapKind.BaseColor)
		},
		{
			"cryo pod_Arctic Valuable Cryo Pod_Emissive",
			new SwapSpec("bucees_cryopod_emissive", SwapKind.Emissive)
		},
		{
			"new valaubles_Valuable Arctic Keycard_BaseColor",
			new SwapSpec("bucees_keycard", SwapKind.BaseColor)
		},
		{
			"new valaubles_Valuable Arctic Scale_BaseColor",
			new SwapSpec("bucees_scale", SwapKind.BaseColor)
		},
		{
			"science station new uv_DefaultMaterial_BaseColor",
			new SwapSpec("bucees_sciencestation", SwapKind.BaseColor)
		},
		{
			"Arctic snow bike_DefaultMaterial_BaseColor",
			new SwapSpec("bucees_snowbike", SwapKind.BaseColor)
		}
	};

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

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

	private readonly List<Material> _materialCache = new List<Material>(2048);

	private readonly HashSet<int> _materialIds = new HashSet<int>();

	private readonly Dictionary<int, string[]> _shaderTexturePropsCache = new Dictionary<int, string[]>();

	private bool _forceRefresh;

	private const int MaterialsPerFrame = 70;

	private const float CacheRefreshInterval = 5f;

	private const float IdleDelay = 1.25f;

	private float _nextCacheRefreshTime;

	private string PngFolder => Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);

	private void Awake()
	{
		LoadAllPngs();
		SceneManager.sceneLoaded += delegate
		{
			_forceRefresh = true;
		};
		SceneManager.activeSceneChanged += delegate
		{
			_forceRefresh = true;
		};
		_forceRefresh = true;
		((MonoBehaviour)this).StartCoroutine(SwapWorker());
	}

	private void LoadAllPngs()
	{
		foreach (SwapSpec value in _replacements.Values)
		{
			if (!_pngTextures.ContainsKey(value.PngStem))
			{
				Texture2D val = LoadPngTexture(value.PngStem);
				if ((Object)(object)val != (Object)null)
				{
					_pngTextures[value.PngStem] = val;
					_ourTextureNames.Add(((Object)val).name);
				}
			}
		}
	}

	[IteratorStateMachine(typeof(<SwapWorker>d__20))]
	private IEnumerator SwapWorker()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <SwapWorker>d__20(0)
		{
			<>4__this = this
		};
	}

	private void RefreshMaterialCache()
	{
		_materialCache.Clear();
		_materialIds.Clear();
		Material[] array = Resources.FindObjectsOfTypeAll<Material>();
		foreach (Material val in array)
		{
			if (!((Object)(object)val == (Object)null))
			{
				int instanceID = ((Object)val).GetInstanceID();
				if (_materialIds.Add(instanceID))
				{
					_materialCache.Add(val);
				}
			}
		}
	}

	private void ApplyToMaterial(Material mat)
	{
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)mat == (Object)null)
		{
			return;
		}
		Shader shader = mat.shader;
		if ((Object)(object)shader == (Object)null)
		{
			return;
		}
		string[] texturePropNames = GetTexturePropNames(shader);
		if (texturePropNames == null || texturePropNames.Length == 0)
		{
			return;
		}
		foreach (string text in texturePropNames)
		{
			Texture texture;
			try
			{
				texture = mat.GetTexture(text);
			}
			catch
			{
				continue;
			}
			if ((Object)(object)texture == (Object)null || !_ShouldReplaceThisTexture(((Object)texture).name, text, out var spec) || !_pngTextures.TryGetValue(spec.PngStem, out var value) || (Object)(object)value == (Object)null || texture == value)
			{
				continue;
			}
			mat.SetTexture(text, (Texture)(object)value);
			if (spec.Kind == SwapKind.BaseColor)
			{
				if (mat.HasProperty("_BaseColor"))
				{
					mat.SetColor("_BaseColor", Color.white);
				}
				if (mat.HasProperty("_Color"))
				{
					mat.SetColor("_Color", Color.white);
				}
			}
			else
			{
				if (mat.HasProperty("_EmissionColor"))
				{
					mat.SetColor("_EmissionColor", Color.white);
				}
				mat.EnableKeyword("_EMISSION");
			}
		}
	}

	private bool _ShouldReplaceThisTexture(string textureName, string propName, out SwapSpec spec)
	{
		spec = default(SwapSpec);
		if (string.IsNullOrEmpty(textureName))
		{
			return false;
		}
		if (_ourTextureNames.Contains(textureName))
		{
			return false;
		}
		if (_replacements.TryGetValue(textureName, out spec))
		{
			return true;
		}
		if (IsBaseColorProperty(propName) && textureName.IndexOf("heavy water", StringComparison.OrdinalIgnoreCase) >= 0)
		{
			return _replacements.TryGetValue("heavy water_DefaultMaterial_BaseColor", out spec);
		}
		return false;
	}

	private string[] GetTexturePropNames(Shader shader)
	{
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Invalid comparison between Unknown and I4
		int instanceID = ((Object)shader).GetInstanceID();
		if (_shaderTexturePropsCache.TryGetValue(instanceID, out var value))
		{
			return value;
		}
		int propertyCount;
		try
		{
			propertyCount = shader.GetPropertyCount();
		}
		catch
		{
			return Array.Empty<string>();
		}
		List<string> list = new List<string>(8);
		for (int i = 0; i < propertyCount; i++)
		{
			if ((int)shader.GetPropertyType(i) == 4)
			{
				string propertyName = shader.GetPropertyName(i);
				if (!string.IsNullOrEmpty(propertyName))
				{
					list.Add(propertyName);
				}
			}
		}
		string[] array = list.ToArray();
		_shaderTexturePropsCache[instanceID] = array;
		return array;
	}

	private static bool IsBaseColorProperty(string propName)
	{
		if (string.IsNullOrEmpty(propName))
		{
			return false;
		}
		string text = propName.ToLowerInvariant();
		int result;
		switch (text)
		{
		default:
			result = (text.Contains("basecolor") ? 1 : 0);
			break;
		case "_basecolormap":
		case "_maintex":
		case "_basemap":
			result = 1;
			break;
		}
		return (byte)result != 0;
	}

	private Texture2D LoadPngTexture(string pngStem)
	{
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Expected O, but got Unknown
		string path = Path.Combine(PngFolder, pngStem + ".png");
		if (!File.Exists(path))
		{
			return null;
		}
		byte[] data;
		try
		{
			data = File.ReadAllBytes(path);
		}
		catch
		{
			return null;
		}
		Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true, false)
		{
			name = pngStem
		};
		if (!LoadImageReflection(val, data, markNonReadable: false))
		{
			return null;
		}
		val.Apply(true, false);
		return val;
	}

	private bool LoadImageReflection(Texture2D target, byte[] data, bool markNonReadable)
	{
		Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule") ?? Type.GetType("UnityEngine.ImageConversion, UnityEngine");
		if (type == null)
		{
			return false;
		}
		MethodInfo method = type.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[3]
		{
			typeof(Texture2D),
			typeof(byte[]),
			typeof(bool)
		}, null);
		if (method == null)
		{
			return false;
		}
		object obj;
		try
		{
			obj = method.Invoke(null, new object[3] { target, data, markNonReadable });
		}
		catch
		{
			return false;
		}
		bool flag = default(bool);
		int num;
		if (obj is bool)
		{
			flag = (bool)obj;
			num = 1;
		}
		else
		{
			num = 0;
		}
		return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
	}
}