using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
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: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Omniscye")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Snow")]
[assembly: AssemblyTitle("Snow")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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]
[Microsoft.CodeAnalysis.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]
[Microsoft.CodeAnalysis.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 Omniscye.SnowEverywhere
{
[BepInPlugin("Omniscye.SnowEverywhere", "SnowEverywhere", "1.4.1")]
public class SnowEverywhere : BaseUnityPlugin
{
private sealed class SnowController : MonoBehaviour
{
internal struct Settings
{
public bool Enabled;
public float FlakesPerSecond;
public float FallSpeed;
public float FlakeSize;
public float WindX;
public float WindZ;
public float SpawnBoxHalfExtent;
public int MaxParticles;
public bool StickToCamera;
public bool UseUnscaledTime;
}
private ParticleSystem _ps = null;
private EmissionModule _emission;
private MainModule _main;
private ShapeModule _shape;
private VelocityOverLifetimeModule _vel;
private ParticleSystemRenderer _rend = null;
private Camera? _cam;
private Settings _settings;
private float _targetLifetime;
private bool _manualSimulateFallback = false;
public void Initialize(Settings s, Texture2D? customTexture)
{
_settings = s;
BuildParticleSystem(customTexture);
RefreshForScene();
if (s.Enabled)
{
Enable();
}
else
{
Disable();
}
}
public void RefreshForScene()
{
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
_cam = Camera.main;
if ((Object)(object)_cam == (Object)null)
{
Camera[] array = Object.FindObjectsOfType<Camera>();
Camera[] array2 = array;
foreach (Camera val in array2)
{
if ((Object)(object)val != (Object)null && ((Behaviour)val).enabled)
{
_cam = val;
break;
}
}
}
if (_settings.StickToCamera && (Object)(object)_cam != (Object)null)
{
Vector3 position = ((Component)_cam).transform.position;
position.y += 15f;
((Component)this).transform.position = position;
}
}
private void LateUpdate()
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
if (_settings.StickToCamera && (Object)(object)_cam != (Object)null)
{
Vector3 position = ((Component)_cam).transform.position;
position.y += 15f;
((Component)this).transform.position = position;
}
if (!_settings.Enabled || (Object)(object)_ps == (Object)null)
{
return;
}
if (_manualSimulateFallback)
{
float num = (_settings.UseUnscaledTime ? Time.unscaledDeltaTime : Time.deltaTime);
if (_ps.isPlaying)
{
_ps.Pause(false);
}
_ps.Simulate(num, false, false, false);
}
else if (_ps.isStopped || _ps.isPaused)
{
_ps.Play();
}
}
private void BuildParticleSystem(Texture2D? customTexture)
{
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Expected O, but got Unknown
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0131: Unknown result type (might be due to invalid IL or missing references)
//IL_0136: Unknown result type (might be due to invalid IL or missing references)
//IL_014e: Unknown result type (might be due to invalid IL or missing references)
//IL_0153: Unknown result type (might be due to invalid IL or missing references)
//IL_016f: Unknown result type (might be due to invalid IL or missing references)
//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
//IL_01c7: 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_0202: Unknown result type (might be due to invalid IL or missing references)
//IL_0225: Unknown result type (might be due to invalid IL or missing references)
//IL_0237: Unknown result type (might be due to invalid IL or missing references)
//IL_023c: Unknown result type (might be due to invalid IL or missing references)
//IL_0288: Unknown result type (might be due to invalid IL or missing references)
//IL_0299: Unknown result type (might be due to invalid IL or missing references)
//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0319: Unknown result type (might be due to invalid IL or missing references)
_ps = ((Component)this).gameObject.AddComponent<ParticleSystem>();
_rend = ((Component)_ps).GetComponent<ParticleSystemRenderer>();
_rend.alignment = (ParticleSystemRenderSpace)0;
_rend.renderMode = (ParticleSystemRenderMode)0;
Shader val = Shader.Find("Particles/Standard Unlit");
if ((Object)(object)val == (Object)null)
{
val = Shader.Find("Legacy Shaders/Particles/Alpha Blended");
}
Material val2 = new Material(val);
((Object)val2).name = "Snow_Menu_Material";
val2.color = Color.white;
if ((Object)(object)customTexture != (Object)null)
{
val2.mainTexture = (Texture)(object)customTexture;
}
val2.SetFloat("_Mode", 2f);
val2.EnableKeyword("_ALPHABLEND_ON");
val2.DisableKeyword("_ALPHATEST_ON");
val2.DisableKeyword("_ALPHAPREMULTIPLY_ON");
val2.SetInt("_ZWrite", 0);
val2.SetInt("_SrcBlend", 5);
val2.SetInt("_DstBlend", 10);
val2.renderQueue = 3000;
((Renderer)_rend).material = val2;
((Renderer)_rend).sortingOrder = 32767;
TrySetAlwaysSimulate(_ps, _rend);
_main = _ps.main;
((MainModule)(ref _main)).loop = true;
((MainModule)(ref _main)).startColor = MinMaxGradient.op_Implicit(Color.white);
((MainModule)(ref _main)).startSize = MinMaxCurve.op_Implicit(_settings.FlakeSize);
_targetLifetime = Mathf.Max(6f, 25f / Mathf.Max(0.05f, _settings.FallSpeed));
((MainModule)(ref _main)).startLifetime = MinMaxCurve.op_Implicit(_targetLifetime);
((MainModule)(ref _main)).startSpeed = MinMaxCurve.op_Implicit(0f);
((MainModule)(ref _main)).maxParticles = _settings.MaxParticles;
((MainModule)(ref _main)).simulationSpace = (ParticleSystemSimulationSpace)1;
_emission = _ps.emission;
((EmissionModule)(ref _emission)).enabled = true;
((EmissionModule)(ref _emission)).rateOverTime = MinMaxCurve.op_Implicit(_settings.FlakesPerSecond);
_shape = _ps.shape;
((ShapeModule)(ref _shape)).enabled = true;
((ShapeModule)(ref _shape)).shapeType = (ParticleSystemShapeType)5;
((ShapeModule)(ref _shape)).scale = new Vector3(_settings.SpawnBoxHalfExtent * 2f, 2f, _settings.SpawnBoxHalfExtent * 2f);
((ShapeModule)(ref _shape)).position = Vector3.zero;
_vel = _ps.velocityOverLifetime;
((VelocityOverLifetimeModule)(ref _vel)).enabled = true;
((VelocityOverLifetimeModule)(ref _vel)).space = (ParticleSystemSimulationSpace)1;
((VelocityOverLifetimeModule)(ref _vel)).x = MinMaxCurve.op_Implicit(_settings.WindX);
((VelocityOverLifetimeModule)(ref _vel)).y = MinMaxCurve.op_Implicit(0f - _settings.FallSpeed);
((VelocityOverLifetimeModule)(ref _vel)).z = MinMaxCurve.op_Implicit(_settings.WindZ);
_ps.Play();
}
private void TrySetAlwaysSimulate(ParticleSystem ps, ParticleSystemRenderer rend)
{
if ((Object)(object)rend != (Object)null)
{
((Renderer)rend).allowOcclusionWhenDynamic = false;
}
PropertyInfo property = typeof(ParticleSystem).GetProperty("cullingMode", BindingFlags.Instance | BindingFlags.Public);
if (property != null)
{
Type propertyType = property.PropertyType;
object value;
try
{
value = Enum.Parse(propertyType, "AlwaysSimulate");
}
catch
{
value = Enum.ToObject(propertyType, 2);
}
try
{
property.SetValue(ps, value, null);
_manualSimulateFallback = false;
return;
}
catch
{
}
}
_manualSimulateFallback = true;
}
public void Enable()
{
_settings.Enabled = true;
if ((Object)(object)_ps == (Object)null)
{
return;
}
if (_manualSimulateFallback)
{
if (_ps.isPlaying)
{
_ps.Pause(false);
}
}
else
{
_ps.Play();
}
}
public void Disable()
{
_settings.Enabled = false;
if (!((Object)(object)_ps == (Object)null))
{
_ps.Pause();
}
}
public void SetEmissionRate(float r)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
_settings.FlakesPerSecond = Mathf.Max(0f, r);
((EmissionModule)(ref _emission)).rateOverTime = MinMaxCurve.op_Implicit(_settings.FlakesPerSecond);
RecalculateRecommendedMaxParticles();
}
public void SetFallSpeed(float s)
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
_settings.FallSpeed = Mathf.Max(0.01f, s);
((VelocityOverLifetimeModule)(ref _vel)).y = MinMaxCurve.op_Implicit(0f - _settings.FallSpeed);
_targetLifetime = Mathf.Max(6f, 25f / _settings.FallSpeed);
((MainModule)(ref _main)).startLifetime = MinMaxCurve.op_Implicit(_targetLifetime);
RecalculateRecommendedMaxParticles();
}
public void SetFlakeSize(float s)
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
_settings.FlakeSize = Mathf.Clamp(s, 0.005f, 0.25f);
((MainModule)(ref _main)).startSize = MinMaxCurve.op_Implicit(_settings.FlakeSize);
}
public void SetWind(float x, float z)
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
_settings.WindX = x;
_settings.WindZ = z;
((VelocityOverLifetimeModule)(ref _vel)).x = MinMaxCurve.op_Implicit(x);
((VelocityOverLifetimeModule)(ref _vel)).z = MinMaxCurve.op_Implicit(z);
}
public void SetSpawnBox(float halfExtent)
{
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
_settings.SpawnBoxHalfExtent = Mathf.Clamp(halfExtent, 5f, 200f);
((ShapeModule)(ref _shape)).scale = new Vector3(_settings.SpawnBoxHalfExtent * 2f, 2f, _settings.SpawnBoxHalfExtent * 2f);
}
public void SetMaxParticles(int max)
{
_settings.MaxParticles = Mathf.Clamp(max, 200, 50000);
((MainModule)(ref _main)).maxParticles = _settings.MaxParticles;
}
public void SetStickToCamera(bool stick)
{
_settings.StickToCamera = stick;
}
public void SetUseUnscaledTime(bool useUnscaled)
{
_settings.UseUnscaledTime = useUnscaled;
}
private void RecalculateRecommendedMaxParticles()
{
int num = Mathf.CeilToInt(_settings.FlakesPerSecond * _targetLifetime * 1.2f);
if (num > _settings.MaxParticles)
{
_settings.MaxParticles = num;
((MainModule)(ref _main)).maxParticles = _settings.MaxParticles;
}
}
}
public const string PluginGuid = "Omniscye.SnowEverywhere";
public const string PluginName = "SnowEverywhere";
public const string PluginVersion = "1.4.1";
private ConfigEntry<bool> _enabled = null;
private ConfigEntry<float> _flakesPerSecond = null;
private ConfigEntry<float> _fallSpeed = null;
private ConfigEntry<float> _flakeSize = null;
private ConfigEntry<float> _windX = null;
private ConfigEntry<float> _windZ = null;
private ConfigEntry<float> _spawnBoxHalfExtent = null;
private ConfigEntry<int> _maxParticles = null;
private ConfigEntry<bool> _stickToCamera = null;
private ConfigEntry<bool> _useUnscaledTime = null;
private ConfigEntry<bool> _onlyInMenuLobby = null;
private ConfigEntry<bool> _useCustomTexture = null;
private ConfigEntry<string> _customTextureName = null;
private SnowController? _controller;
private float _filterPollTimer;
private bool _lastAllowed;
private bool _loggedSemiFuncNotReady;
private Texture2D? _snowTex;
internal static SnowEverywhere Instance { get; private set; }
internal static ManualLogSource Logger => Instance._logger;
private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;
internal Harmony? Harmony { get; set; }
private void Awake()
{
//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_0045: Expected O, but got Unknown
//IL_004a: Expected O, but got Unknown
Instance = this;
((Component)this).transform.parent = null;
((Object)this).hideFlags = (HideFlags)61;
BindConfig();
if (Harmony == null)
{
Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
Harmony val2 = val;
Harmony = val;
}
Harmony.PatchAll();
TryLoadSnowTexture();
EnsureController();
SceneManager.sceneLoaded += OnSceneLoaded;
ApplyMenuFilter(initial: true);
Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} loaded — menu/lobby-gated snowfall with custom texture support.");
}
private void OnDestroy()
{
SceneManager.sceneLoaded -= OnSceneLoaded;
Harmony? harmony = Harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
private void Update()
{
_filterPollTimer -= (_useUnscaledTime.Value ? Time.unscaledDeltaTime : Time.deltaTime);
if (_filterPollTimer <= 0f)
{
_filterPollTimer = 0.5f;
ApplyMenuFilter(initial: false);
}
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
if ((Object)(object)_controller == (Object)null)
{
EnsureController();
}
_controller.RefreshForScene();
ApplyMenuFilter(initial: true);
Logger.LogDebug((object)("Snow refreshed for scene '" + ((Scene)(ref scene)).name + "'."));
}
private void BindConfig()
{
_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master toggle for snowfall.");
_flakesPerSecond = ((BaseUnityPlugin)this).Config.Bind<float>("Snow", "FlakesPerSecond", 150f, "Emission rate (flakes/second).");
_fallSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Snow", "FallSpeed", 0.8f, "Downward speed in m/s. Lower = slower.");
_flakeSize = ((BaseUnityPlugin)this).Config.Bind<float>("Snow", "FlakeSize", 0.06f, "Base particle size in meters.");
_windX = ((BaseUnityPlugin)this).Config.Bind<float>("Snow", "WindX", 0.15f, "Horizontal drift X.");
_windZ = ((BaseUnityPlugin)this).Config.Bind<float>("Snow", "WindZ", -0.05f, "Horizontal drift Z.");
_spawnBoxHalfExtent = ((BaseUnityPlugin)this).Config.Bind<float>("Snow", "SpawnBoxHalfExtent", 25f, "Half-extent of spawn box (XZ).");
_maxParticles = ((BaseUnityPlugin)this).Config.Bind<int>("Performance", "MaxParticles", 8000, "Max live particles (raise if rate×lifetime is high).");
_stickToCamera = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "StickToCamera", true, "Anchor emitter to active camera.");
_useUnscaledTime = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "UseUnscaledTime", true, "Use unscaled time so menus/slowmo don’t freeze snow.");
_onlyInMenuLobby = ((BaseUnityPlugin)this).Config.Bind<bool>("Scenes", "OnlyInMenuLobby", true, "If true, snow runs only when SemiFunc.MenuLevel() is true.");
_useCustomTexture = ((BaseUnityPlugin)this).Config.Bind<bool>("Visual", "UseCustomTexture", true, "If true, tries to load a PNG beside the DLL and use it for flake texture.");
_customTextureName = ((BaseUnityPlugin)this).Config.Bind<string>("Visual", "CustomTextureName", "snow.png", "File name of the texture next to the plugin DLL.");
}
private void EnsureController()
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Expected O, but got Unknown
if (!((Object)(object)_controller != (Object)null))
{
GameObject val = new GameObject("SnowEverywhere_Controller");
Object.DontDestroyOnLoad((Object)(object)val);
((Object)val).hideFlags = (HideFlags)61;
_controller = val.AddComponent<SnowController>();
_controller.Initialize(new SnowController.Settings
{
Enabled = _enabled.Value,
FlakesPerSecond = _flakesPerSecond.Value,
FallSpeed = _fallSpeed.Value,
FlakeSize = _flakeSize.Value,
WindX = _windX.Value,
WindZ = _windZ.Value,
SpawnBoxHalfExtent = _spawnBoxHalfExtent.Value,
MaxParticles = _maxParticles.Value,
StickToCamera = _stickToCamera.Value,
UseUnscaledTime = _useUnscaledTime.Value
}, _snowTex);
_enabled.SettingChanged += delegate
{
ApplyMenuFilter(initial: false);
};
_flakesPerSecond.SettingChanged += delegate
{
_controller.SetEmissionRate(_flakesPerSecond.Value);
};
_fallSpeed.SettingChanged += delegate
{
_controller.SetFallSpeed(_fallSpeed.Value);
};
_flakeSize.SettingChanged += delegate
{
_controller.SetFlakeSize(_flakeSize.Value);
};
_windX.SettingChanged += delegate
{
_controller.SetWind(_windX.Value, _windZ.Value);
};
_windZ.SettingChanged += delegate
{
_controller.SetWind(_windX.Value, _windZ.Value);
};
_spawnBoxHalfExtent.SettingChanged += delegate
{
_controller.SetSpawnBox(_spawnBoxHalfExtent.Value);
};
_maxParticles.SettingChanged += delegate
{
_controller.SetMaxParticles(_maxParticles.Value);
};
_stickToCamera.SettingChanged += delegate
{
_controller.SetStickToCamera(_stickToCamera.Value);
};
_useUnscaledTime.SettingChanged += delegate
{
_controller.SetUseUnscaledTime(_useUnscaledTime.Value);
};
}
}
private void ApplyMenuFilter(bool initial)
{
if ((Object)(object)_controller == (Object)null)
{
return;
}
if (!_enabled.Value)
{
_controller.Disable();
return;
}
bool flag = true;
if (_onlyInMenuLobby.Value)
{
flag = IsMenuOrLobbyActiveSafe();
}
if (initial || flag != _lastAllowed)
{
_lastAllowed = flag;
if (flag)
{
_controller.Enable();
Logger.LogDebug((object)"Snow: ENABLE (menu level detected).");
}
else
{
_controller.Disable();
Logger.LogDebug((object)"Snow: DISABLE (not a menu level).");
}
}
}
private bool IsMenuOrLobbyActiveSafe()
{
try
{
return SemiFunc.MenuLevel();
}
catch (Exception ex)
{
if (!_loggedSemiFuncNotReady)
{
_loggedSemiFuncNotReady = true;
Logger.LogDebug((object)("Snow: SemiFunc.MenuLevel() not ready yet (" + ex.GetType().Name + "). Will retry."));
}
return false;
}
}
private void TryLoadSnowTexture()
{
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Expected O, but got Unknown
_snowTex = null;
if (!_useCustomTexture.Value)
{
return;
}
try
{
string path = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? "";
string text = Path.Combine(path, _customTextureName.Value);
if (!File.Exists(text))
{
Logger.LogDebug((object)("Snow: custom texture not found at '" + text + "'. Using default white material."));
return;
}
byte[] array = File.ReadAllBytes(text);
Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false, false);
if (!ImageConversion.LoadImage(val, array, false))
{
Logger.LogWarning((object)"Snow: failed to load snow texture (LoadImage returned false).");
Object.Destroy((Object)(object)val);
return;
}
((Object)val).name = "Snow_Menu_Texture";
((Texture)val).wrapMode = (TextureWrapMode)1;
((Texture)val).filterMode = (FilterMode)1;
_snowTex = val;
Logger.LogInfo((object)$"Snow: loaded custom flake texture '{_customTextureName.Value}' ({((Texture)val).width}x{((Texture)val).height}).");
}
catch (Exception ex)
{
Logger.LogWarning((object)("Snow: error loading custom texture: " + ex.GetType().Name + ": " + ex.Message));
_snowTex = null;
}
}
}
}