using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Rendering;
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("SwingTrail")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Geezt Jeez")]
[assembly: AssemblyProduct("SFT by FhpSlime")]
[assembly: AssemblyCopyright("Copyright © 2022")]
[assembly: AssemblyTrademark("SwingTrail")]
[assembly: ComVisible(false)]
[assembly: Guid("3a45c3cf-230c-4310-952f-0887d4266a22")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
namespace SkyboxChange;
[BepInPlugin("GeeztJeez.SkyboxChange", "SkyboxChange", "1.0.1")]
internal class Loader : BaseUnityPlugin
{
private class AnimatedSky
{
public string name;
public List<Texture2D> frames;
public List<float> delays;
public bool loop = true;
}
private static ConfigEntry<bool> configEnableMod;
public string skyboxFolderPath;
public AssetBundle assetBundle;
private List<Texture2D> skyboxTextures;
private List<AnimatedSky> animatedSkies;
private Dictionary<string, Cubemap> cubemapCache = new Dictionary<string, Cubemap>();
public static bool Enabled => configEnableMod.Value;
public Loader()
{
animatedSkies = new List<AnimatedSky>();
skyboxFolderPath = "Skybox";
skyboxTextures = new List<Texture2D>();
}
private void Awake()
{
((MonoBehaviour)this).StartCoroutine("Call");
}
private IEnumerator Call()
{
yield return (object)new WaitUntil((Func<bool>)(() => (Object)(object)Object.FindObjectOfType<ServiceLocator>() != (Object)null));
yield return (object)new WaitUntil((Func<bool>)(() => ServiceLocator.GetService<ISaveLoaderService>() != null));
Debug.Log((object)"Loading SkyboxChange.");
new Harmony("SkyboxChange").PatchAll();
LoadBundle("skychangebundle");
DoConfig();
Check();
LoadSkyboxTextures();
ChangeSkyboxRandom();
SceneManager.sceneLoaded += SceneLoaded;
((MonoBehaviour)this).StartCoroutine(GenerateSettings());
Debug.Log((object)"Loaded SkyboxChange Successfully!");
}
private IEnumerator GenerateSettings()
{
GlobalSettingsHandler service = null;
yield return (object)new WaitUntil((Func<bool>)(() => Object.op_Implicit((Object)(object)(service = ServiceLocator.GetService<GlobalSettingsHandler>()))));
List<SettingsInstance> list = service.GameplaySettings.ToList();
SettingsInstance val2 = new SettingsInstance();
val2.settingsType = (SettingsType)0;
val2.options = new string[2] { "On", "Off" };
val2.currentValue = ((!configEnableMod.Value) ? 1 : 0);
val2.m_settingsKey = "Use Skybox Change";
val2.toolTip = "Enables Skybox Change mod.";
SettingsInstance val3 = val2;
val3.OnValueChanged += delegate(int val)
{
configEnableMod.Value = val == 0;
};
list.Add(val3);
((object)service).GetType().GetField("m_gameplaySettings", (BindingFlags)(-1)).SetValue(service, list.ToArray());
}
private void DoConfig()
{
configEnableMod = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable Sky Change");
}
public void Check()
{
if (!Directory.Exists(skyboxFolderPath))
{
Directory.CreateDirectory(skyboxFolderPath);
}
}
public void ChangeSkyboxRandom()
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Expected O, but got Unknown
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Expected O, but got Unknown
if (skyboxTextures.Count <= 0)
{
RenderSettings.skybox = (Material)assetBundle.LoadAsset("SkyMat");
return;
}
int index = Random.Range(0, skyboxTextures.Count);
Material val = CreateSkyMaterial_WithCubemapFallback(index);
if ((Object)(object)val != (Object)null)
{
((MonoBehaviour)this).StartCoroutine(CrossfadeSkybox(val, 2f));
}
else
{
RenderSettings.skybox = (Material)assetBundle.LoadAsset("SkyMat");
}
}
public void SceneLoaded(Scene scene, LoadSceneMode loadSceneMode)
{
ChangeSkyboxRandom();
}
private void LoadBundle(string name)
{
Stream manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name);
if (manifestResourceStream == null)
{
Debug.LogError((object)("[LoadBundle] Failed to find resource: " + name));
}
else if (!manifestResourceStream.CanRead)
{
Debug.LogError((object)("[LoadBundle] Resource stream is not readable: " + name));
}
else
{
assetBundle = AssetBundle.LoadFromStream(manifestResourceStream);
}
}
public void LoadSkyboxTextures()
{
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Expected O, but got Unknown
if (!Directory.Exists(skyboxFolderPath))
{
Debug.LogWarning((object)("Skybox folder not found: " + skyboxFolderPath));
return;
}
string[] files = Directory.GetFiles(skyboxFolderPath);
foreach (string text in files)
{
if (!IsImageFile(text))
{
continue;
}
try
{
byte[] array = File.ReadAllBytes(text);
Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
if (!ImageConversion.LoadImage(val, array))
{
Debug.LogError((object)("Failed to LoadImage: " + text));
continue;
}
((Object)val).name = Path.GetFileNameWithoutExtension(text);
((Texture)val).wrapMode = (TextureWrapMode)1;
((Texture)val).filterMode = (FilterMode)1;
skyboxTextures.Add(val);
Debug.Log((object)("Loaded skybox texture: " + text));
}
catch (Exception ex)
{
Debug.LogError((object)("Error loading skybox file: " + text + " -> " + ex));
}
}
}
public bool IsImageFile(string filePath)
{
string text = Path.GetExtension(filePath).ToLower();
switch (text)
{
default:
return text == ".bmp";
case ".png":
case ".jpg":
case ".jpeg":
return true;
}
}
public Material CreateSkyMaterial(int index)
{
//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Expected O, but got Unknown
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Expected O, but got Unknown
//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
//IL_00f7: Expected O, but got Unknown
if (index < 0 || index >= skyboxTextures.Count)
{
Debug.LogError((object)"CreateSkyMaterial: index out of range");
return null;
}
Texture2D val = skyboxTextures[index];
if ((Object)(object)val == (Object)null)
{
Debug.LogError((object)"CreateSkyMaterial: texture is null");
return null;
}
Shader val2 = Shader.Find("Skybox/Panoramic");
if ((Object)(object)val2 != (Object)null)
{
Material val3 = new Material(val2);
string text = (val3.HasProperty("_MainTex") ? "_MainTex" : (val3.HasProperty("_Tex") ? "_Tex" : null));
if (text != null)
{
val3.SetTexture(text, (Texture)(object)val);
}
else
{
Debug.LogWarning((object)"Panoramic shader found but doesn't have _MainTex/_Tex property.");
}
if (val3.HasProperty("_Exposure"))
{
val3.SetFloat("_Exposure", 1f);
}
return val3;
}
Material val4 = (Material)assetBundle.LoadAsset("SkyMat");
if ((Object)(object)val4 == (Object)null)
{
Debug.LogError((object)"No SkyMat in asset bundle and Skybox/Panoramic not found.");
return null;
}
Material val5 = new Material(val4);
Shader shader = val5.shader;
string[] array = new string[3] { "_MainTex", "_Tex", "_BaseMap" };
foreach (string text2 in array)
{
if (val5.HasProperty(text2))
{
if (!ShaderHasTexturePropertyAndIsCube(shader, text2))
{
val5.SetTexture(text2, (Texture)(object)val);
Debug.Log((object)("Assigned 2D texture to template property '" + text2 + "'."));
return val5;
}
Debug.LogWarning((object)("Template shader property '" + text2 + "' expects a CUBE texture — skipping assignment."));
}
}
string text3 = FindFirstNonCubeTextureProperty(shader);
if (!string.IsNullOrEmpty(text3))
{
val5.SetTexture(text3, (Texture)(object)val);
Debug.Log((object)("Assigned 2D texture to template shader property '" + text3 + "' (first non-cube)."));
return val5;
}
Debug.LogWarning((object)"Template sky material expects only CUBE texture properties. Falling back to Panoramic shader attempt failed earlier; returning null.");
return null;
}
private Cubemap SetCubeMap(Texture2D texture)
{
//IL_0089: 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_0095: Expected O, but got Unknown
//IL_0010: 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_001c: Expected O, but got Unknown
if ((Object)(object)texture != (Object)null)
{
Cubemap val = new Cubemap(((Texture)texture).width, texture.format, false);
val.SetPixels(texture.GetPixels(), (CubemapFace)0);
val.SetPixels(texture.GetPixels(), (CubemapFace)1);
val.SetPixels(texture.GetPixels(), (CubemapFace)2);
val.SetPixels(texture.GetPixels(), (CubemapFace)3);
val.SetPixels(texture.GetPixels(), (CubemapFace)4);
val.SetPixels(texture.GetPixels(), (CubemapFace)5);
val.Apply();
RenderSettings.skybox.SetTexture("_Tex", (Texture)(object)val);
return val;
}
return new Cubemap(((Texture)texture).width, texture.format, false);
}
private IEnumerator CrossfadeSkybox(Material newMat, float duration)
{
if ((Object)(object)newMat == (Object)null)
{
Debug.LogError((object)"CrossfadeSkybox: newMat is null");
yield break;
}
Material oldMat = RenderSettings.skybox;
if ((Object)(object)oldMat == (Object)null)
{
RenderSettings.skybox = newMat;
yield break;
}
bool oldHasExposure = oldMat.HasProperty("_Exposure");
bool newHasExposure = newMat.HasProperty("_Exposure");
float t2 = 0f;
while (t2 < duration)
{
t2 += Time.deltaTime;
float num = Mathf.Clamp01(t2 / duration);
if (oldHasExposure)
{
oldMat.SetFloat("_Exposure", Mathf.Lerp(1f, 0f, num));
}
yield return null;
}
if (oldHasExposure)
{
oldMat.SetFloat("_Exposure", 0f);
}
RenderSettings.skybox = newMat;
if (newHasExposure)
{
newMat.SetFloat("_Exposure", 0f);
}
t2 = 0f;
while (t2 < duration)
{
t2 += Time.deltaTime;
float num2 = Mathf.Clamp01(t2 / duration);
if (newHasExposure)
{
newMat.SetFloat("_Exposure", Mathf.Lerp(0f, 1f, num2));
}
yield return null;
}
if (newHasExposure)
{
newMat.SetFloat("_Exposure", 1f);
}
}
private IEnumerator PlayAnimatedSky(Material mat, AnimatedSky animated, string textureProp = "_MainTex")
{
if (animated == null || animated.frames == null || animated.frames.Count == 0)
{
yield break;
}
int idx = 0;
while (true)
{
mat.SetTexture(textureProp, (Texture)(object)animated.frames[idx]);
float num = ((animated.delays != null && idx < animated.delays.Count) ? animated.delays[idx] : 0.1f);
yield return (object)new WaitForSeconds(num);
idx++;
if (idx >= animated.frames.Count)
{
if (!animated.loop)
{
break;
}
idx = 0;
}
}
}
private bool ShaderHasTexturePropertyAndIsCube(Shader shader, string propName)
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Invalid comparison between Unknown and I4
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Invalid comparison between Unknown and I4
if ((Object)(object)shader == (Object)null)
{
return false;
}
int propertyCount = shader.GetPropertyCount();
for (int i = 0; i < propertyCount; i++)
{
if (shader.GetPropertyName(i) == propName)
{
if ((int)shader.GetPropertyType(i) == 4)
{
return (int)shader.GetPropertyTextureDimension(i) == 4;
}
return false;
}
}
return false;
}
private string FindFirstNonCubeTextureProperty(Shader shader)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Invalid comparison between Unknown and I4
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Invalid comparison between Unknown and I4
if ((Object)(object)shader == (Object)null)
{
return null;
}
int propertyCount = shader.GetPropertyCount();
for (int i = 0; i < propertyCount; i++)
{
if ((int)shader.GetPropertyType(i) == 4 && (int)shader.GetPropertyTextureDimension(i) != 4)
{
return shader.GetPropertyName(i);
}
}
return null;
}
public Cubemap ConvertEquirectangularToCubemap(Texture2D eqTex, int cubemapSize = 512)
{
//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Expected O, but got Unknown
//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
//IL_00eb: Expected O, but got Unknown
//IL_012f: Unknown result type (might be due to invalid IL or missing references)
//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
//IL_01ff: Expected O, but got Unknown
//IL_0203: Unknown result type (might be due to invalid IL or missing references)
//IL_020a: Expected O, but got Unknown
//IL_0228: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)eqTex == (Object)null)
{
return null;
}
if (cubemapCache.TryGetValue(((Object)eqTex).name, out var value))
{
return value;
}
Shader val = null;
if ((Object)(object)assetBundle != (Object)null)
{
try
{
val = assetBundle.LoadAsset<Shader>("Hidden/EquirectangularToCubemap");
if ((Object)(object)val == (Object)null)
{
Shader[] array = assetBundle.LoadAllAssets<Shader>();
foreach (Shader val2 in array)
{
Debug.Log((object)("[SkyboxChange] Bundle shader: '" + ((Object)val2).name + "'"));
}
}
}
catch (Exception ex)
{
Debug.LogWarning((object)("[SkyboxChange] assetBundle.LoadAsset<Shader> threw: " + ex.Message));
}
}
if ((Object)(object)val == (Object)null)
{
val = FindConversionShaderFromBundleOrFallback();
}
if ((Object)(object)val == (Object)null)
{
Debug.LogError((object)"[SkyboxChange] Conversion shader 'Hidden/EquirectangularToCubemap' not found. Make sure it's included in your build/asset bundle or added to Always Included Shaders.");
return null;
}
Material val3 = new Material(val);
val3.SetTexture("_MainTex", (Texture)(object)eqTex);
RenderTexture val4 = new RenderTexture(cubemapSize, cubemapSize, 0);
((Texture)val4).dimension = (TextureDimension)4;
((Object)val4).hideFlags = (HideFlags)52;
val4.useMipMap = false;
val4.autoGenerateMips = false;
val4.Create();
for (int j = 0; j < 6; j++)
{
val3.SetInt("_FaceIndex", j);
Graphics.SetRenderTarget(val4, 0, (CubemapFace)j);
GL.Clear(true, true, Color.black);
GL.PushMatrix();
GL.LoadOrtho();
val3.SetPass(0);
GL.Begin(7);
GL.TexCoord2(0f, 0f);
GL.Vertex3(0f, 0f, 0f);
GL.TexCoord2(1f, 0f);
GL.Vertex3(1f, 0f, 0f);
GL.TexCoord2(1f, 1f);
GL.Vertex3(1f, 1f, 0f);
GL.TexCoord2(0f, 1f);
GL.Vertex3(0f, 1f, 0f);
GL.End();
GL.PopMatrix();
}
Cubemap val5 = new Cubemap(cubemapSize, (TextureFormat)4, false);
Texture2D val6 = new Texture2D(cubemapSize, cubemapSize, (TextureFormat)4, false);
for (int k = 0; k < 6; k++)
{
Graphics.SetRenderTarget(val4, 0, (CubemapFace)k);
val6.ReadPixels(new Rect(0f, 0f, (float)cubemapSize, (float)cubemapSize), 0, 0);
val6.Apply();
val5.SetPixels(val6.GetPixels(), (CubemapFace)k);
}
val5.Apply();
Object.DestroyImmediate((Object)(object)val6);
val4.Release();
Object.DestroyImmediate((Object)(object)val4);
Object.DestroyImmediate((Object)(object)val3);
((Object)val5).name = ((Object)eqTex).name + "_cubemap";
cubemapCache[((Object)eqTex).name] = val5;
Debug.Log((object)$"[SkyboxChange] Converted '{((Object)eqTex).name}' -> Cubemap ({cubemapSize}x{cubemapSize})");
return val5;
}
public Material CreateSkyMaterial_WithCubemapFallback(int index)
{
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Expected O, but got Unknown
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Expected O, but got Unknown
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
//IL_00c9: Invalid comparison between Unknown and I4
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Invalid comparison between Unknown and I4
if (index < 0 || index >= skyboxTextures.Count)
{
return null;
}
Texture2D val = skyboxTextures[index];
if ((Object)(object)val == (Object)null)
{
return null;
}
Material val2 = (Material)assetBundle.LoadAsset("SkyMat");
if ((Object)(object)val2 == (Object)null)
{
return null;
}
Material val3 = new Material(val2);
Shader shader = val3.shader;
string[] array = new string[4] { "_Tex", "_TexCube", "_Cube", "_MainTex" };
foreach (string text in array)
{
if (!val3.HasProperty(text))
{
continue;
}
int propertyCount = shader.GetPropertyCount();
bool flag = false;
for (int j = 0; j < propertyCount; j++)
{
if (shader.GetPropertyName(j) == text && (int)shader.GetPropertyType(j) == 4 && (int)shader.GetPropertyTextureDimension(j) == 4)
{
flag = true;
break;
}
}
if (!flag)
{
val3.SetTexture(text, (Texture)(object)val);
return val3;
}
int cubemapSize = Mathf.ClosestPowerOfTwo(Mathf.Clamp(((Texture)val).width, 128, 1024));
Cubemap val4 = ConvertEquirectangularToCubemap(val, cubemapSize);
if ((Object)(object)val4 != (Object)null)
{
val3.SetTexture(text, (Texture)(object)val4);
Debug.Log((object)("[SkyboxChange] Assigned generated cubemap to property '" + text + "'."));
return val3;
}
Debug.LogWarning((object)"[SkyboxChange] Conversion failed; cannot assign cube.");
return null;
}
Debug.LogWarning((object)"[SkyboxChange] Template had no usable texture property.");
return null;
}
private Shader FindConversionShaderFromBundleOrFallback()
{
Shader val = null;
if ((Object)(object)assetBundle != (Object)null)
{
try
{
string[] allAssetNames = assetBundle.GetAllAssetNames();
Debug.Log((object)$"[SkyboxChange] assetBundle has {allAssetNames.Length} assets:");
for (int i = 0; i < allAssetNames.Length; i++)
{
Debug.Log((object)$"[SkyboxChange] asset[{i}] = '{allAssetNames[i]}'");
}
string[] array = new string[4] { "Hidden/EquirectangularToCubemap", "EquirectangularToCubemap", "Assets/Shaders/EquirectangularToCubemap.shader", "Shaders/EquirectangularToCubemap" };
foreach (string text in array)
{
try
{
val = assetBundle.LoadAsset<Shader>(text);
Debug.Log((object)("[SkyboxChange] LoadAsset<Shader>(\"" + text + "\") -> " + (((Object)(object)val != (Object)null) ? "FOUND" : "null")));
}
catch (Exception ex)
{
Debug.LogWarning((object)("[SkyboxChange] LoadAsset<Shader>(\"" + text + "\") threw: " + ex.Message));
}
if ((Object)(object)val != (Object)null)
{
break;
}
}
if ((Object)(object)val == (Object)null)
{
Shader[] array2 = assetBundle.LoadAllAssets<Shader>();
Debug.Log((object)$"[SkyboxChange] assetBundle.LoadAllAssets<Shader>() returned {array2.Length} shaders.");
for (int k = 0; k < array2.Length; k++)
{
Shader val2 = array2[k];
Debug.Log((object)$"[SkyboxChange] bundle shader[{k}] asset-name='{((Object)val2).name}' (internal shader name).");
if (((Object)val2).name == "Hidden/EquirectangularToCubemap" || ((Object)val2).name == "EquirectangularToCubemap" || ((Object)val2).name.Contains("Equirect"))
{
val = val2;
Debug.Log((object)("[SkyboxChange] Matched shader by name: '" + ((Object)val2).name + "'"));
break;
}
}
}
}
catch (Exception ex2)
{
Debug.LogWarning((object)("[SkyboxChange] Error while enumerating assetBundle: " + ex2));
}
}
else
{
Debug.LogWarning((object)"[SkyboxChange] assetBundle is null when searching for conversion shader.");
}
if ((Object)(object)val == (Object)null)
{
val = Shader.Find("Hidden/EquirectangularToCubemap");
Debug.Log((object)("[SkyboxChange] Shader.Find('Hidden/EquirectangularToCubemap') -> " + (((Object)(object)val != (Object)null) ? "FOUND" : "null")));
}
if ((Object)(object)val == (Object)null)
{
string[] array = new string[3] { "EquirectangularToCubemap", "Equirectangular", "CubemapConversion" };
foreach (string text2 in array)
{
val = Shader.Find(text2);
if ((Object)(object)val != (Object)null)
{
Debug.Log((object)("[SkyboxChange] Shader.Find('" + text2 + "') matched shader: " + ((Object)val).name));
break;
}
}
}
if ((Object)(object)val == (Object)null)
{
Debug.LogError((object)"[SkyboxChange] Conversion shader not found by any method. Check your asset bundle contents and the shader's internal name (top line of the .shader file).");
}
return val;
}
}