Decompiled source of RealTime v1.3.3

plugins/RealTime.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
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.Networking;
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("RealTime")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.3.1.0")]
[assembly: AssemblyInformationalVersion("1.3.1+2c0ef0da08b36bca9e9a2dc8dfc18eb4ee52bd61")]
[assembly: AssemblyProduct("Puts the game's time into YOUR system's time.")]
[assembly: AssemblyTitle("RealTime")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.3.1.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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RealTime
{
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "RealTime";

		public const string PLUGIN_NAME = "Puts the game's time into YOUR system's time.";

		public const string PLUGIN_VERSION = "1.3.1";
	}
}
namespace Realtime
{
	[BepInPlugin("com.laymxd.realtime", "RealTime", "1.3.0")]
	public class Plugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private sealed class <DelayedSetup>d__17 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public Plugin <>4__this;

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

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

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

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

			private bool MoveNext()
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(2f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>4__this.HookDayNight();
					return false;
				}
			}

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

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

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

			private object <>2__current;

			public Plugin <>4__this;

			private string <url>5__1;

			private UnityWebRequest <request>5__2;

			private string <json>5__3;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<url>5__1 = null;
				<request>5__2 = null;
				<json>5__3 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d6: Invalid comparison between Unknown and I4
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					Log.LogInfo((object)"Weather request started");
					<url>5__1 = $"https://api.open-meteo.com/v1/forecast?latitude={<>4__this.latitude.Value}&longitude={<>4__this.longitude.Value}&current_weather=true&timezone=auto";
					Log.LogInfo((object)("Weather URL: " + <url>5__1));
					<request>5__2 = UnityWebRequest.Get(<url>5__1);
					<>2__current = <request>5__2.SendWebRequest();
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					Log.LogInfo((object)"Weather request finished");
					if ((int)<request>5__2.result != 1)
					{
						Log.LogWarning((object)("Weather request failed: " + <request>5__2.error));
						return false;
					}
					<json>5__3 = <request>5__2.downloadHandler.text;
					Log.LogInfo((object)("Weather JSON: " + <json>5__3));
					<>4__this.ParseWeather(<json>5__3);
					return false;
				}
			}

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

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

		internal static ManualLogSource Log;

		private sDayNightCycle cycle;

		private sWeatherSystem weatherSystem;

		public static float realTemp = 10f;

		private ConfigEntry<bool> enableRealtime;

		private ConfigEntry<float> dayDuration;

		private ConfigEntry<float> syncInterval;

		private ConfigEntry<bool> enableRealWeather;

		private ConfigEntry<float> latitude;

		private ConfigEntry<float> longitude;

		private ConfigEntry<float> weatherUpdateMinutes;

		private ConfigEntry<float> tempRange;

		private float timer;

		private float weatherTimer;

		private CoroutineRunner runner;

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Harmony val = new Harmony("com.laymxd.realtime");
			val.PatchAll();
			Log.LogInfo((object)"RealTime loaded with Harmony");
			enableRealtime = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableRealtimeSync", true, "Sync the game day/night cycle with real system time");
			dayDuration = ((BaseUnityPlugin)this).Config.Bind<float>("General", "DayDurationSeconds", 86400f, "How long a full day lasts in seconds (86400 = real 24 hours)");
			syncInterval = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SyncInterval", 1f, "How often (in seconds) the game time updates");
			enableRealWeather = ((BaseUnityPlugin)this).Config.Bind<bool>("Weather", "EnableRealWeather", false, "Sync in-game weather with real world weather");
			latitude = ((BaseUnityPlugin)this).Config.Bind<float>("Weather", "Latitude", 51.5072f, "Latitude for weather lookup");
			longitude = ((BaseUnityPlugin)this).Config.Bind<float>("Weather", "Longitude", -0.1276f, "Longitude for weather lookup");
			weatherUpdateMinutes = ((BaseUnityPlugin)this).Config.Bind<float>("Weather", "WeatherUpdateMinutes", 30f, "How often to refresh weather");
			tempRange = ((BaseUnityPlugin)this).Config.Bind<float>("Weather", "TemperatureRange", 2f, "How much temperature varies around the real value");
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			Log.LogInfo((object)("Scene loaded: " + ((Scene)(ref scene)).name));
			string[] array = new string[4] { "TitleScreen", "Credits", "Ending", "TrainIntro" };
			if (Array.IndexOf(array, ((Scene)(ref scene)).name) == -1)
			{
				if ((Object)(object)runner == (Object)null)
				{
					GameObject val = new GameObject("RealTimeRunner");
					Object.DontDestroyOnLoad((Object)(object)val);
					runner = val.AddComponent<CoroutineRunner>();
				}
				((MonoBehaviour)runner).StartCoroutine(DelayedSetup());
			}
		}

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

		private void HookDayNight()
		{
			cycle = Object.FindObjectOfType<sDayNightCycle>();
			if ((Object)(object)cycle != (Object)null)
			{
				cycle.dayDuration = dayDuration.Value;
				SyncTime();
				if (enableRealWeather.Value)
				{
					cycle.randomWeather = false;
					if ((Object)(object)runner != (Object)null)
					{
						((MonoBehaviour)runner).StartCoroutine(GetWeather());
					}
					Log.LogInfo((object)"Getting weather.");
				}
				Log.LogInfo((object)$"DayNight synced to real time: {cycle.time}");
			}
			else
			{
				Log.LogWarning((object)"DayNightCycle not found");
			}
		}

		private void SyncTime()
		{
			double totalSeconds = DateTime.Now.TimeOfDay.TotalSeconds;
			cycle.time = (float)(totalSeconds / (double)dayDuration.Value);
		}

		private void Update()
		{
			if (!enableRealtime.Value || (Object)(object)cycle == (Object)null)
			{
				return;
			}
			timer += Time.deltaTime;
			if (timer >= syncInterval.Value)
			{
				timer = 0f;
				SyncTime();
			}
			if (!enableRealWeather.Value)
			{
				return;
			}
			weatherTimer += Time.deltaTime;
			if (weatherTimer >= weatherUpdateMinutes.Value * 60f)
			{
				weatherTimer = 0f;
				if ((Object)(object)runner != (Object)null)
				{
					((MonoBehaviour)runner).StartCoroutine(GetWeather());
				}
			}
		}

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

		private void ParseWeather(string json)
		{
			Log.LogInfo((object)"Parsing weather...");
			int num = json.IndexOf("\"current_weather\":");
			if (num == -1)
			{
				Log.LogWarning((object)"current_weather block not found");
				return;
			}
			num = json.IndexOf("{", num);
			int num2 = json.IndexOf("}", num);
			string text = json.Substring(num, num2 - num + 1);
			CurrentWeather currentWeather = JsonUtility.FromJson<CurrentWeather>(text);
			if (currentWeather == null)
			{
				Log.LogWarning((object)"Weather parse failed");
				return;
			}
			int weathercode = currentWeather.weathercode;
			realTemp = currentWeather.temperature;
			Log.LogInfo((object)$"Real weather code: {weathercode}");
			Log.LogInfo((object)$"Real temperature: {realTemp}C");
			ApplyWeather(weathercode, realTemp);
		}

		private void ApplyWeather(int code, float realTemp)
		{
			weatherSystem = ((Component)cycle).GetComponent<sWeatherSystem>();
			cycle.lowTemp = Mathf.Lerp(cycle.lowTemp, realTemp - tempRange.Value, 0.3f);
			cycle.highTemp = Mathf.Lerp(cycle.highTemp, realTemp + tempRange.Value, 0.3f);
			float num = 0.005f;
			if (code == 0)
			{
				Log.LogInfo((object)"Clear sky");
				weatherSystem.intensity = 0f;
				weatherSystem.density = num;
			}
			else if (code >= 1 && code <= 3)
			{
				Log.LogInfo((object)"Cloudy");
				weatherSystem.intensity = 0f;
				weatherSystem.density = num * 2f;
			}
			else if (code >= 51 && code <= 67)
			{
				Log.LogInfo((object)"Rain (not implemented)");
			}
			else if (code >= 71 && code <= 77)
			{
				Log.LogInfo((object)"Snow");
				weatherSystem.intensity = 1f;
				weatherSystem.density = num;
			}
			else if (code >= 95)
			{
				Log.LogInfo((object)"Thunderstorm (not implemented)");
			}
		}
	}
	public class CoroutineRunner : MonoBehaviour
	{
	}
	[Serializable]
	internal class MeteoResponse
	{
		public CurrentWeather current_weather;
	}
	[Serializable]
	internal class CurrentWeather
	{
		public int weathercode;

		public float temperature;
	}
	[HarmonyPatch(typeof(sDayNightCycle), "Temperature")]
	internal class TempPatch
	{
		private static void Postfix(ref float __result)
		{
			__result = Plugin.realTemp;
		}
	}
}