Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of SidewalkEconomy v1.0.1
SidewalkEconomy-IL2CPP.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
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.Versioning; using System.Security; using System.Security.Permissions; using HarmonyLib; using Il2Cpp; using Il2CppFishNet; using Il2CppFishNet.Connection; using Il2CppFishNet.Managing; using Il2CppFishNet.Managing.Object; using Il2CppFishNet.Object; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppScheduleOne; using Il2CppScheduleOne.AvatarFramework; using Il2CppScheduleOne.Building; using Il2CppScheduleOne.Core.Items.Framework; using Il2CppScheduleOne.DevUtilities; using Il2CppScheduleOne.Dialogue; using Il2CppScheduleOne.Employees; using Il2CppScheduleOne.EntityFramework; using Il2CppScheduleOne.GameTime; using Il2CppScheduleOne.Heatmap; using Il2CppScheduleOne.Interaction; using Il2CppScheduleOne.ItemFramework; using Il2CppScheduleOne.Lighting; using Il2CppScheduleOne.NPCs; using Il2CppScheduleOne.ObjectScripts; using Il2CppScheduleOne.Persistence; using Il2CppScheduleOne.Persistence.Datas; using Il2CppScheduleOne.Persistence.Loaders; using Il2CppScheduleOne.PlayerScripts; using Il2CppScheduleOne.Product; using Il2CppScheduleOne.Property; using Il2CppScheduleOne.Storage; using Il2CppScheduleOne.Tiles; using Il2CppScheduleOne.UI; using Il2CppScheduleOne.UI.Management; using Il2CppScheduleOne.Variables; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using S1API.AssetBundles; using S1API.Economy; using S1API.Entities; using S1API.Entities.Customer; using S1API.Entities.Relation; using S1API.GameTime; using S1API.Internal.Abstraction; using S1API.Items; using S1API.Leveling; using S1API.Map; using S1API.Map.Buildings; using S1API.Products; using S1API.Quests; using S1API.Quests.Constants; using S1API.Saveables; using SidewalkEconomy; using SidewalkEconomy.Controllers; using SidewalkEconomy.Helpers; using SidewalkEconomy.Saveables; using UnityEngine; using UnityEngine.AI; using UnityEngine.Events; 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: MelonInfo(typeof(SidewalkEconomyMod), "SidewalkEconomy", "1.0.1", "SirTidez", null)] [assembly: MelonColor(1, 0, 0, 255)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("SidewalkEconomy-IL2CPP")] [assembly: AssemblyConfiguration("Debug IL2CPP")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+de42324db45c550550d20429a0fc34e385f32488")] [assembly: AssemblyProduct("SidewalkEconomy-IL2CPP")] [assembly: AssemblyTitle("SidewalkEconomy-IL2CPP")] [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 SidewalkEconomy { public static class BuildInfo { public const string Name = "SidewalkEconomy"; public const string Description = "Allows placing buildable items anywhere on the map"; public const string Author = "SirTidez"; public const string Version = "1.0.1"; } public class SidewalkEconomyMod : MelonMod { [CompilerGenerated] private sealed class <CheckTentSpawnOnSceneLoad>d__61 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public SidewalkEconomyMod <>4__this; private int <attempts>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CheckTentSpawnOnSceneLoad>d__61(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; ModLogger.Info("CheckTentSpawnOnSceneLoad: Started waiting for tent prefab..."); <attempts>5__1 = 0; goto IL_0074; case 1: <>1__state = -1; goto IL_0074; case 2: { <>1__state = -1; ModLogger.Info($"CheckTentSpawnOnSceneLoad: Tent prefab loaded after {<attempts>5__1} attempts - performing initial level check"); <>4__this.OnDayPass(); ModLogger.Info("CheckTentSpawnOnSceneLoad: OnDayPass() called"); return false; } IL_0074: if (!EnsureTentPrefabReady(<attempts>5__1 > 0) && <attempts>5__1 < 100) { <attempts>5__1++; <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; } if (!EnsureTentPrefabReady(logReload: true)) { ModLogger.Warn("Tent prefab not loaded after waiting - cannot perform initial level check"); return false; } <>2__current = (object)new WaitForSeconds(1.5f); <>1__state = 2; return true; } } 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 <EnsureTentOwnedWhenReady>d__59 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public SidewalkEconomyMod <>4__this; private float <startTime>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <EnsureTentOwnedWhenReady>d__59(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <startTime>5__1 = Time.time; break; case 1: <>1__state = -1; break; } if (TentOwnershipSaveable.Instance == null || !TentOwnershipSaveable.Instance.IsReady) { if (Time.time - <startTime>5__1 > 10f) { ModLogger.Warn("Timed out waiting for tent ownership saveable"); return false; } <>2__current = null; <>1__state = 1; return true; } TentOwnershipManager.SetTentOwned(owned: true); ModLogger.Info("Tent ownership set to player"); 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 <LoadAssetBundleAssets>d__65 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public SidewalkEconomyMod <>4__this; private WrappedAssetBundle <bundle>5__1; private string[] <allAssetNames>5__2; private string[] <>s__3; private int <>s__4; private string <assetName>5__5; private Exception <ex>5__6; private Exception <ex>5__7; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadAssetBundleAssets>d__65(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <bundle>5__1 = null; <allAssetNames>5__2 = null; <>s__3 = null; <assetName>5__5 = null; <ex>5__6 = null; <ex>5__7 = null; <>1__state = -2; } private bool MoveNext() { if (<>1__state != 0) { return false; } <>1__state = -1; try { ModLogger.Debug("Loading assetbundle assets..."); if (CachedAssetBundle == null) { ModLogger.Debug("Loading assetbundle..."); CachedAssetBundle = AssetBundleUtils.LoadAssetBundle("SidewalkEconomy.sidewalkeconomy"); if (CachedAssetBundle == null) { ModLogger.Error("Failed to load assetbundle"); return false; } ModLogger.Debug("✓ Assetbundle loaded successfully"); } <bundle>5__1 = CachedAssetBundle; try { ModLogger.Info("=== Listing all assets in assetbundle ==="); <allAssetNames>5__2 = <bundle>5__1.GetAllAssetNames(); ModLogger.Info($"Total assets in bundle: {<allAssetNames>5__2.Length}"); <>s__3 = <allAssetNames>5__2; for (<>s__4 = 0; <>s__4 < <>s__3.Length; <>s__4++) { <assetName>5__5 = <>s__3[<>s__4]; ModLogger.Info(" - " + <assetName>5__5); <assetName>5__5 = null; } <>s__3 = null; ModLogger.Info("=== End of asset list ==="); <allAssetNames>5__2 = null; } catch (Exception ex) { <ex>5__6 = ex; ModLogger.Warn("Failed to list assets: " + <ex>5__6.Message); ModLogger.Warn("Stack trace: " + <ex>5__6.StackTrace); } ModLogger.Debug("Loading sleepingbag prefab: assets/sidewalk economy/sleepingbag.prefab"); SleepingBagPrefab = <bundle>5__1.LoadAsset<GameObject>("assets/sidewalk economy/sleepingbag.prefab"); if ((Object)(object)SleepingBagPrefab == (Object)null) { ModLogger.Warn("Failed to load sleepingbag prefab 'assets/sidewalk economy/sleepingbag.prefab' from assetbundle"); } else { ModLogger.Info("✓ Sleepingbag prefab loaded: " + ((Object)SleepingBagPrefab).name); ShaderUtils.FixShadersOnGameObject(SleepingBagPrefab); } ModLogger.Debug("Loading tent prefab: assets/sidewalk economy/tent.prefab"); TentPrefab = <bundle>5__1.LoadAsset<GameObject>("assets/sidewalk economy/tent.prefab"); if ((Object)(object)TentPrefab == (Object)null) { ModLogger.Warn("Failed to load tent prefab 'assets/sidewalk economy/tent.prefab' from assetbundle"); } else { _tentPrefabLoadedOnce = true; ModLogger.Info("✓ Tent prefab loaded: " + ((Object)TentPrefab).name); ShaderUtils.FixShadersOnGameObject(TentPrefab); } ModLogger.Info("Assetbundle assets loaded successfully"); PrefabControllerInstaller.InstallControllers(SleepingBagPrefab, TentPrefab); ModLogger.Info("Scheduling custom buildable item registration..."); MelonCoroutines.Start(ItemRegistrationManager.RegisterCustomItemsWhenReady()); ModLogger.Info("Requesting initial world spawns..."); WorldSpawnManager.SpawnInitialShelters(SleepingBagPrefab, TentPrefab); <bundle>5__1 = null; } catch (Exception ex) { <ex>5__7 = ex; ModLogger.Error("[MainMod] Failed to load assetbundle assets: " + <ex>5__7.Message); ModLogger.Error("Stack trace: " + <ex>5__7.StackTrace); } 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 <RegisterSaveListener>d__63 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; private SaveManager <saveManager>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RegisterSaveListener>d__63(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <saveManager>5__1 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if (!Singleton<SaveManager>.InstanceExists) { <>2__current = null; <>1__state = 1; return true; } if (_saveListenerRegistered) { return false; } <saveManager>5__1 = Singleton<SaveManager>.Instance; if ((Object)(object)<saveManager>5__1 == (Object)null) { return false; } if (_saveStartHandler == null) { _saveStartHandler = OnGameSaveStarted; } <saveManager>5__1.onSaveStart.AddListener(UnityAction.op_Implicit(_saveStartHandler)); _saveListenerRegistered = true; ModLogger.Debug("Registered outside buildable save listener"); 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 <SubscribeToDayPassEvent>d__60 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public SidewalkEconomyMod <>4__this; private Exception <ex>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SubscribeToDayPassEvent>d__60(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <ex>5__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (_dayPassEventSubscribed) { return false; } <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 2; return true; case 2: <>1__state = -1; try { ModLogger.Debug("Subscribing to S1API TimeManager.OnDayPass event"); TimeManager.OnDayPass = (Action)Delegate.Combine(TimeManager.OnDayPass, new Action(<>4__this.OnDayPass)); _dayPassEventSubscribed = true; ModLogger.Info("Subscribed to day pass event - tent will spawn when player reaches Peddler rank"); } catch (Exception ex) { <ex>5__1 = ex; ModLogger.Error("Failed to subscribe to day pass event: " + <ex>5__1.Message); ModLogger.Error("Stack trace: " + <ex>5__1.StackTrace); } 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(); } } private const float SyntheticPropertyRenameDistance = 30f; private const int SyntheticPropertyNameMaxLength = 48; private const float SyntheticIdleEditDistance = 40f; private const float SyntheticIdleYawStep = 5f; private static Harmony HarmonyInstance; private static bool _tentSpawned; private static bool _tentPrefabLoadedOnce; private static bool _dayPassEventSubscribed; private static bool _saveListenerRegistered; private static Action _saveStartHandler; private bool _showSyntheticPropertyRenameWindow; private bool _focusSyntheticPropertyNameInput; private string _syntheticPropertyNameInput = string.Empty; private string _syntheticPropertyRenameError = string.Empty; private Rect _syntheticPropertyRenameWindowRect = new Rect(24f, 24f, 420f, 180f); private Property _selectedSyntheticProperty; private bool _isSyntheticIdleEditMode; private Property _syntheticIdleEditProperty; private Vector3 _syntheticIdleEditPosition; private float _syntheticIdleEditYaw; private bool _syntheticIdleEditValid; private string _syntheticIdleEditStatus = string.Empty; private GameObject _syntheticIdleEditGizmo; private Renderer _syntheticIdleEditGizmoBaseRenderer; private Renderer _syntheticIdleEditGizmoArrowRenderer; public static WrappedAssetBundle? CachedAssetBundle { get; private set; } public static GameObject? SleepingBagPrefab { get; private set; } public static GameObject? TentPrefab { get; private set; } public override void OnInitializeMelon() { //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown ModSettings.Initialize(); ModLogger.SetDebugEnabled(ModSettings.EnableDebugLogging); GameTimeManager.Instance.Initialize(); ModLogger.Info("Build-anywhere systems initialized"); new TentOwnershipSaveable(); new TentStorageSaveable(); SyntheticGridSaveable syntheticGridSaveable = new SyntheticGridSaveable(); OutsideBuildablesSaveable outsideBuildablesSaveable = new OutsideBuildablesSaveable(); SyntheticGridManager.Initialize(); if (_saveStartHandler == null) { _saveStartHandler = OnGameSaveStarted; } ModLogger.Info("SidewalkEconomy initialized"); ModLogger.Debug("This will only show in debug mode"); ModLogger.Debug($"[MainMod] EnableOutsidePlacement: {ModSettings.EnableOutsidePlacement}"); ModLogger.Debug($"[MainMod] EnableDebugLogging: {ModSettings.EnableDebugLogging}"); HarmonyInstance = new Harmony("SidewalkEconomy"); ModLogger.Debug("[MainMod] Applying Harmony patches..."); ModLogger.Debug("[MainMod] Patching BuildUpdate_Grid.CheckIntersections"); HarmonyInstance.PatchAll(); ModLogger.Debug("Harmony patches applied"); try { MethodInfo method = typeof(BuildUpdate_Grid).GetMethod("CheckIntersections", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); ModLogger.Debug($"[MainMod] CheckIntersections method found: {method != null}"); if (!(method != null)) { return; } Patches patchInfo = Harmony.GetPatchInfo((MethodBase)method); ModLogger.Debug($"[MainMod] CheckIntersections patches: {(patchInfo?.Postfixes?.Count).GetValueOrDefault()} postfix(es)"); if (patchInfo?.Postfixes == null || patchInfo.Postfixes.Count <= 0) { return; } foreach (Patch postfix in patchInfo.Postfixes) { ModLogger.Debug("[MainMod] - Postfix: " + postfix.owner); } } catch (Exception value) { ModLogger.Warn($"[MainMod] Error verifying patches: {value}"); } } public override void OnDeinitializeMelon() { ExitSyntheticIdleEditMode(); if (_saveListenerRegistered && Singleton<SaveManager>.InstanceExists) { try { if (_saveStartHandler != null) { Singleton<SaveManager>.Instance.onSaveStart.RemoveListener(UnityAction.op_Implicit(_saveStartHandler)); } _saveListenerRegistered = false; ModLogger.Debug("Unregistered outside buildable save listener"); } catch (Exception ex) { ModLogger.Warn("Failed to unregister save listener: " + ex.Message); } } if (_dayPassEventSubscribed) { try { TimeManager.OnDayPass = (Action)Delegate.Remove(TimeManager.OnDayPass, new Action(OnDayPass)); _dayPassEventSubscribed = false; ModLogger.Debug("Unsubscribed from S1API TimeManager day pass event"); } catch (Exception ex2) { ModLogger.Debug("Failed to unsubscribe from day pass event: " + ex2.Message); } } Harmony harmonyInstance = HarmonyInstance; if (harmonyInstance != null) { harmonyInstance.UnpatchSelf(); } ModLogger.Debug("Harmony patches removed"); GameTimeManager.Instance.Shutdown(); } public override void OnUpdate() { HandleSyntheticIdleEditHotkey(); UpdateSyntheticIdleEditMode(); HandleSyntheticPropertyRenameHotkey(); } public override void OnGUI() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (_isSyntheticIdleEditMode) { DrawSyntheticIdleEditOverlay(); } if (_showSyntheticPropertyRenameWindow) { GUILayout.BeginArea(_syntheticPropertyRenameWindowRect, "Rename Synthetic Property", GUI.skin.window); DrawSyntheticPropertyRenameWindowContents(); GUILayout.EndArea(); } } private void HandleTeleportHotkeys() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown((KeyCode)91)) { TeleportPlayer(Constants.WorldSpawns.TENT_POSITION, "Tent"); } if (Input.GetKeyDown((KeyCode)112)) { TeleportPlayer(Constants.WorldSpawns.SLEEPING_BAG_POSITION, "Sleeping Bag"); } } private void HandleSyntheticPropertyRenameHotkey() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) if (!ModSettings.EnableOutsidePlacement || _showSyntheticPropertyRenameWindow || _isSyntheticIdleEditMode || !IsAltHeld() || !Input.GetKeyDown((KeyCode)114)) { return; } Player local = Player.Local; if ((Object)(object)local == (Object)null) { ModLogger.Warn("Cannot rename synthetic property: player not found"); return; } Property nearestSyntheticProperty = SyntheticGridManager.GetNearestSyntheticProperty(((Component)local).transform.position, 30f); if ((Object)(object)nearestSyntheticProperty == (Object)null) { ModLogger.Warn("No synthetic property found nearby. Move closer and press Alt+R."); return; } _selectedSyntheticProperty = nearestSyntheticProperty; _syntheticPropertyNameInput = nearestSyntheticProperty.PropertyName ?? string.Empty; _syntheticPropertyRenameError = string.Empty; _showSyntheticPropertyRenameWindow = true; _focusSyntheticPropertyNameInput = true; } private void DrawSyntheticPropertyRenameWindowContents() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Invalid comparison between Unknown and I4 //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Invalid comparison between Unknown and I4 Event current = Event.current; if ((int)current.type == 4) { if ((int)current.keyCode == 27) { CloseSyntheticPropertyRenameWindow(); current.Use(); return; } if ((int)current.keyCode == 13 || (int)current.keyCode == 271) { ApplySyntheticPropertyRename(); current.Use(); return; } } GUILayout.BeginVertical((Il2CppReferenceArray<GUILayoutOption>)null); GUILayout.Label("Set a custom name for this synthetic property.", (Il2CppReferenceArray<GUILayoutOption>)null); GUILayout.Label("This name is used internally for save data and troubleshooting.", (Il2CppReferenceArray<GUILayoutOption>)null); GUILayout.Space(6f); GUI.SetNextControlName("SyntheticPropertyNameInput"); _syntheticPropertyNameInput = GUILayout.TextField(_syntheticPropertyNameInput ?? string.Empty, 48, Array.Empty<GUILayoutOption>()); if (_focusSyntheticPropertyNameInput) { GUI.FocusControl("SyntheticPropertyNameInput"); _focusSyntheticPropertyNameInput = false; } if (!string.IsNullOrWhiteSpace(_syntheticPropertyRenameError)) { GUILayout.Label(_syntheticPropertyRenameError, (Il2CppReferenceArray<GUILayoutOption>)null); } GUILayout.FlexibleSpace(); GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null); if (GUILayout.Button("Save", (Il2CppReferenceArray<GUILayoutOption>)null)) { ApplySyntheticPropertyRename(); } if (GUILayout.Button("Cancel", (Il2CppReferenceArray<GUILayoutOption>)null)) { CloseSyntheticPropertyRenameWindow(); } GUILayout.EndHorizontal(); GUILayout.EndVertical(); } private void ApplySyntheticPropertyRename() { if ((Object)(object)_selectedSyntheticProperty == (Object)null) { _syntheticPropertyRenameError = "No synthetic property selected."; return; } string text = (_syntheticPropertyNameInput ?? string.Empty).Trim(); if (string.IsNullOrWhiteSpace(text)) { _syntheticPropertyRenameError = "Property name cannot be empty."; return; } if (!SyntheticGridManager.TryRenameSyntheticProperty(_selectedSyntheticProperty, text, out var failureReason)) { _syntheticPropertyRenameError = (string.IsNullOrWhiteSpace(failureReason) ? "Failed to rename synthetic property." : failureReason); return; } ModLogger.Info("Renamed synthetic property to '" + text + "'"); CloseSyntheticPropertyRenameWindow(); } private void CloseSyntheticPropertyRenameWindow() { _showSyntheticPropertyRenameWindow = false; _focusSyntheticPropertyNameInput = false; _syntheticPropertyRenameError = string.Empty; _selectedSyntheticProperty = null; } private void HandleSyntheticIdleEditHotkey() { if (!SyntheticGridManager.AreSyntheticEmployeesEnabled()) { if (_isSyntheticIdleEditMode) { ExitSyntheticIdleEditMode(); } if (IsAltHeld() && Input.GetKeyDown((KeyCode)105)) { ModLogger.Warn("Synthetic property employees are disabled in this version."); } } else if (ModSettings.EnableOutsidePlacement && !_showSyntheticPropertyRenameWindow && IsAltHeld() && Input.GetKeyDown((KeyCode)105)) { if (_isSyntheticIdleEditMode) { ExitSyntheticIdleEditMode(); } else { EnterSyntheticIdleEditMode(); } } } private void EnterSyntheticIdleEditMode() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) if (!SyntheticGridManager.AreSyntheticEmployeesEnabled()) { return; } Player local = Player.Local; if ((Object)(object)local == (Object)null) { ModLogger.Warn("Cannot enter synthetic idle edit mode: player not found"); return; } Property nearestSyntheticProperty = SyntheticGridManager.GetNearestSyntheticProperty(((Component)local).transform.position, 40f); if ((Object)(object)nearestSyntheticProperty == (Object)null) { ModLogger.Warn("No synthetic property found nearby. Move closer and press Alt+I."); return; } _syntheticIdleEditProperty = nearestSyntheticProperty; if (!SyntheticGridManager.TryGetManualIdlePoint(nearestSyntheticProperty, out _syntheticIdleEditPosition, out _syntheticIdleEditYaw)) { _syntheticIdleEditPosition = (((Object)(object)nearestSyntheticProperty.NPCSpawnPoint != (Object)null) ? nearestSyntheticProperty.NPCSpawnPoint.position : ((Component)local).transform.position); _syntheticIdleEditYaw = ((Component)local).transform.eulerAngles.y; } _isSyntheticIdleEditMode = true; _syntheticIdleEditStatus = "Idle edit mode active."; EnsureSyntheticIdleEditGizmo(); UpdateSyntheticIdleEditGizmo(); } private void ExitSyntheticIdleEditMode() { _isSyntheticIdleEditMode = false; _syntheticIdleEditProperty = null; _syntheticIdleEditStatus = string.Empty; if ((Object)(object)_syntheticIdleEditGizmo != (Object)null) { Object.Destroy((Object)(object)_syntheticIdleEditGizmo); _syntheticIdleEditGizmo = null; _syntheticIdleEditGizmoBaseRenderer = null; _syntheticIdleEditGizmoArrowRenderer = null; } } private void UpdateSyntheticIdleEditMode() { //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) if (!SyntheticGridManager.AreSyntheticEmployeesEnabled()) { if (_isSyntheticIdleEditMode) { ExitSyntheticIdleEditMode(); } } else { if (!_isSyntheticIdleEditMode) { return; } if ((Object)(object)_syntheticIdleEditProperty == (Object)null) { ExitSyntheticIdleEditMode(); return; } if (Input.GetKeyDown((KeyCode)27)) { ExitSyntheticIdleEditMode(); return; } bool flag = false; if (Input.GetKeyDown((KeyCode)113)) { _syntheticIdleEditYaw -= 5f; flag = true; } if (Input.GetKeyDown((KeyCode)101)) { _syntheticIdleEditYaw += 5f; flag = true; } if (Input.GetMouseButtonDown(0) && TryGetIdleEditAimPoint(out var point)) { _syntheticIdleEditPosition = point; flag = true; } if (Input.GetKeyDown((KeyCode)8) || Input.GetKeyDown((KeyCode)127)) { SyntheticGridManager.ClearManualIdlePoint(_syntheticIdleEditProperty); _syntheticIdleEditStatus = "Cleared manual idle marker. Hiring is now disabled until a marker is placed."; UpdateSyntheticIdleEditGizmo(); return; } if (flag) { if (SyntheticGridManager.TrySetManualIdlePoint(_syntheticIdleEditProperty, _syntheticIdleEditPosition, _syntheticIdleEditYaw, out var failureReason)) { _syntheticIdleEditStatus = "Idle marker updated."; } else { _syntheticIdleEditStatus = (string.IsNullOrWhiteSpace(failureReason) ? "Idle marker is invalid. Move it to clear navmesh." : failureReason); } } UpdateSyntheticIdleEditGizmo(); } } private bool TryGetIdleEditAimPoint(out Vector3 point) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) point = Vector3.zero; Camera main = Camera.main; if ((Object)(object)main == (Object)null) { return false; } Ray val = main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0f)); RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val, ref val2, 500f, -1, (QueryTriggerInteraction)1)) { point = ((RaycastHit)(ref val2)).point; return true; } point = ((Component)main).transform.position + ((Component)main).transform.forward * 4f; return true; } private void EnsureSyntheticIdleEditGizmo() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_syntheticIdleEditGizmo != (Object)null)) { _syntheticIdleEditGizmo = new GameObject("SyntheticIdleEditGizmo"); GameObject val = GameObject.CreatePrimitive((PrimitiveType)2); ((Object)val).name = "Base"; val.transform.SetParent(_syntheticIdleEditGizmo.transform, false); val.transform.localScale = new Vector3(0.35f, 0.05f, 0.35f); val.transform.localPosition = Vector3.zero; _syntheticIdleEditGizmoBaseRenderer = val.GetComponent<Renderer>(); Collider component = val.GetComponent<Collider>(); if ((Object)(object)component != (Object)null) { component.enabled = false; } GameObject val2 = GameObject.CreatePrimitive((PrimitiveType)3); ((Object)val2).name = "Forward"; val2.transform.SetParent(_syntheticIdleEditGizmo.transform, false); val2.transform.localScale = new Vector3(0.08f, 0.08f, 0.5f); val2.transform.localPosition = new Vector3(0f, 0.1f, 0.25f); _syntheticIdleEditGizmoArrowRenderer = val2.GetComponent<Renderer>(); Collider component2 = val2.GetComponent<Collider>(); if ((Object)(object)component2 != (Object)null) { component2.enabled = false; } } } private void UpdateSyntheticIdleEditGizmo() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) if (!_isSyntheticIdleEditMode || (Object)(object)_syntheticIdleEditProperty == (Object)null) { return; } EnsureSyntheticIdleEditGizmo(); if ((Object)(object)_syntheticIdleEditGizmo == (Object)null) { return; } _syntheticIdleEditYaw = Mathf.Repeat(_syntheticIdleEditYaw, 360f); if (SyntheticGridManager.TryValidateEmployeeIdlePoint(_syntheticIdleEditProperty, _syntheticIdleEditPosition, out var resolvedPosition, out var failureReason)) { _syntheticIdleEditValid = true; _syntheticIdleEditPosition = resolvedPosition; if (string.IsNullOrWhiteSpace(_syntheticIdleEditStatus) || _syntheticIdleEditStatus.Contains("invalid", StringComparison.OrdinalIgnoreCase)) { _syntheticIdleEditStatus = "Idle marker is valid."; } } else { _syntheticIdleEditValid = false; if (!string.IsNullOrWhiteSpace(failureReason)) { _syntheticIdleEditStatus = failureReason; } } _syntheticIdleEditGizmo.transform.position = _syntheticIdleEditPosition + Vector3.up * 0.03f; _syntheticIdleEditGizmo.transform.rotation = Quaternion.Euler(0f, _syntheticIdleEditYaw, 0f); Color color = (_syntheticIdleEditValid ? new Color(0.2f, 0.9f, 0.3f, 0.95f) : new Color(0.95f, 0.25f, 0.25f, 0.95f)); if ((Object)(object)_syntheticIdleEditGizmoBaseRenderer != (Object)null) { _syntheticIdleEditGizmoBaseRenderer.material.color = color; } if ((Object)(object)_syntheticIdleEditGizmoArrowRenderer != (Object)null) { _syntheticIdleEditGizmoArrowRenderer.material.color = color; } } private void DrawSyntheticIdleEditOverlay() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (SyntheticGridManager.AreSyntheticEmployeesEnabled() && _isSyntheticIdleEditMode && !((Object)(object)_syntheticIdleEditProperty == (Object)null)) { GUILayout.BeginArea(new Rect(24f, 214f, 520f, 150f), "Synthetic Idle Edit", GUI.skin.window); GUILayout.Label("Property: " + _syntheticIdleEditProperty.PropertyName, (Il2CppReferenceArray<GUILayoutOption>)null); GUILayout.Label($"Point: {_syntheticIdleEditPosition.x:F2}, {_syntheticIdleEditPosition.y:F2}, {_syntheticIdleEditPosition.z:F2} | Yaw: {_syntheticIdleEditYaw:F1}", (Il2CppReferenceArray<GUILayoutOption>)null); GUILayout.Label(_syntheticIdleEditValid ? "Status: Valid" : "Status: Invalid", (Il2CppReferenceArray<GUILayoutOption>)null); if (!string.IsNullOrWhiteSpace(_syntheticIdleEditStatus)) { GUILayout.Label(_syntheticIdleEditStatus, (Il2CppReferenceArray<GUILayoutOption>)null); } GUILayout.Label("Controls: LMB place marker | Q/E rotate | Delete clear | Alt+I or Esc exit", (Il2CppReferenceArray<GUILayoutOption>)null); GUILayout.EndArea(); } } private static bool IsAltHeld() { return Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307); } private void TeleportPlayer(Vector3 position, string label) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) Player local = Player.Local; if ((Object)(object)local == (Object)null) { ModLogger.Warn("Teleport skipped - player not found (" + label + ")"); return; } ((Component)local).transform.position = position; ModLogger.Info($"Teleported player to {label} at {position}"); } private void OnDayPass() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Invalid comparison between Unknown and I4 //IL_009b: Unknown result type (might be due to invalid IL or missing references) ModLogger.Info("OnDayPass: Called"); try { if (_tentSpawned && !IsTentPresent()) { _tentSpawned = false; ModLogger.Warn("Tent spawn flag was set but tent is missing in scene. Retrying spawn."); } if (_tentSpawned) { ModLogger.Debug("OnDayPass: Tent already spawned, skipping"); return; } if (!EnsureTentPrefabReady(logReload: true)) { ModLogger.Debug("OnDayPass: Tent prefab not loaded yet"); return; } Rank rank = LevelManager.Rank; if ((int)rank >= 2) { ModLogger.Info($"Player reached {rank} - spawning tent!"); if (WorldSpawnManager.SpawnTent(TentPrefab)) { EnsureTentOwned(); _tentSpawned = true; } else { ModLogger.Warn("Tent spawn attempt did not succeed; will retry on next trigger."); } } } catch (Exception ex) { ModLogger.Error("OnDayPass error: " + ex.Message); } } private static bool IsTentPresent() { return (Object)(object)GameObject.Find("SidewalkEconomy_Tent_Spawn") != (Object)null; } private void EnsureTentOwned() { if (!TentOwnershipManager.IsTentOwned()) { TentOwnershipManager.SetTentOwned(owned: true); if (!TentOwnershipManager.IsTentOwned()) { MelonCoroutines.Start(EnsureTentOwnedWhenReady()); } else { ModLogger.Info("Tent ownership set to player"); } } } [IteratorStateMachine(typeof(<EnsureTentOwnedWhenReady>d__59))] private IEnumerator EnsureTentOwnedWhenReady() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <EnsureTentOwnedWhenReady>d__59(0) { <>4__this = this }; } [IteratorStateMachine(typeof(<SubscribeToDayPassEvent>d__60))] private IEnumerator SubscribeToDayPassEvent() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SubscribeToDayPassEvent>d__60(0) { <>4__this = this }; } [IteratorStateMachine(typeof(<CheckTentSpawnOnSceneLoad>d__61))] private IEnumerator CheckTentSpawnOnSceneLoad() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <CheckTentSpawnOnSceneLoad>d__61(0) { <>4__this = this }; } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { ExitSyntheticIdleEditMode(); ModLogger.Debug("Scene loaded: " + sceneName); if (sceneName == "Main") { _tentSpawned = IsTentPresent(); ModLogger.Debug($"Tent present on scene load: {_tentSpawned}"); ModLogger.Debug("Main scene loaded"); MelonCoroutines.Start(LoadAssetBundleAssets()); MelonCoroutines.Start(SubscribeToDayPassEvent()); MelonCoroutines.Start(Utils.WaitForNetwork(CheckTentSpawnOnSceneLoad())); MelonCoroutines.Start(RegisterSaveListener()); } } [IteratorStateMachine(typeof(<RegisterSaveListener>d__63))] private static IEnumerator RegisterSaveListener() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <RegisterSaveListener>d__63(0); } private static void OnGameSaveStarted() { if (OutsideBuildablesSaveable.Instance == null) { ModLogger.Warn("Outside buildables saveable not ready; skipping capture"); } else { OutsideBuildablesSaveable.Instance.CaptureFromWorld(); } SyntheticGridManager.CaptureForSave(); TentStorageEntity.FlushAllForSave(); } [IteratorStateMachine(typeof(<LoadAssetBundleAssets>d__65))] private IEnumerator LoadAssetBundleAssets() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadAssetBundleAssets>d__65(0) { <>4__this = this }; } private static bool EnsureTentPrefabReady(bool logReload) { if ((Object)(object)TentPrefab != (Object)null) { return true; } if (CachedAssetBundle == null || !_tentPrefabLoadedOnce) { return false; } try { TentPrefab = CachedAssetBundle.LoadAsset<GameObject>("assets/sidewalk economy/tent.prefab"); if ((Object)(object)TentPrefab != (Object)null) { if (logReload) { ModLogger.Debug("Rehydrated tent prefab reference from cached assetbundle"); } ShaderUtils.FixShadersOnGameObject(TentPrefab); return true; } } catch (Exception ex) { if (logReload) { ModLogger.Warn("Failed to rehydrate tent prefab from cached assetbundle: " + ex.Message); } } return false; } } public static class ModSettings { private static MelonPreferences_Category _category; private static MelonPreferences_Entry<bool> _enableDebugLogging; private static MelonPreferences_Entry<bool> _enableOutsidePlacement; public static bool EnableDebugLogging { get { return _enableDebugLogging?.Value ?? false; } set { if (_enableDebugLogging != null) { _enableDebugLogging.Value = value; MelonPreferences.Save(); } } } public static bool EnableOutsidePlacement { get { return _enableOutsidePlacement?.Value ?? true; } set { if (_enableOutsidePlacement != null) { _enableOutsidePlacement.Value = value; MelonPreferences.Save(); } } } public static void Initialize() { _category = MelonPreferences.CreateCategory("SidewalkEconomy", "SidewalkEconomy"); _enableDebugLogging = _category.CreateEntry<bool>("EnableDebugLogging", false, "Enable Debug Logging", "When enabled, detailed debug messages will be logged to the console.", false, false, (ValueValidator)null, (string)null); _enableOutsidePlacement = _category.CreateEntry<bool>("EnableOutsidePlacement", true, "Enable Outside Placement", "Enables or disables the ability to place buildable items anywhere on the map. When enabled, players can place items outside of approved building zones.", false, false, (ValueValidator)null, (string)null); MelonPreferences.Save(); } } } namespace SidewalkEconomy.Saveables { public sealed class OutsideBuildablesSaveable : Saveable { private sealed class OutsideBuildableRecordWithOrder { public OutsideBuildableRecord Record { get; set; } public int LoadOrder { get; set; } } private sealed class PendingRestoreRecord { public OutsideBuildableRecord Record { get; set; } public int SourceIndex { get; set; } public int Attempts { get; set; } public string LastDeferredReason { get; set; } } private enum RestoreOutcome { Restored, Deferred, PermanentFailure } private enum BuildableCaptureState { Valid, Transient, Invalid } [CompilerGenerated] private sealed class <RestoreRoutine>d__15 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public OutsideBuildablesSaveable <>4__this; private LoadManager <loadManager>5__1; private List<PendingRestoreRecord> <pending>5__2; private int <restoredCount>5__3; private int <permanentlyFailedCount>5__4; private int <pass>5__5; private bool <restoredAnyThisPass>5__6; private int <passCount>5__7; private List<PendingRestoreRecord> <nextPending>5__8; private List<PendingRestoreRecord>.Enumerator <>s__9; private PendingRestoreRecord <pendingRecord>5__10; private RestoreOutcome <outcome>5__11; private string <reason>5__12; private RestoreOutcome <>s__13; private List<PendingRestoreRecord>.Enumerator <>s__14; private PendingRestoreRecord <pendingRecord>5__15; private string <reason>5__16; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RestoreRoutine>d__15(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 4) { try { } finally { <>m__Finally1(); } } <loadManager>5__1 = null; <pending>5__2 = null; <nextPending>5__8 = null; <>s__9 = default(List<PendingRestoreRecord>.Enumerator); <pendingRecord>5__10 = null; <reason>5__12 = null; <>s__14 = default(List<PendingRestoreRecord>.Enumerator); <pendingRecord>5__15 = null; <reason>5__16 = null; <>1__state = -2; } private bool MoveNext() { //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_0455: Unknown result type (might be due to invalid IL or missing references) //IL_045f: Expected O, but got Unknown try { Scene activeScene; switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (!InstanceFinder.IsServer) { ModLogger.Debug("Outside buildable restore skipped - not server"); return false; } goto IL_008d; case 1: <>1__state = -1; goto IL_008d; case 2: <>1__state = -1; goto IL_00c9; case 3: <>1__state = -1; goto IL_00f7; case 4: <>1__state = -3; <reason>5__12 = null; <pendingRecord>5__10 = null; goto IL_03e7; case 5: { <>1__state = -1; goto IL_0475; } IL_048f: if (<pass>5__5 > 6 || <pending>5__2.Count <= 0) { break; } <restoredAnyThisPass>5__6 = false; <passCount>5__7 = <pending>5__2.Count; <nextPending>5__8 = new List<PendingRestoreRecord>(); ModLogger.Info((<pass>5__5 == 1) ? $"Restoring {<passCount>5__7} outside buildable(s)..." : $"Retrying {<passCount>5__7} deferred outside buildable restore(s) (pass {<pass>5__5}/{6})"); <>s__9 = <pending>5__2.GetEnumerator(); <>1__state = -3; goto IL_03e7; IL_008d: activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).name != "Main") { <>2__current = null; <>1__state = 1; return true; } goto IL_00c9; IL_00c9: if (!NetworkSingleton<GameManager>.InstanceExists) { <>2__current = null; <>1__state = 2; return true; } goto IL_00f7; IL_00f7: if ((Object)(object)Singleton<LoadManager>.Instance == (Object)null) { <>2__current = null; <>1__state = 3; return true; } <loadManager>5__1 = Singleton<LoadManager>.Instance; <pending>5__2 = <>4__this._records.Select((OutsideBuildableRecord record, int index) => new PendingRestoreRecord { Record = record, SourceIndex = index + 1 }).ToList(); <restoredCount>5__3 = 0; <permanentlyFailedCount>5__4 = 0; <pass>5__5 = 1; goto IL_048f; IL_0475: <nextPending>5__8 = null; <pass>5__5++; goto IL_048f; IL_03e7: if (<>s__9.MoveNext()) { <pendingRecord>5__10 = <>s__9.Current; <pendingRecord>5__10.Attempts++; <outcome>5__11 = TryRestoreRecord(<loadManager>5__1, <pendingRecord>5__10, out <reason>5__12); RestoreOutcome restoreOutcome = <outcome>5__11; <>s__13 = restoreOutcome; switch (<>s__13) { case RestoreOutcome.Restored: <restoredAnyThisPass>5__6 = true; <restoredCount>5__3++; break; case RestoreOutcome.Deferred: if (!string.Equals(<pendingRecord>5__10.LastDeferredReason, <reason>5__12, StringComparison.Ordinal)) { ModLogger.Warn("Deferring restore for " + DescribeRecord(<pendingRecord>5__10.Record, <pendingRecord>5__10.SourceIndex) + ": " + <reason>5__12); <pendingRecord>5__10.LastDeferredReason = <reason>5__12; } <nextPending>5__8.Add(<pendingRecord>5__10); break; case RestoreOutcome.PermanentFailure: <permanentlyFailedCount>5__4++; ModLogger.Warn("Failed to restore " + DescribeRecord(<pendingRecord>5__10.Record, <pendingRecord>5__10.SourceIndex) + ": " + <reason>5__12); break; } <>2__current = null; <>1__state = 4; return true; } <>m__Finally1(); <>s__9 = default(List<PendingRestoreRecord>.Enumerator); <pending>5__2 = <nextPending>5__8; if (<pending>5__2.Count == 0) { break; } if (<pass>5__5 < 6) { <>2__current = (object)new WaitForSeconds(<restoredAnyThisPass>5__6 ? 0.25f : 1f); <>1__state = 5; return true; } goto IL_0475; } <>s__14 = <pending>5__2.GetEnumerator(); try { while (<>s__14.MoveNext()) { <pendingRecord>5__15 = <>s__14.Current; <permanentlyFailedCount>5__4++; <reason>5__16 = (string.IsNullOrWhiteSpace(<pendingRecord>5__15.LastDeferredReason) ? "dependencies never reached a ready state" : <pendingRecord>5__15.LastDeferredReason); ModLogger.Warn($"Giving up on deferred restore for {DescribeRecord(<pendingRecord>5__15.Record, <pendingRecord>5__15.SourceIndex)} after {<pendingRecord>5__15.Attempts} attempt(s): {<reason>5__16}"); <reason>5__16 = null; <pendingRecord>5__15 = null; } } finally { ((IDisposable)<>s__14).Dispose(); } <>s__14 = default(List<PendingRestoreRecord>.Enumerator); ModLogger.Info($"Outside buildables restore complete ({<restoredCount>5__3} restored, {<permanentlyFailedCount>5__4} unresolved)"); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>s__9).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const int RestoreRetryAttempts = 3; private const int MaxDeferredRestorePasses = 6; private const float DeferredRestoreRetryDelaySeconds = 1f; [SaveableField("outside_buildables")] private List<OutsideBuildableRecord> _records = new List<OutsideBuildableRecord>(); public static OutsideBuildablesSaveable Instance { get; private set; } public override SaveableLoadOrder LoadOrder => (SaveableLoadOrder)1; public OutsideBuildablesSaveable() { Instance = this; } public IReadOnlyList<OutsideBuildableRecord> GetRecords() { return _records; } public void SetRecords(List<OutsideBuildableRecord> records) { _records = records ?? new List<OutsideBuildableRecord>(); } public void CaptureFromWorld() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (!InstanceFinder.IsServer) { ModLogger.Debug("Outside buildable capture skipped - not server"); return; } Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).name != "Main") { ModLogger.Debug("Outside buildable capture skipped - not in Main scene"); return; } List<OutsideBuildableRecord> list = CloneRecords(_records); int num = 0; int num2 = 0; foreach (Property item in Property.Properties.AsEnumerable<Property>()) { if ((Object)(object)item == (Object)null || (Object)(object)InjectedComponentHelper.GetInjectedComponent<SyntheticPropertyMarker>((Component)(object)item) == (Object)null) { continue; } if (!TryGetPropertyGridGuids(item, out var gridGuids)) { ModLogger.Warn("Preserving outside buildable snapshot for property '" + item.PropertyCode + "' because no grid GUIDs were available"); num2++; continue; } List<BuildableItem> list2 = new List<BuildableItem>(); List<OutsideBuildableRecordWithOrder> list3 = new List<OutsideBuildableRecordWithOrder>(); string text = string.Empty; foreach (BuildableItem item2 in item.BuildableItems.AsEnumerable<BuildableItem>().ToList()) { string reason; bool pruneFromProperty; switch (EvaluateBuildableCaptureState(item, item2, out reason, out pruneFromProperty)) { case BuildableCaptureState.Transient: text = reason; break; case BuildableCaptureState.Invalid: ModLogger.Warn("Skipping outside buildable capture for " + DescribeBuildable(item2) + ": " + reason); if (pruneFromProperty && (Object)(object)item2 != (Object)null) { list2.Add(item2); } continue; default: { DynamicSaveData val = null; try { val = item2.GetSaveData(); } catch (Exception ex) { text = "save data capture failed for " + DescribeBuildable(item2) + ": " + ex.Message; break; } if (val == null) { text = "save data was null for " + DescribeBuildable(item2); break; } OutsideBuildableRecord record2 = CreateRecord(val); list3.Add(new OutsideBuildableRecordWithOrder { Record = record2, LoadOrder = GetLoadOrder(val.BaseData) }); continue; } } break; } if (!string.IsNullOrWhiteSpace(text)) { ModLogger.Warn("Preserving outside buildable snapshot for property '" + item.PropertyCode + "' because " + text); num2++; continue; } RemoveRecordsForGridGuids(list, gridGuids); list.AddRange(from item in list3 orderby item.LoadOrder select item.Record); num++; PruneInvalidBuildables(item, list2); } _records = list.OrderBy((OutsideBuildableRecord record) => GetLoadOrder(record?.BaseData)).ToList(); ModLogger.Info($"Captured {_records.Count} outside buildable(s) for save across {num} stable property snapshot(s); preserved {num2} property snapshot(s)"); } protected override void OnLoaded() { ModLogger.Info($"Outside buildables loaded ({_records?.Count ?? 0} record(s))"); if (_records != null && _records.Count != 0) { MelonCoroutines.Start(Utils.WaitForPlayer(RestoreRoutine())); } } [IteratorStateMachine(typeof(<RestoreRoutine>d__15))] private IEnumerator RestoreRoutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <RestoreRoutine>d__15(0) { <>4__this = this }; } private static DynamicSaveData BuildDynamicSaveData(OutsideBuildableRecord record) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown DynamicSaveData val = new DynamicSaveData(new SaveData()) { DataType = (record.DataType ?? string.Empty), BaseData = (record.BaseData ?? string.Empty) }; val.AdditionalDatas.Clear(); if (record.AdditionalDatas != null) { foreach (AdditionalDataRecord additionalData in record.AdditionalDatas) { if (additionalData != null) { val.AdditionalDatas.Add(new AdditionalData { Name = (additionalData.Name ?? string.Empty), Contents = (additionalData.Contents ?? string.Empty) }); } } } return val; } private static OutsideBuildableRecord CreateRecord(DynamicSaveData saveData) { return new OutsideBuildableRecord { DataType = ((SaveData)saveData).DataType, BaseData = saveData.BaseData, AdditionalDatas = ConvertAdditionalDatas(saveData.AdditionalDatas.AsEnumerable<AdditionalData>()) }; } private static List<AdditionalDataRecord> ConvertAdditionalDatas(IEnumerable<AdditionalData> additionalDatas) { List<AdditionalDataRecord> list = new List<AdditionalDataRecord>(); if (additionalDatas == null) { return list; } foreach (AdditionalData additionalData in additionalDatas) { if (additionalData != null) { list.Add(new AdditionalDataRecord { Name = (additionalData.Name ?? string.Empty), Contents = (additionalData.Contents ?? string.Empty) }); } } return list; } private static bool TryGetGridGuid(string baseDataJson, out Guid guid) { guid = default(Guid); if (string.IsNullOrEmpty(baseDataJson)) { return false; } try { GridItemData val = JsonUtility.FromJson<GridItemData>(baseDataJson); if (val != null && !string.IsNullOrEmpty(val.GridGUID) && Guid.TryParse(val.GridGUID, out guid)) { return true; } } catch (Exception value) { ModLogger.Warn($"Failed to read grid GUID from base data: {value}"); } return false; } private static bool TryGetBuildableGuid(string baseDataJson, out Guid guid) { guid = default(Guid); if (string.IsNullOrEmpty(baseDataJson)) { return false; } try { BuildableItemData val = JsonUtility.FromJson<BuildableItemData>(baseDataJson); if (val != null && !string.IsNullOrEmpty(val.GUID) && Guid.TryParse(val.GUID, out guid)) { return true; } } catch (Exception value) { ModLogger.Warn($"Failed to read buildable GUID from base data: {value}"); } return false; } private static T GetObjectByGuid<T>(Guid guid) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) return GUIDManager.GetObject<T>(new Guid(guid.ToString())); } private static bool TryParseProceduralGridItemData(string baseDataJson, out ProceduralGridItemData proceduralData) { proceduralData = null; if (string.IsNullOrEmpty(baseDataJson)) { return false; } try { proceduralData = JsonUtility.FromJson<ProceduralGridItemData>(baseDataJson); if (proceduralData == null || proceduralData.FootprintMatches == null || ((Il2CppArrayBase<FootprintMatchData>)(object)proceduralData.FootprintMatches).Length == 0) { proceduralData = null; return false; } return true; } catch { proceduralData = null; return false; } } private static bool AreProceduralDependenciesReady(ProceduralGridItemData proceduralData, out string reason) { //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Expected O, but got Unknown //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Expected O, but got Unknown reason = string.Empty; if (proceduralData == null || proceduralData.FootprintMatches == null || ((Il2CppArrayBase<FootprintMatchData>)(object)proceduralData.FootprintMatches).Length == 0) { reason = "procedural footprint match data is missing"; return false; } for (int i = 0; i < ((Il2CppArrayBase<FootprintMatchData>)(object)proceduralData.FootprintMatches).Length; i++) { FootprintMatchData val = ((Il2CppArrayBase<FootprintMatchData>)(object)proceduralData.FootprintMatches)[i]; if (!Guid.TryParse(val.TileOwnerGUID, out var result)) { reason = $"invalid tile owner GUID at footprint index {i}"; return false; } BuildableItem objectByGuid = GetObjectByGuid<BuildableItem>(result); if ((Object)(object)objectByGuid == (Object)null || objectByGuid.IsDestroyed || (Object)(object)((NetworkBehaviour)objectByGuid).NetworkObject == (Object)null) { reason = "tile owner " + val.TileOwnerGUID + " is missing"; return false; } CoordinateProceduralTilePair val2 = new CoordinateProceduralTilePair { coord = new Coordinate(Mathf.RoundToInt(val.FootprintCoordinate.x), Mathf.RoundToInt(val.FootprintCoordinate.y)), tileParent = ((NetworkBehaviour)objectByGuid).NetworkObject, tileIndex = val.TileIndex }; ProceduralTile tile; try { tile = val2.tile; } catch { reason = $"tile lookup failed for owner {val.TileOwnerGUID} at index {val.TileIndex}"; return false; } if ((Object)(object)tile == (Object)null) { reason = $"tile lookup returned null for owner {val.TileOwnerGUID} at index {val.TileIndex}"; return false; } if ((Object)(object)tile.MatchedFootprintTile == (Object)null) { reason = $"tile {val.TileIndex} on owner {val.TileOwnerGUID} is not matched to a footprint tile"; return false; } if ((Object)(object)tile.MatchedFootprintTile.MatchedStandardTile == (Object)null) { reason = $"tile {val.TileIndex} on owner {val.TileOwnerGUID} has no matched standard tile"; return false; } if ((Object)(object)tile.MatchedFootprintTile.MatchedStandardTile.LightExposureNode == (Object)null) { reason = $"tile {val.TileIndex} on owner {val.TileOwnerGUID} has no light exposure node"; return false; } } return true; } private static int GetLoadOrder(string baseDataJson) { if (string.IsNullOrEmpty(baseDataJson)) { return 0; } try { BuildableItemData val = JsonUtility.FromJson<BuildableItemData>(baseDataJson); return (val != null) ? val.LoadOrder : 0; } catch (Exception value) { ModLogger.Warn($"Failed to read load order from base data: {value}"); } return 0; } private static BuildableCaptureState EvaluateBuildableCaptureState(Property property, BuildableItem buildable, out string reason, out bool pruneFromProperty) { reason = string.Empty; pruneFromProperty = false; if ((Object)(object)buildable == (Object)null) { reason = "buildable was null"; return BuildableCaptureState.Invalid; } if ((Object)(object)((Component)buildable).gameObject == (Object)null) { reason = "buildable game object missing"; pruneFromProperty = true; return BuildableCaptureState.Invalid; } if (buildable.IsDestroyed) { reason = "buildable is destroyed"; pruneFromProperty = true; return BuildableCaptureState.Invalid; } if (buildable.isGhost) { reason = "buildable is still ghost-only"; return BuildableCaptureState.Transient; } if (!buildable.Initialized) { reason = "buildable was never initialized"; return BuildableCaptureState.Transient; } if ((Object)(object)buildable.ParentProperty == (Object)null) { reason = "buildable parent property is missing"; pruneFromProperty = true; return BuildableCaptureState.Invalid; } if ((Object)(object)buildable.ParentProperty != (Object)(object)property) { reason = "buildable belongs to a different property"; pruneFromProperty = true; return BuildableCaptureState.Invalid; } GridItem val = (GridItem)(object)((buildable is GridItem) ? buildable : null); if (val != null && (Object)(object)val.OwnerGrid == (Object)null) { reason = "grid item owner grid is missing"; return BuildableCaptureState.Transient; } Pot val2 = (Pot)(object)((buildable is Pot) ? buildable : null); if (val2 != null && val2.Configuration == null) { reason = "pot configuration is missing"; return BuildableCaptureState.Transient; } return BuildableCaptureState.Valid; } private static void PruneInvalidBuildables(Property property, List<BuildableItem> invalidBuildables) { if ((Object)(object)property == (Object)null || property.BuildableItems == null) { return; } if (invalidBuildables == null) { invalidBuildables = new List<BuildableItem>(); } int num = 0; for (int num2 = property.BuildableItems.Count - 1; num2 >= 0; num2--) { if ((Object)(object)property.BuildableItems[num2] == (Object)null) { property.BuildableItems.RemoveAt(num2); num++; } } foreach (BuildableItem item in invalidBuildables.Distinct().ToList()) { if (!((Object)(object)item == (Object)null) && property.BuildableItems.Remove(item)) { num++; } } if (num > 0) { ModLogger.Warn($"Pruned {num} invalid outside buildable(s) from property '{property.PropertyCode}'"); } } private static string DescribeBuildable(BuildableItem buildable) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)buildable == (Object)null) { return "<null buildable>"; } string text = (((Object)(object)((Component)buildable).gameObject != (Object)null) ? ((Object)((Component)buildable).gameObject).name : ((object)buildable).GetType().Name); string text2 = "no-guid"; try { Guid gUID = buildable.GUID; string text3 = ((object)(Guid)(ref gUID)).ToString(); if (!string.IsNullOrWhiteSpace(text3) && !text3.Equals("00000000-0000-0000-0000-000000000000", StringComparison.Ordinal)) { text2 = text3; } } catch { } return text + " (" + text2 + ")"; } private static RestoreOutcome TryRestoreRecord(LoadManager loadManager, PendingRestoreRecord pendingRecord, out string reason) { reason = string.Empty; if (pendingRecord?.Record == null) { reason = "record was null"; return RestoreOutcome.PermanentFailure; } OutsideBuildableRecord record = pendingRecord.Record; if (string.IsNullOrEmpty(record.BaseData)) { reason = "record had empty base data"; return RestoreOutcome.PermanentFailure; } DynamicSaveData val = BuildDynamicSaveData(record); if (string.IsNullOrEmpty(((SaveData)val).DataType)) { reason = "record was missing data type"; return RestoreOutcome.PermanentFailure; } if (!TryGetBuildableGuid(val.BaseData, out var guid)) { reason = "record had invalid buildable GUID"; return RestoreOutcome.PermanentFailure; } if (TryGetGridGuid(val.BaseData, out var guid2) && (Object)(object)GetObjectByGuid<Grid>(guid2) == (Object)null) { reason = $"grid {guid2} is not ready"; return RestoreOutcome.Deferred; } BuildableItemLoader objectLoader = loadManager.GetObjectLoader(((SaveData)val).DataType); if (objectLoader == null) { reason = "object loader for " + ((SaveData)val).DataType + " is not ready"; return RestoreOutcome.Deferred; } if (TryParseProceduralGridItemData(val.BaseData, out var proceduralData) && !AreProceduralDependenciesReady(proceduralData, out var reason2)) { reason = "procedural dependencies are not ready: " + reason2; return RestoreOutcome.Deferred; } try { objectLoader.Load(val); ModLogger.Info($"Restored outside buildable {((SaveData)val).DataType} ({guid})"); return RestoreOutcome.Restored; } catch (Exception ex) { reason = ((SaveData)val).DataType + " restore threw: " + ex.Message; return (pendingRecord.Attempts < 3) ? RestoreOutcome.Deferred : RestoreOutcome.PermanentFailure; } } private static List<OutsideBuildableRecord> CloneRecords(IEnumerable<OutsideBuildableRecord> records) { List<OutsideBuildableRecord> list = new List<OutsideBuildableRecord>(); if (records == null) { return list; } foreach (OutsideBuildableRecord record in records) { if (record != null) { list.Add(new OutsideBuildableRecord { DataType = record.DataType, BaseData = record.BaseData, AdditionalDatas = ((record.AdditionalDatas != null) ? record.AdditionalDatas.Select((AdditionalDataRecord additional) => new AdditionalDataRecord { Name = (additional?.Name ?? string.Empty), Contents = (additional?.Contents ?? string.Empty) }).ToList() : new List<AdditionalDataRecord>()) }); } } return list; } private static bool TryGetPropertyGridGuids(Property property, out HashSet<Guid> gridGuids) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) gridGuids = new HashSet<Guid>(); if (((property != null) ? property.Grids : null) == null) { return false; } foreach (Grid item in property.Grids.AsEnumerable<Grid>()) { if ((Object)(object)item == (Object)null) { continue; } try { Guid gUID = item.GUID; string input = ((object)(Guid)(ref gUID)).ToString(); if (Guid.TryParse(input, out var result) && result != Guid.Empty) { gridGuids.Add(result); } } catch { } } return gridGuids.Count > 0; } private static void RemoveRecordsForGridGuids(List<OutsideBuildableRecord> records, HashSet<Guid> gridGuids) { if (records == null || records.Count == 0 || gridGuids == null || gridGuids.Count == 0) { return; } for (int num = records.Count - 1; num >= 0; num--) { OutsideBuildableRecord outsideBuildableRecord = records[num]; Guid guid; if (outsideBuildableRecord == null) { records.RemoveAt(num); } else if (TryGetGridGuid(outsideBuildableRecord.BaseData, out guid) && gridGuids.Contains(guid)) { records.RemoveAt(num); } } } private static string DescribeRecord(OutsideBuildableRecord record, int sourceIndex) { if (record == null) { return $"outside buildable record #{sourceIndex}"; } string text = ((!string.IsNullOrWhiteSpace(record.DataType)) ? record.DataType : $"record #{sourceIndex}"); if (TryGetBuildableGuid(record.BaseData, out var guid)) { return $"{text} ({guid})"; } return text; } } public sealed class OutsideBuildableRecord { public string DataType { get; set; } public string BaseData { get; set; } public List<AdditionalDataRecord> AdditionalDatas { get; set; } = new List<AdditionalDataRecord>(); } public sealed class AdditionalDataRecord { public string Name { get; set; } public string Contents { get; set; } } public sealed class SyntheticGridSaveable : Saveable { [SaveableField("synthetic_grids")] private List<SyntheticGridRecord> _records = new List<SyntheticGridRecord>(); public static SyntheticGridSaveable Instance { get; private set; } public SyntheticGridSaveable() { Instance = this; } public IReadOnlyList<SyntheticGridRecord> GetRecords() { return _records; } public void SetRecords(List<SyntheticGridRecord> records) { _records = records ?? new List<SyntheticGridRecord>(); } protected override void OnLoaded() { if (SyntheticGridManager.TryMigrateLegacySyntheticGridRecords(_records, out var migratedRecords, out var mergedPropertiesCount, out var mergedRecordCount)) { _records = migratedRecords; ModLogger.Warn($"Migrated legacy synthetic properties: merged {mergedRecordCount} record(s) across {mergedPropertiesCount} nearby cluster(s). Changes will persist on the next save."); } SyntheticGridManager.RestoreFromSave(_records); } } public sealed class SyntheticGridRecord { public string PropertyCode { get; set; } public string PropertyName { get; set; } public string GridGuid { get; set; } public Vector3 Origin { get; set; } public int MinX { get; set; } public int MaxX { get; set; } public int MinY { get; set; } public int MaxY { get; set; } public bool HasManualIdlePoint { get; set; } public Vector3 ManualIdlePointPosition { get; set; } public float ManualIdlePointYaw { get; set; } } public sealed class TentOwnershipSaveable : Saveable { private bool _isReady = false; [SaveableField("tent_owned")] private bool _tentOwned = false; [SaveableField("quest_completed")] private bool _questCompleted = false; [SaveableField("npc_relocated")] private bool _npcRelocated = false; public static TentOwnershipSaveable Instance { get; private set; } public override SaveableLoadOrder LoadOrder => (SaveableLoadOrder)1; public bool IsTentOwned => _tentOwned; public bool IsQuestCompleted => _questCompleted; public bool IsNPCRelocated => _npcRelocated; public bool IsReady => _isReady; public TentOwnershipSaveable() { Instance = this; } protected override void OnCreated() { _isReady = true; } protected override void OnLoaded() { _isReady = true; } public void SetTentOwned(bool owned) { _tentOwned = owned; } public void SetQuestCompleted(bool completed) { _questCompleted = completed; if (completed) { _tentOwned = true; } } public void SetNPCRelocated(bool relocated) { _npcRelocated = relocated; } } public sealed class TentStorageSaveable : Saveable { private bool _isReady; [SaveableField("tent_storage_items")] private List<TentStoredItem> _items = new List<TentStoredItem>(); public static TentStorageSaveable Instance { get; private set; } public override SaveableLoadOrder LoadOrder => (SaveableLoadOrder)1; public bool IsReady => _isReady; public TentStorageSaveable() { Instance = this; } public IReadOnlyList<TentStoredItem> GetItems() { return _items; } public void SetItems(List<TentStoredItem> items) { _items = items ?? new List<TentStoredItem>(); } protected override void OnCreated() { _isReady = true; ModLogger.Info("Tent storage saveable created"); } protected override void OnLoaded() { _isReady = true; ModLogger.Info($"Tent storage loaded ({_items?.Count ?? 0} item(s))"); } protected override void OnSaved() { ModLogger.Info($"Tent storage saved ({_items?.Count ?? 0} item(s))"); } } public sealed class TentStoredItem { public string ItemId { get; set; } public int Quantity { get; set; } } } namespace SidewalkEconomy.Quests { public sealed class TentInheritanceQuest : Quest { private const string QUEST_ID = "reginald_tent_inheritance_quest"; [SaveableField("rewardGranted")] private bool _rewardGranted = false; [SaveableField("requiredItems")] private Dictionary<string, int> _requiredItems = new Dictionary<string, int>(); private QuestEntry _itemEntry; private QuestEntry _returnEntry; public IReadOnlyDictionary<string, int> RequiredItems => _requiredItems; protected override string Title => "New Beginnings"; protected override string Description => ""; protected override bool AutoBegin => false; protected override void OnCreated() { ((Registerable)this).OnCreated(); if (base.QuestEntries.Count == 0) { if (_requiredItems.Count == 0) { _requiredItems["growtent"] = 1; _requiredItems["ogkushseed"] = 3; } _itemEntry = ((Quest)this).AddEntry("Bring " + PrintRequiredItems() + " for Reggie", (Vector3?)null); _itemEntry.Begin(); _returnEntry = ((Quest)this).AddEntry("Return to Reggie with the supplies", (Vector3?)null); _returnEntry.SetState((QuestState)0); } else { if (base.QuestEntries.Count >= 1) { _itemEntry = base.QuestEntries[0]; } if (base.QuestEntries.Count >= 2) { _returnEntry = base.QuestEntries[1]; } } } public string PrintRequiredItems() { return string.Join(", ", _requiredItems.Select(delegate(KeyValuePair<string, int> entry) { string key = entry.Key; int value = entry.Value; ItemDefinition itemDefinition = ItemManager.GetItemDefinition(key); string value2 = ((itemDefinition != null) ? itemDefinition.Name : null) ?? ("Unknown Item (" + key + ")"); return $"{value} {value2}"; })); } public void SetRequiredItems(Dictionary<string, int> requiredItems) { if (requiredItems == null) { ModLogger.Warn("Required items cannot be null. Quest setup aborted."); } else { _requiredItems = requiredItems; } } } } namespace SidewalkEconomy.NPCs { public sealed class ReginaldIterson : NPC { [Serializable] private class PersistedData { public bool QuestCompleted = false; public bool NPCRelocated = false; } [SaveableField("ReginaldItersonData")] private PersistedData _data = new PersistedData(); public override bool IsPhysical => true; public ReginaldIterson() : base("reginald_iterson", "Reginald", "Iterson", (Sprite)null) { } protected override void ConfigurePrefab(NPCPrefabBuilder builder) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) Vector3 val = CalculateSpawnPosition(); Building val2 = Building.Get<NorthApartments>(); Building val3 = Building.Get<Arcade>(); Building val4 = Building.Get<BudsBar>(); builder.WithIdentity("reginald_iterson", "Reginald", "Iterson").WithAppearanceDefaults((Action<AvatarDefaultsBuilder>)delegate(AvatarDefaultsBuilder av) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) av.Gender = 0f; av.Height = 1f; av.Weight = 0.1f; av.SkinColor = new Color32((byte)211, (byte)181, (byte)143, byte.MaxValue); av.LeftEyeLidColor = new Color(0.827f, 0.71f, 0.561f); av.RightEyeLidColor = new Color(0.827f, 0.71f, 0.561f); av.EyeBallTint = new Color(1f, 1f, 1f); av.HairColor = new Color(0.176f, 0.125f, 0.075f); av.HairPath = "Avatar/Hair/closebuzzcut/CloseBuzzCut"; av.EyeballMaterialIdentifier = "Default"; av.PupilDilation = 0.5f; av.EyebrowScale = 1f; av.EyebrowThickness = 1f; av.EyebrowRestingHeight = -0.75f; av.EyebrowRestingAngle = 0.3f; av.LeftEye = (0.5f, 0.35f); av.RightEye = (0.555f, 0.35f); av.WithFaceLayer("Avatar/Layers/Face/Face_Agape", new Color(1f, 1f, 1f)); av.WithFaceLayer("Avatar/Layers/Face/FacialHair_Stubble", new Color(0f, 0f, 0f)); av.WithFaceLayer("Avatar/Layers/Face/FacialHair_Goatee", new Color(0.325f, 0.282f, 0.192f)); av.WithBodyLayer("Avatar/Layers/Top/ChestHair1", new Color(0.318f, 0.294f, 0.2f)); av.WithBodyLayer("Avatar/Layers/Bottom/CargoPants", new Color(0.125f, 0.125f, 0.125f)); av.WithBodyLayer("Avatar/Layers/Bottom/MaleUnderwear", new Color(1f, 1f, 1f)); av.WithBodyLayer("Avatar/Layers/Top/FlannelButtonUp", new Color(0.541f, 0f, 0f)); av.WithAccessoryLayer("Avatar/Accessories/Chest/OpenVest/OpenVest", new Color(0.592f, 0.569f, 0.341f)); av.WithAccessoryLayer("Avatar/Accessories/Head/Cap/Cap", new Color(0.384f, 0.369f, 0.216f)); }).WithSpawnPosition(val) .EnsureCustomer() .WithCustomerDefaults((Action<CustomerDataBuilder>)delegate(CustomerDataBuilder cd) { cd.WithSpending(400f, 900f).WithOrdersPerWeek(1, 4).WithPreferredOrderDay((Day)6) .WithOrderTime(900) .WithStandards((CustomerStandard)1) .WithMutualRelationRequirement(2.5f, 4f) .AllowDirectApproach(true) .WithCallPoliceChance(0.7f) .WithDependence(0.15f, 1f) .WithAffinities((IEnumerable<ValueTuple<DrugType, float>>)new(DrugType, float)[2] { ((DrugType)0, 0.5f), ((DrugType)4, 0.5f) }); }) .WithRelationshipDefaults((Action<NPCRelationshipDataBuilder>)delegate(NPCRelationshipDataBuilder r) { r.WithDelta(1f).SetUnlocked(false).SetUnlockType((UnlockType)1) .WithConnectionsById(new string[1] { "kyle_cooley" }); }) .WithInventoryDefaults((Action<RandomInventoryItemsBuilder>)delegate(RandomInventoryItemsBuilder inv) { inv.WithStartupItems(new string[2] { "machete", "donut" }).WithRandomCash(50, 500); }); } private Vector3 CalculateSpawnPosition() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) Vector3 tENT_POSITION = Constants.WorldSpawns.TENT_POSITION; return new Vector3(500f, 0f, 500f); } protected override void OnLoaded() { ((Saveable)this).OnLoaded(); } protected override void OnCreated() { ((NPC)this).OnCreated(); ((NPC)this).Appearance.Build(); ((NPC)this).Schedule.Enable(); ((NPC)this).Region = (Region)0; SetupDialogue(); ((NPC)this).RequiresRegionUnlocked = false; ((NPC)this).Region = (Region)0; ((NPC)this).Aggressiveness = 0f; } private void SetupDialogue() { } } } namespace SidewalkEconomy.Helpers { public static class AssetBundleUtils { private static readonly SidewalkEconomyMod mod = MelonAssembly.FindMelonInstance<SidewalkEconomyMod>(); private static readonly MelonAssembly melonAssembly = ((MelonBase)mod).MelonAssembly; private static readonly Assembly modAssembly = melonAssembly.Assembly; private static Dictionary<string, WrappedAssetBundle> _bundleCache = new Dictionary<string, WrappedAssetBundle>(); public static WrappedAssetBundle LoadAssetBundle(string bundleFileName) { try { if (_bundleCache.TryGetValue(bundleFileName, out var value)) { if (value != null) { ModLogger.Debug("Using cached asset bundle: " + bundleFileName); return value; } _bundleCache.Remove(bundleFileName); } string text = (bundleFileName.Contains(".") ? bundleFileName : (modAssembly.GetName().Name + "." + bundleFileName)); ModLogger.Debug("Loading asset bundle from embedded resource: " + text); WrappedAssetBundle assetBundleFromStream = AssetLoader.GetAssetBundleFromStream(text, modAssembly); if (assetBundleFromStream == null) { if (modAssembly != null) { string[] manifestResourceNames = modAssembly.GetManifestResourceNames(); ModLogger.Error($"Failed to load AssetBundle from resource: '{text}'. Make sure the bundle file '{bundleFileName}' is set as 'EmbeddedResource' in your .csproj file."); ModLogger.Error($"Available embedded resources ({manifestResourceNames.Length}):"); string[] array = manifestResourceNames; foreach (string text2 in array) { ModLogger.Error(" - " + text2); } } else { ModLogger.Error($"Failed to load AssetBundle from resource: '{text}'. Make sure the bundle file '{bundleFileName}' is set as 'EmbeddedResource' in your .csproj file."); } return null; } _bundleCache[bundleFileName] = assetBundleFromStream; ModLogger.Debug("✓ Successfully loaded and cached asset bundle: " + bundleFileName); return assetBundleFromStream; } catch (Exception ex) { ModLogger.Error("Failed to load AssetBundle '" + bundleFileName + "': " + ex.Message); ModLogger.Error("Stack trace: " + ex.StackTrace); return null; } } public static WrappedAssetBundle GetLoadedAssetBundle(string asset_name_flag) { if (_bundleCache.TryGetValue(asset_name_flag, out var value)) { if (value != null) { return value; } _bundleCache.Remove(asset_name_flag); } IEnumerable<AssetBundle> allLoadedAssetBundles = AssetBundle.GetAllLoadedAssetBundles(); AssetBundle[] array = ConvertIl2CppEnumerableToArray(allLoadedAssetBundles); try { AssetBundle[] array2 = array; foreach (AssetBundle val in array2) { if (!((Object)(object)val == (Object)null) && val.Contains(asset_name_flag)) { string name = ((Object)val).name; if (_bundleCache.TryGetValue(name, out var value2)) { return value2; } ModLogger.Debug("Found bundle '" + name + "' but it's not in cache as WrappedAssetBundle"); } } string text = ""; AssetBundle[] array3 = array; foreach (AssetBundle val2 in array3) { if (!((Object)(object)val2 == (Object)null)) { try { string[] array4 = Il2CppArrayBase<string>.op_Implicit((Il2CppArrayBase<string>)(object)val2.GetAllAssetNames()); string value3 = string.Join("\n\r -", array4); text += $"{((Object)val2).name}({array4.Length} assets):{value3}\n"; } catch { text = text + ((Object)val2).name + "(error getting asset names)\n"; } } } ModLogger.Error($"Asset '{asset_name_flag}' not found in {array.Length} bundle(s).\n{text}"); return null; } catch (Exception ex) { ModLogger.Error("Failed to get loaded AssetBundle: " + ex.Message); ModLogger.Error("Stack trace: " + ex.StackTrace); return null; } } public static GameObject LoadAssetFromBundle(string asset_name) { WrappedAssetBundle loadedAssetBundle = GetLoadedAssetBundle(asset_name); if (loadedAssetBundle == null) { ModLogger.Error("Cannot load asset '" + asset_name + "': bundle not found"); return null; } try { return loadedAssetBundle.LoadAsset<GameObject>(asset_name); } catch (Exception ex) { ModLogger.Error("Failed to load asset '" + asset_name + "' from bundle: " + ex.Message); return null; } } public static void ClearBundleCache(string bundleFileName = null) { if (bundleFileName == null) { _bundleCache.Clear(); ModLogger.Debug("Cleared entire asset bundle cache"); } else if (_bundleCache.Remove(bundleFileName)) { ModLogger.Debug("Removed " + bundleFileName + " from asset bundle cache"); } } private static AssetBundle[] ConvertIl2CppEnumerableToArray(object il2cppEnumerable) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown if (il2cppEnumerable == null) { return Array.Empty<AssetBundle>(); } List<AssetBundle> list = new List<AssetBundle>(); foreach (AssetBundle item in (IEnumerable)il2cppEnumerable) { AssetBundle val = item; if ((Object)(object)val != (Object)null) { list.Add(val); } } return list.ToArray(); } } internal static class BuildModeRecovery { private const float OutsidePlacementHeartbeatWindowSeconds = 0.35f; private static float _outsidePlacementHeartbeatExpiry; internal static void ReportOutsidePlacementHeartbeat() { _outsidePlacementHeartbeatExpiry = Time.unscaledTime + 0.35f; } internal static bool OwnsOutsidePlacementFlow() { return Time.unscaledTime <= _outsidePlacementHeartbeatExpiry && IsBuildModeActive(); } internal static bool IsBuildModeActive() { if (!NetworkSingleton<BuildManager>.InstanceExists) { _outsidePlacementHeartbeatExpiry = 0f; return false; } BuildManager instance = NetworkSingleton<BuildManager>.Instance; if ((Object)(object)instance == (Object)null) { _outsidePlacementHeartbeatExpiry = 0f; return false; } if (instance.isBuilding) { return true; } return (Object)(object)GetCurrentBuildHandler(instance) != (Object)null; } internal static bool TryExitBuildMode(string reason, bool force) { if (!NetworkSingleton<BuildManager>.InstanceExists) { _outsidePlacementHeartbeatExpiry = 0f; return false; } BuildManager instance = NetworkSingleton<BuildManager>.Instance; if ((Object)(object)instance == (Object)null) { return false; } GameObject currentBuildHandler = GetCurrentBuildHandler(instance); bool isBuilding = instance.isBuilding; if (!force && !isBuilding && (Object)(object)currentBuildHandler == (Object)null) { _outsidePlacementHeartbeatExpiry = 0f; return false; } try { if (isBuilding && (Object)(object)currentBuildHandler != (Object)null && (Object)(object)currentBuildHandler.GetComponent<BuildStop_Base>() != (Object)null) { instance.StopBuilding(); if (!IsBuildModeStillActive(instance)) { _outsidePlacementHeartbeatExpiry = 0f; ModLogger.Debug("Build mode exited: " + reason); return true; } ModLogger.Warn("BuildManager.StopBuilding did not fully clear build mode (" + reason + "); escalating to forced reset"); } } catch (Exception value) { ModLogger.Warn($"BuildManager.StopBuilding failed during recovery ({reason}): {value}"); } ForceResetBuildMode(instance, currentBuildHandler, reason); return true; } private static GameObject GetCurrentBuildHandler(BuildManager buildManager) { return ((Object)(object)buildManager != (Object)null) ? buildManager.currentBuildHandler : null; } private static void ForceResetBuildMode(BuildManager buildManager, GameObject handler, string reason) { try { if ((Object)(object)handler != (Object)null) { BuildStop_Base component = handler.GetComponent<BuildStop_Base>(); if ((Object)(object)component != (Object)null) { component.Stop_Building(); } else { Object.Destroy((Object)(object)handler); } } TrySetPropertyValue(buildManager, "isBuilding", value: false); TrySetPropertyValue<GameObject>(buildManager, "currentBuildHandler", null); if (Singleton<InputPromptsCanvas>.InstanceExists) { Singleton<InputPromptsCanvas>.Instance.UnloadModule(); } if (Singleton<HeatmapManager>.InstanceExists) { Singleton<HeatmapManager>.Instance.SetAllHeatmapsActive(false); } if (PlayerSingleton<PlayerCamera>.InstanceExists && Singleton<HUD>.InstanceExists && PlayerSingleton<PlayerCamera>.Instance.activeUIElementCount == 0) { Singleton<HUD>.Instance.SetCrosshairVisible(true); } _outsidePlacementHeartbeatExpiry = 0f; if (IsBuildModeStillActive(buildManager)) { ModLogger.Warn("Forced build mode reset completed with residual active state: " + reason); } else { ModLogger.Warn("Forced build mode reset: " + reason); } } catch (Exception value) { ModLogger.Error($"Forced build mode reset failed ({reason}): {value}"); } } private static bool IsBuildModeStillActive(BuildManager buildManager) { return (Object)(object)buildManager != (Object)null && (buildManager.isBuilding || (Object)(object)GetCurrentBuildHandler(buildManager) != (Object)null); } private static bool TrySetPropertyValue<T>(BuildManager buildManager, string propertyName, T value) { if ((Object)(object)buildManager == (Object)null) { return false; } PropertyInfo property = typeof(BuildManager).GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if ((object)property == null || !property.CanWrite) { return false; } try { property.SetValue(buildManager, value, null); return true; } catch { return false; } } } public static class Constants { public static class AssetBundle { public const string ASSETBUNDLE_NAME = "SidewalkEconomy.sidewalkeconomy"; public const string ASSETBUNDLE_FILE_NAME = "sidewalkeconomy"; public const string SLEEPINGBAG_PREFAB_NAME = "assets/sidewalk economy/sleepingbag.prefab"; public const string TENT_PREFAB_NAME = "assets/sidewalk economy/tent.prefab"; } public static class CustomItems { public const string TENT_ID = "sidewalkeconomy.tent"; public const string SLEEPINGBAG_ID = "sidewalkeconomy.sleepingbag"; public const string TENT_NAME = "Sidewalk Tent"; public const string SLEEPINGBAG_NAME = "Sleeping Bag"; public const string TENT_DESCRIPTION = "A portable shelter for outdoor living. Provides basic protection from the elements."; public const string SLEEPINGBAG_DESCRIPTION = "A warm sleeping bag for rough nights on the streets."; public const string CATEGORY = "Survival Gear"; public const int TENT_PRICE = 150; public const int SLEEPINGBAG_PRICE = 75; public const ushort TENT_PREFAB_ID = 9001; public const ushort SLEEPINGBAG_PREFAB_ID = 9002; public const string TENT_ICON_PATH = "SidewalkEconomy.Icons.tent.png"; public const string SLEEPINGBAG_ICON_PATH = "SidewalkEconomy.Icons.sleepingbag.png"; } public static class WorldSpawns { public const string SLEEPING_BAG_SPAWN_NAME = "SidewalkEconomy_SleepingBag_Spawn"; public const string TENT_SPAWN_NAME = "SidewalkEconomy_Tent_Spawn"; public const string TENT_STORAGE_ANCHOR_NAME = "SidewalkEconomy_TentStorage"; public static readonly Vector3 SLEEPING_BAG_POSITION = new Vector3(-90.5f, -3.85f, 69.728f); public static readonly Vector3 SLEEPING_BAG_ROTATION_EULER = Vector3.zero; public static readonly Vector3 TENT_POSITION = new Vector3(10f, 0.65f, -76f); public static readonly Vector3 TENT_ROTATION_EULER = new Vector3(0f, 180f, 0f); public static readonly Vector3 MARCUS_RELOCATE_POSITION = new Vector3(25f, 0.65f, -60f); public static readonly Vector3 MARCUS_RELOCATE_ROTATION_EULER = new Vector3(0f, 90f, 0f); public const float TENT_ENTRANCE_ANGLE_DEGREES = 30f; public const float TENT_ENTRANCE_YAW_OFFSET_DEGREES = 20f; public static readonly Vector3 TENT_SLEEP_OFFSET = new Vector3(0f, 0.9f, 1.35f); public static readonly Vector3 TENT_SLEEP_COLLIDER_SIZE = new Vector3(1.1f, 1.4f, 0.75f); public static readonly Vector3 TENT_STORAGE_OFFSET = new Vector3(1.25f, 0f, 0f); public static readonly Vector3 TENT_STORAGE_COLLIDER_SIZE = new Vector3(0.6f, 1f, 0.6f); } public static class NPCs { public const string MARCUS_ID = "reginald_iterson"; public const string MARCUS_FIRST_NAME = "Reginald"; public const string MARCUS_LAST_NAME = "Iterson"; } public static class Quests { public const string TENT_INHERITANCE_ID = "tent_inheritance_quest"; public const string TENT_INHERITANCE_TITLE = "New Beginnings"; public const string TENT_INHERITANCE_GROW_TENT_ID = "growtent"; public const string TENT_INHERITANCE_GROW_TENT_NAME = "Grow Tent"; public const int TENT_INHERITANCE_GROW_TENT_AMOUNT = 1; public const string TENT_INHERITANCE_OG_KUSH_SEED_ID = "ogkushseed"; public const string TENT_INHERITANCE_OG_KUSH_SEED_NAME = "OG Kush Seeds"; public const int TENT_INHERITANCE_OG_KUSH_SEED_AMOUNT = 3; } } public sealed class GameTimeManager { [CompilerGenerated] private sealed class <UpdateGameTime>d__30 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public GameTimeManager <>4__this; private float <gameMinutes>5__1; private int <newGameDay>5__2; private float <dayMinutes>5__3; private int <newGameHour>5__4; private int <newGameMinute>5__5; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <UpdateGameTime>d__30(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1;
SidewalkEconomy-Mono.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
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.Versioning; using System.Security; using System.Security.Permissions; using FishNet; using FishNet.Connection; using FishNet.Managing; using FishNet.Managing.Object; using FishNet.Object; using HarmonyLib; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using S1API.AssetBundles; using S1API.Economy; using S1API.Entities; using S1API.Entities.Customer; using S1API.Entities.Relation; using S1API.GameTime; using S1API.Internal.Abstraction; using S1API.Items; using S1API.Leveling; using S1API.Map; using S1API.Map.Buildings; using S1API.Products; using S1API.Quests; using S1API.Quests.Constants; using S1API.Saveables; using ScheduleOne; using ScheduleOne.AvatarFramework; using ScheduleOne.Building; using ScheduleOne.Core.Items.Framework; using ScheduleOne.DevUtilities; using ScheduleOne.Dialogue; using ScheduleOne.Employees; using ScheduleOne.EntityFramework; using ScheduleOne.GameTime; using ScheduleOne.Heatmap; using ScheduleOne.Interaction; using ScheduleOne.ItemFramework; using ScheduleOne.Lighting; using ScheduleOne.NPCs; using ScheduleOne.ObjectScripts; using ScheduleOne.Persistence; using ScheduleOne.Persistence.Datas; using ScheduleOne.Persistence.Loaders; using ScheduleOne.PlayerScripts; using ScheduleOne.Product; using ScheduleOne.Property; using ScheduleOne.Storage; using ScheduleOne.Tiles; using ScheduleOne.UI; using ScheduleOne.UI.Management; using ScheduleOne.Variables; using SidewalkEconomy; using SidewalkEconomy.Controllers; using SidewalkEconomy.Helpers; using SidewalkEconomy.Saveables; using UnityEngine; using UnityEngine.AI; using UnityEngine.Events; 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: MelonInfo(typeof(SidewalkEconomyMod), "SidewalkEconomy", "1.0.1", "SirTidez", null)] [assembly: MelonColor(1, 0, 0, 255)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("SidewalkEconomy-Mono")] [assembly: AssemblyConfiguration("Debug Mono")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+de42324db45c550550d20429a0fc34e385f32488")] [assembly: AssemblyProduct("SidewalkEconomy-Mono")] [assembly: AssemblyTitle("SidewalkEconomy-Mono")] [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 SidewalkEconomy { public static class BuildInfo { public const string Name = "SidewalkEconomy"; public const string Description = "Allows placing buildable items anywhere on the map"; public const string Author = "SirTidez"; public const string Version = "1.0.1"; } public class SidewalkEconomyMod : MelonMod { [CompilerGenerated] private static class <>O { public static UnityAction <0>__OnGameSaveStarted; } [CompilerGenerated] private sealed class <CheckTentSpawnOnSceneLoad>d__61 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public SidewalkEconomyMod <>4__this; private int <attempts>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CheckTentSpawnOnSceneLoad>d__61(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; ModLogger.Info("CheckTentSpawnOnSceneLoad: Started waiting for tent prefab..."); <attempts>5__1 = 0; goto IL_0074; case 1: <>1__state = -1; goto IL_0074; case 2: { <>1__state = -1; ModLogger.Info($"CheckTentSpawnOnSceneLoad: Tent prefab loaded after {<attempts>5__1} attempts - performing initial level check"); <>4__this.OnDayPass(); ModLogger.Info("CheckTentSpawnOnSceneLoad: OnDayPass() called"); return false; } IL_0074: if (!EnsureTentPrefabReady(<attempts>5__1 > 0) && <attempts>5__1 < 100) { <attempts>5__1++; <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; } if (!EnsureTentPrefabReady(logReload: true)) { ModLogger.Warn("Tent prefab not loaded after waiting - cannot perform initial level check"); return false; } <>2__current = (object)new WaitForSeconds(1.5f); <>1__state = 2; return true; } } 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 <EnsureTentOwnedWhenReady>d__59 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public SidewalkEconomyMod <>4__this; private float <startTime>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <EnsureTentOwnedWhenReady>d__59(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <startTime>5__1 = Time.time; break; case 1: <>1__state = -1; break; } if (TentOwnershipSaveable.Instance == null || !TentOwnershipSaveable.Instance.IsReady) { if (Time.time - <startTime>5__1 > 10f) { ModLogger.Warn("Timed out waiting for tent ownership saveable"); return false; } <>2__current = null; <>1__state = 1; return true; } TentOwnershipManager.SetTentOwned(owned: true); ModLogger.Info("Tent ownership set to player"); 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 <LoadAssetBundleAssets>d__65 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public SidewalkEconomyMod <>4__this; private WrappedAssetBundle <bundle>5__1; private string[] <allAssetNames>5__2; private string[] <>s__3; private int <>s__4; private string <assetName>5__5; private Exception <ex>5__6; private Exception <ex>5__7; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadAssetBundleAssets>d__65(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <bundle>5__1 = null; <allAssetNames>5__2 = null; <>s__3 = null; <assetName>5__5 = null; <ex>5__6 = null; <ex>5__7 = null; <>1__state = -2; } private bool MoveNext() { if (<>1__state != 0) { return false; } <>1__state = -1; try { ModLogger.Debug("Loading assetbundle assets..."); if (CachedAssetBundle == null) { ModLogger.Debug("Loading assetbundle..."); CachedAssetBundle = AssetBundleUtils.LoadAssetBundle("SidewalkEconomy.sidewalkeconomy"); if (CachedAssetBundle == null) { ModLogger.Error("Failed to load assetbundle"); return false; } ModLogger.Debug("✓ Assetbundle loaded successfully"); } <bundle>5__1 = CachedAssetBundle; try { ModLogger.Info("=== Listing all assets in assetbundle ==="); <allAssetNames>5__2 = <bundle>5__1.GetAllAssetNames(); ModLogger.Info($"Total assets in bundle: {<allAssetNames>5__2.Length}"); <>s__3 = <allAssetNames>5__2; for (<>s__4 = 0; <>s__4 < <>s__3.Length; <>s__4++) { <assetName>5__5 = <>s__3[<>s__4]; ModLogger.Info(" - " + <assetName>5__5); <assetName>5__5 = null; } <>s__3 = null; ModLogger.Info("=== End of asset list ==="); <allAssetNames>5__2 = null; } catch (Exception ex) { <ex>5__6 = ex; ModLogger.Warn("Failed to list assets: " + <ex>5__6.Message); ModLogger.Warn("Stack trace: " + <ex>5__6.StackTrace); } ModLogger.Debug("Loading sleepingbag prefab: assets/sidewalk economy/sleepingbag.prefab"); SleepingBagPrefab = <bundle>5__1.LoadAsset<GameObject>("assets/sidewalk economy/sleepingbag.prefab"); if ((Object)(object)SleepingBagPrefab == (Object)null) { ModLogger.Warn("Failed to load sleepingbag prefab 'assets/sidewalk economy/sleepingbag.prefab' from assetbundle"); } else { ModLogger.Info("✓ Sleepingbag prefab loaded: " + ((Object)SleepingBagPrefab).name); ShaderUtils.FixShadersOnGameObject(SleepingBagPrefab); } ModLogger.Debug("Loading tent prefab: assets/sidewalk economy/tent.prefab"); TentPrefab = <bundle>5__1.LoadAsset<GameObject>("assets/sidewalk economy/tent.prefab"); if ((Object)(object)TentPrefab == (Object)null) { ModLogger.Warn("Failed to load tent prefab 'assets/sidewalk economy/tent.prefab' from assetbundle"); } else { _tentPrefabLoadedOnce = true; ModLogger.Info("✓ Tent prefab loaded: " + ((Object)TentPrefab).name); ShaderUtils.FixShadersOnGameObject(TentPrefab); } ModLogger.Info("Assetbundle assets loaded successfully"); PrefabControllerInstaller.InstallControllers(SleepingBagPrefab, TentPrefab); ModLogger.Info("Scheduling custom buildable item registration..."); MelonCoroutines.Start(ItemRegistrationManager.RegisterCustomItemsWhenReady()); ModLogger.Info("Requesting initial world spawns..."); WorldSpawnManager.SpawnInitialShelters(SleepingBagPrefab, TentPrefab); <bundle>5__1 = null; } catch (Exception ex) { <ex>5__7 = ex; ModLogger.Error("[MainMod] Failed to load assetbundle assets: " + <ex>5__7.Message); ModLogger.Error("Stack trace: " + <ex>5__7.StackTrace); } 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 <RegisterSaveListener>d__63 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; private SaveManager <saveManager>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RegisterSaveListener>d__63(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <saveManager>5__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if (!Singleton<SaveManager>.InstanceExists) { <>2__current = null; <>1__state = 1; return true; } if (_saveListenerRegistered) { return false; } <saveManager>5__1 = Singleton<SaveManager>.Instance; if ((Object)(object)<saveManager>5__1 == (Object)null) { return false; } if (_saveStartHandler == null) { object obj = <>O.<0>__OnGameSaveStarted; if (obj == null) { UnityAction val = OnGameSaveStarted; <>O.<0>__OnGameSaveStarted = val; obj = (object)val; } _saveStartHandler = (UnityAction)obj; } <saveManager>5__1.onSaveStart.AddListener(_saveStartHandler); _saveListenerRegistered = true; ModLogger.Debug("Registered outside buildable save listener"); 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 <SubscribeToDayPassEvent>d__60 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public SidewalkEconomyMod <>4__this; private Exception <ex>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SubscribeToDayPassEvent>d__60(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <ex>5__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (_dayPassEventSubscribed) { return false; } <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 2; return true; case 2: <>1__state = -1; try { ModLogger.Debug("Subscribing to S1API TimeManager.OnDayPass event"); TimeManager.OnDayPass = (Action)Delegate.Combine(TimeManager.OnDayPass, new Action(<>4__this.OnDayPass)); _dayPassEventSubscribed = true; ModLogger.Info("Subscribed to day pass event - tent will spawn when player reaches Peddler rank"); } catch (Exception ex) { <ex>5__1 = ex; ModLogger.Error("Failed to subscribe to day pass event: " + <ex>5__1.Message); ModLogger.Error("Stack trace: " + <ex>5__1.StackTrace); } 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(); } } private const float SyntheticPropertyRenameDistance = 30f; private const int SyntheticPropertyNameMaxLength = 48; private const float SyntheticIdleEditDistance = 40f; private const float SyntheticIdleYawStep = 5f; private static Harmony HarmonyInstance; private static bool _tentSpawned; private static bool _tentPrefabLoadedOnce; private static bool _dayPassEventSubscribed; private static bool _saveListenerRegistered; private static UnityAction _saveStartHandler; private bool _showSyntheticPropertyRenameWindow; private bool _focusSyntheticPropertyNameInput; private string _syntheticPropertyNameInput = string.Empty; private string _syntheticPropertyRenameError = string.Empty; private Rect _syntheticPropertyRenameWindowRect = new Rect(24f, 24f, 420f, 180f); private Property _selectedSyntheticProperty; private bool _isSyntheticIdleEditMode; private Property _syntheticIdleEditProperty; private Vector3 _syntheticIdleEditPosition; private float _syntheticIdleEditYaw; private bool _syntheticIdleEditValid; private string _syntheticIdleEditStatus = string.Empty; private GameObject _syntheticIdleEditGizmo; private Renderer _syntheticIdleEditGizmoBaseRenderer; private Renderer _syntheticIdleEditGizmoArrowRenderer; public static WrappedAssetBundle? CachedAssetBundle { get; private set; } public static GameObject? SleepingBagPrefab { get; private set; } public static GameObject? TentPrefab { get; private set; } public override void OnInitializeMelon() { //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown ModSettings.Initialize(); ModLogger.SetDebugEnabled(ModSettings.EnableDebugLogging); GameTimeManager.Instance.Initialize(); ModLogger.Info("Build-anywhere systems initialized"); new TentOwnershipSaveable(); new TentStorageSaveable(); SyntheticGridSaveable syntheticGridSaveable = new SyntheticGridSaveable(); OutsideBuildablesSaveable outsideBuildablesSaveable = new OutsideBuildablesSaveable(); SyntheticGridManager.Initialize(); if (_saveStartHandler == null) { object obj = <>O.<0>__OnGameSaveStarted; if (obj == null) { UnityAction val = OnGameSaveStarted; <>O.<0>__OnGameSaveStarted = val; obj = (object)val; } _saveStartHandler = (UnityAction)obj; } ModLogger.Info("SidewalkEconomy initialized"); ModLogger.Debug("This will only show in debug mode"); ModLogger.Debug($"[MainMod] EnableOutsidePlacement: {ModSettings.EnableOutsidePlacement}"); ModLogger.Debug($"[MainMod] EnableDebugLogging: {ModSettings.EnableDebugLogging}"); HarmonyInstance = new Harmony("SidewalkEconomy"); ModLogger.Debug("[MainMod] Applying Harmony patches..."); ModLogger.Debug("[MainMod] Patching BuildUpdate_Grid.CheckIntersections"); HarmonyInstance.PatchAll(); ModLogger.Debug("Harmony patches applied"); try { MethodInfo method = typeof(BuildUpdate_Grid).GetMethod("CheckIntersections", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); ModLogger.Debug($"[MainMod] CheckIntersections method found: {method != null}"); if (!(method != null)) { return; } Patches patchInfo = Harmony.GetPatchInfo((MethodBase)method); ModLogger.Debug($"[MainMod] CheckIntersections patches: {(patchInfo?.Postfixes?.Count).GetValueOrDefault()} postfix(es)"); if (patchInfo?.Postfixes == null || patchInfo.Postfixes.Count <= 0) { return; } foreach (Patch postfix in patchInfo.Postfixes) { ModLogger.Debug("[MainMod] - Postfix: " + postfix.owner); } } catch (Exception arg) { ModLogger.Warn($"[MainMod] Error verifying patches: {arg}"); } } public override void OnDeinitializeMelon() { ExitSyntheticIdleEditMode(); if (_saveListenerRegistered && Singleton<SaveManager>.InstanceExists) { try { if (_saveStartHandler != null) { Singleton<SaveManager>.Instance.onSaveStart.RemoveListener(_saveStartHandler); } _saveListenerRegistered = false; ModLogger.Debug("Unregistered outside buildable save listener"); } catch (Exception ex) { ModLogger.Warn("Failed to unregister save listener: " + ex.Message); } } if (_dayPassEventSubscribed) { try { TimeManager.OnDayPass = (Action)Delegate.Remove(TimeManager.OnDayPass, new Action(OnDayPass)); _dayPassEventSubscribed = false; ModLogger.Debug("Unsubscribed from S1API TimeManager day pass event"); } catch (Exception ex2) { ModLogger.Debug("Failed to unsubscribe from day pass event: " + ex2.Message); } } Harmony harmonyInstance = HarmonyInstance; if (harmonyInstance != null) { harmonyInstance.UnpatchSelf(); } ModLogger.Debug("Harmony patches removed"); GameTimeManager.Instance.Shutdown(); } public override void OnUpdate() { HandleSyntheticIdleEditHotkey(); UpdateSyntheticIdleEditMode(); HandleSyntheticPropertyRenameHotkey(); } public override void OnGUI() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (_isSyntheticIdleEditMode) { DrawSyntheticIdleEditOverlay(); } if (_showSyntheticPropertyRenameWindow) { GUILayout.BeginArea(_syntheticPropertyRenameWindowRect, "Rename Synthetic Property", GUI.skin.window); DrawSyntheticPropertyRenameWindowContents(); GUILayout.EndArea(); } } private void HandleTeleportHotkeys() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown((KeyCode)91)) { TeleportPlayer(Constants.WorldSpawns.TENT_POSITION, "Tent"); } if (Input.GetKeyDown((KeyCode)112)) { TeleportPlayer(Constants.WorldSpawns.SLEEPING_BAG_POSITION, "Sleeping Bag"); } } private void HandleSyntheticPropertyRenameHotkey() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) if (!ModSettings.EnableOutsidePlacement || _showSyntheticPropertyRenameWindow || _isSyntheticIdleEditMode || !IsAltHeld() || !Input.GetKeyDown((KeyCode)114)) { return; } Player local = Player.Local; if ((Object)(object)local == (Object)null) { ModLogger.Warn("Cannot rename synthetic property: player not found"); return; } Property nearestSyntheticProperty = SyntheticGridManager.GetNearestSyntheticProperty(((Component)local).transform.position, 30f); if ((Object)(object)nearestSyntheticProperty == (Object)null) { ModLogger.Warn("No synthetic property found nearby. Move closer and press Alt+R."); return; } _selectedSyntheticProperty = nearestSyntheticProperty; _syntheticPropertyNameInput = nearestSyntheticProperty.PropertyName ?? string.Empty; _syntheticPropertyRenameError = string.Empty; _showSyntheticPropertyRenameWindow = true; _focusSyntheticPropertyNameInput = true; } private void DrawSyntheticPropertyRenameWindowContents() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Invalid comparison between Unknown and I4 //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Invalid comparison between Unknown and I4 Event current = Event.current; if ((int)current.type == 4) { if ((int)current.keyCode == 27) { CloseSyntheticPropertyRenameWindow(); current.Use(); return; } if ((int)current.keyCode == 13 || (int)current.keyCode == 271) { ApplySyntheticPropertyRename(); current.Use(); return; } } GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); GUILayout.Label("Set a custom name for this synthetic property.", Array.Empty<GUILayoutOption>()); GUILayout.Label("This name is used internally for save data and troubleshooting.", Array.Empty<GUILayoutOption>()); GUILayout.Space(6f); GUI.SetNextControlName("SyntheticPropertyNameInput"); _syntheticPropertyNameInput = GUILayout.TextField(_syntheticPropertyNameInput ?? string.Empty, 48, Array.Empty<GUILayoutOption>()); if (_focusSyntheticPropertyNameInput) { GUI.FocusControl("SyntheticPropertyNameInput"); _focusSyntheticPropertyNameInput = false; } if (!string.IsNullOrWhiteSpace(_syntheticPropertyRenameError)) { GUILayout.Label(_syntheticPropertyRenameError, Array.Empty<GUILayoutOption>()); } GUILayout.FlexibleSpace(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Save", Array.Empty<GUILayoutOption>())) { ApplySyntheticPropertyRename(); } if (GUILayout.Button("Cancel", Array.Empty<GUILayoutOption>())) { CloseSyntheticPropertyRenameWindow(); } GUILayout.EndHorizontal(); GUILayout.EndVertical(); } private void ApplySyntheticPropertyRename() { if ((Object)(object)_selectedSyntheticProperty == (Object)null) { _syntheticPropertyRenameError = "No synthetic property selected."; return; } string text = (_syntheticPropertyNameInput ?? string.Empty).Trim(); if (string.IsNullOrWhiteSpace(text)) { _syntheticPropertyRenameError = "Property name cannot be empty."; return; } if (!SyntheticGridManager.TryRenameSyntheticProperty(_selectedSyntheticProperty, text, out var failureReason)) { _syntheticPropertyRenameError = (string.IsNullOrWhiteSpace(failureReason) ? "Failed to rename synthetic property." : failureReason); return; } ModLogger.Info("Renamed synthetic property to '" + text + "'"); CloseSyntheticPropertyRenameWindow(); } private void CloseSyntheticPropertyRenameWindow() { _showSyntheticPropertyRenameWindow = false; _focusSyntheticPropertyNameInput = false; _syntheticPropertyRenameError = string.Empty; _selectedSyntheticProperty = null; } private void HandleSyntheticIdleEditHotkey() { if (!SyntheticGridManager.AreSyntheticEmployeesEnabled()) { if (_isSyntheticIdleEditMode) { ExitSyntheticIdleEditMode(); } if (IsAltHeld() && Input.GetKeyDown((KeyCode)105)) { ModLogger.Warn("Synthetic property employees are disabled in this version."); } } else if (ModSettings.EnableOutsidePlacement && !_showSyntheticPropertyRenameWindow && IsAltHeld() && Input.GetKeyDown((KeyCode)105)) { if (_isSyntheticIdleEditMode) { ExitSyntheticIdleEditMode(); } else { EnterSyntheticIdleEditMode(); } } } private void EnterSyntheticIdleEditMode() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) if (!SyntheticGridManager.AreSyntheticEmployeesEnabled()) { return; } Player local = Player.Local; if ((Object)(object)local == (Object)null) { ModLogger.Warn("Cannot enter synthetic idle edit mode: player not found"); return; } Property nearestSyntheticProperty = SyntheticGridManager.GetNearestSyntheticProperty(((Component)local).transform.position, 40f); if ((Object)(object)nearestSyntheticProperty == (Object)null) { ModLogger.Warn("No synthetic property found nearby. Move closer and press Alt+I."); return; } _syntheticIdleEditProperty = nearestSyntheticProperty; if (!SyntheticGridManager.TryGetManualIdlePoint(nearestSyntheticProperty, out _syntheticIdleEditPosition, out _syntheticIdleEditYaw)) { _syntheticIdleEditPosition = (((Object)(object)nearestSyntheticProperty.NPCSpawnPoint != (Object)null) ? nearestSyntheticProperty.NPCSpawnPoint.position : ((Component)local).transform.position); _syntheticIdleEditYaw = ((Component)local).transform.eulerAngles.y; } _isSyntheticIdleEditMode = true; _syntheticIdleEditStatus = "Idle edit mode active."; EnsureSyntheticIdleEditGizmo(); UpdateSyntheticIdleEditGizmo(); } private void ExitSyntheticIdleEditMode() { _isSyntheticIdleEditMode = false; _syntheticIdleEditProperty = null; _syntheticIdleEditStatus = string.Empty; if ((Object)(object)_syntheticIdleEditGizmo != (Object)null) { Object.Destroy((Object)(object)_syntheticIdleEditGizmo); _syntheticIdleEditGizmo = null; _syntheticIdleEditGizmoBaseRenderer = null; _syntheticIdleEditGizmoArrowRenderer = null; } } private void UpdateSyntheticIdleEditMode() { //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) if (!SyntheticGridManager.AreSyntheticEmployeesEnabled()) { if (_isSyntheticIdleEditMode) { ExitSyntheticIdleEditMode(); } } else { if (!_isSyntheticIdleEditMode) { return; } if ((Object)(object)_syntheticIdleEditProperty == (Object)null) { ExitSyntheticIdleEditMode(); return; } if (Input.GetKeyDown((KeyCode)27)) { ExitSyntheticIdleEditMode(); return; } bool flag = false; if (Input.GetKeyDown((KeyCode)113)) { _syntheticIdleEditYaw -= 5f; flag = true; } if (Input.GetKeyDown((KeyCode)101)) { _syntheticIdleEditYaw += 5f; flag = true; } if (Input.GetMouseButtonDown(0) && TryGetIdleEditAimPoint(out var point)) { _syntheticIdleEditPosition = point; flag = true; } if (Input.GetKeyDown((KeyCode)8) || Input.GetKeyDown((KeyCode)127)) { SyntheticGridManager.ClearManualIdlePoint(_syntheticIdleEditProperty); _syntheticIdleEditStatus = "Cleared manual idle marker. Hiring is now disabled until a marker is placed."; UpdateSyntheticIdleEditGizmo(); return; } if (flag) { if (SyntheticGridManager.TrySetManualIdlePoint(_syntheticIdleEditProperty, _syntheticIdleEditPosition, _syntheticIdleEditYaw, out var failureReason)) { _syntheticIdleEditStatus = "Idle marker updated."; } else { _syntheticIdleEditStatus = (string.IsNullOrWhiteSpace(failureReason) ? "Idle marker is invalid. Move it to clear navmesh." : failureReason); } } UpdateSyntheticIdleEditGizmo(); } } private bool TryGetIdleEditAimPoint(out Vector3 point) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) point = Vector3.zero; Camera main = Camera.main; if ((Object)(object)main == (Object)null) { return false; } Ray val = main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0f)); RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val, ref val2, 500f, -1, (QueryTriggerInteraction)1)) { point = ((RaycastHit)(ref val2)).point; return true; } point = ((Component)main).transform.position + ((Component)main).transform.forward * 4f; return true; } private void EnsureSyntheticIdleEditGizmo() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_syntheticIdleEditGizmo != (Object)null)) { _syntheticIdleEditGizmo = new GameObject("SyntheticIdleEditGizmo"); GameObject val = GameObject.CreatePrimitive((PrimitiveType)2); ((Object)val).name = "Base"; val.transform.SetParent(_syntheticIdleEditGizmo.transform, false); val.transform.localScale = new Vector3(0.35f, 0.05f, 0.35f); val.transform.localPosition = Vector3.zero; _syntheticIdleEditGizmoBaseRenderer = val.GetComponent<Renderer>(); Collider component = val.GetComponent<Collider>(); if ((Object)(object)component != (Object)null) { component.enabled = false; } GameObject val2 = GameObject.CreatePrimitive((PrimitiveType)3); ((Object)val2).name = "Forward"; val2.transform.SetParent(_syntheticIdleEditGizmo.transform, false); val2.transform.localScale = new Vector3(0.08f, 0.08f, 0.5f); val2.transform.localPosition = new Vector3(0f, 0.1f, 0.25f); _syntheticIdleEditGizmoArrowRenderer = val2.GetComponent<Renderer>(); Collider component2 = val2.GetComponent<Collider>(); if ((Object)(object)component2 != (Object)null) { component2.enabled = false; } } } private void UpdateSyntheticIdleEditGizmo() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) if (!_isSyntheticIdleEditMode || (Object)(object)_syntheticIdleEditProperty == (Object)null) { return; } EnsureSyntheticIdleEditGizmo(); if ((Object)(object)_syntheticIdleEditGizmo == (Object)null) { return; } _syntheticIdleEditYaw = Mathf.Repeat(_syntheticIdleEditYaw, 360f); if (SyntheticGridManager.TryValidateEmployeeIdlePoint(_syntheticIdleEditProperty, _syntheticIdleEditPosition, out var resolvedPosition, out var failureReason)) { _syntheticIdleEditValid = true; _syntheticIdleEditPosition = resolvedPosition; if (string.IsNullOrWhiteSpace(_syntheticIdleEditStatus) || _syntheticIdleEditStatus.Contains("invalid", StringComparison.OrdinalIgnoreCase)) { _syntheticIdleEditStatus = "Idle marker is valid."; } } else { _syntheticIdleEditValid = false; if (!string.IsNullOrWhiteSpace(failureReason)) { _syntheticIdleEditStatus = failureReason; } } _syntheticIdleEditGizmo.transform.position = _syntheticIdleEditPosition + Vector3.up * 0.03f; _syntheticIdleEditGizmo.transform.rotation = Quaternion.Euler(0f, _syntheticIdleEditYaw, 0f); Color color = (_syntheticIdleEditValid ? new Color(0.2f, 0.9f, 0.3f, 0.95f) : new Color(0.95f, 0.25f, 0.25f, 0.95f)); if ((Object)(object)_syntheticIdleEditGizmoBaseRenderer != (Object)null) { _syntheticIdleEditGizmoBaseRenderer.material.color = color; } if ((Object)(object)_syntheticIdleEditGizmoArrowRenderer != (Object)null) { _syntheticIdleEditGizmoArrowRenderer.material.color = color; } } private void DrawSyntheticIdleEditOverlay() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (SyntheticGridManager.AreSyntheticEmployeesEnabled() && _isSyntheticIdleEditMode && !((Object)(object)_syntheticIdleEditProperty == (Object)null)) { GUILayout.BeginArea(new Rect(24f, 214f, 520f, 150f), "Synthetic Idle Edit", GUI.skin.window); GUILayout.Label("Property: " + _syntheticIdleEditProperty.PropertyName, Array.Empty<GUILayoutOption>()); GUILayout.Label($"Point: {_syntheticIdleEditPosition.x:F2}, {_syntheticIdleEditPosition.y:F2}, {_syntheticIdleEditPosition.z:F2} | Yaw: {_syntheticIdleEditYaw:F1}", Array.Empty<GUILayoutOption>()); GUILayout.Label(_syntheticIdleEditValid ? "Status: Valid" : "Status: Invalid", Array.Empty<GUILayoutOption>()); if (!string.IsNullOrWhiteSpace(_syntheticIdleEditStatus)) { GUILayout.Label(_syntheticIdleEditStatus, Array.Empty<GUILayoutOption>()); } GUILayout.Label("Controls: LMB place marker | Q/E rotate | Delete clear | Alt+I or Esc exit", Array.Empty<GUILayoutOption>()); GUILayout.EndArea(); } } private static bool IsAltHeld() { return Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307); } private void TeleportPlayer(Vector3 position, string label) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) Player local = Player.Local; if ((Object)(object)local == (Object)null) { ModLogger.Warn("Teleport skipped - player not found (" + label + ")"); return; } ((Component)local).transform.position = position; ModLogger.Info($"Teleported player to {label} at {position}"); } private void OnDayPass() { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Invalid comparison between Unknown and I4 //IL_0084: Unknown result type (might be due to invalid IL or missing references) ModLogger.Info("OnDayPass: Called"); try { if (_tentSpawned && !IsTentPresent()) { _tentSpawned = false; ModLogger.Warn("Tent spawn flag was set but tent is missing in scene. Retrying spawn."); } if (_tentSpawned) { ModLogger.Debug("OnDayPass: Tent already spawned, skipping"); return; } if (!EnsureTentPrefabReady(logReload: true)) { ModLogger.Debug("OnDayPass: Tent prefab not loaded yet"); return; } Rank rank = LevelManager.Rank; if ((int)rank >= 2) { ModLogger.Info($"Player reached {rank} - spawning tent!"); if (WorldSpawnManager.SpawnTent(TentPrefab)) { EnsureTentOwned(); _tentSpawned = true; } else { ModLogger.Warn("Tent spawn attempt did not succeed; will retry on next trigger."); } } } catch (Exception ex) { ModLogger.Error("OnDayPass error: " + ex.Message); } } private static bool IsTentPresent() { return (Object)(object)GameObject.Find("SidewalkEconomy_Tent_Spawn") != (Object)null; } private void EnsureTentOwned() { if (!TentOwnershipManager.IsTentOwned()) { TentOwnershipManager.SetTentOwned(owned: true); if (!TentOwnershipManager.IsTentOwned()) { MelonCoroutines.Start(EnsureTentOwnedWhenReady()); } else { ModLogger.Info("Tent ownership set to player"); } } } [IteratorStateMachine(typeof(<EnsureTentOwnedWhenReady>d__59))] private IEnumerator EnsureTentOwnedWhenReady() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <EnsureTentOwnedWhenReady>d__59(0) { <>4__this = this }; } [IteratorStateMachine(typeof(<SubscribeToDayPassEvent>d__60))] private IEnumerator SubscribeToDayPassEvent() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SubscribeToDayPassEvent>d__60(0) { <>4__this = this }; } [IteratorStateMachine(typeof(<CheckTentSpawnOnSceneLoad>d__61))] private IEnumerator CheckTentSpawnOnSceneLoad() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <CheckTentSpawnOnSceneLoad>d__61(0) { <>4__this = this }; } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { ExitSyntheticIdleEditMode(); ModLogger.Debug("Scene loaded: " + sceneName); if (sceneName == "Main") { _tentSpawned = IsTentPresent(); ModLogger.Debug($"Tent present on scene load: {_tentSpawned}"); ModLogger.Debug("Main scene loaded"); MelonCoroutines.Start(LoadAssetBundleAssets()); MelonCoroutines.Start(SubscribeToDayPassEvent()); MelonCoroutines.Start(Utils.WaitForNetwork(CheckTentSpawnOnSceneLoad())); MelonCoroutines.Start(RegisterSaveListener()); } } [IteratorStateMachine(typeof(<RegisterSaveListener>d__63))] private static IEnumerator RegisterSaveListener() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <RegisterSaveListener>d__63(0); } private static void OnGameSaveStarted() { if (OutsideBuildablesSaveable.Instance == null) { ModLogger.Warn("Outside buildables saveable not ready; skipping capture"); } else { OutsideBuildablesSaveable.Instance.CaptureFromWorld(); } SyntheticGridManager.CaptureForSave(); TentStorageEntity.FlushAllForSave(); } [IteratorStateMachine(typeof(<LoadAssetBundleAssets>d__65))] private IEnumerator LoadAssetBundleAssets() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadAssetBundleAssets>d__65(0) { <>4__this = this }; } private static bool EnsureTentPrefabReady(bool logReload) { if ((Object)(object)TentPrefab != (Object)null) { return true; } if (CachedAssetBundle == null || !_tentPrefabLoadedOnce) { return false; } try { TentPrefab = CachedAssetBundle.LoadAsset<GameObject>("assets/sidewalk economy/tent.prefab"); if ((Object)(object)TentPrefab != (Object)null) { if (logReload) { ModLogger.Debug("Rehydrated tent prefab reference from cached assetbundle"); } ShaderUtils.FixShadersOnGameObject(TentPrefab); return true; } } catch (Exception ex) { if (logReload) { ModLogger.Warn("Failed to rehydrate tent prefab from cached assetbundle: " + ex.Message); } } return false; } } public static class ModSettings { private static MelonPreferences_Category _category; private static MelonPreferences_Entry<bool> _enableDebugLogging; private static MelonPreferences_Entry<bool> _enableOutsidePlacement; public static bool EnableDebugLogging { get { return _enableDebugLogging?.Value ?? false; } set { if (_enableDebugLogging != null) { _enableDebugLogging.Value = value; MelonPreferences.Save(); } } } public static bool EnableOutsidePlacement { get { return _enableOutsidePlacement?.Value ?? true; } set { if (_enableOutsidePlacement != null) { _enableOutsidePlacement.Value = value; MelonPreferences.Save(); } } } public static void Initialize() { _category = MelonPreferences.CreateCategory("SidewalkEconomy", "SidewalkEconomy"); _enableDebugLogging = _category.CreateEntry<bool>("EnableDebugLogging", false, "Enable Debug Logging", "When enabled, detailed debug messages will be logged to the console.", false, false, (ValueValidator)null, (string)null); _enableOutsidePlacement = _category.CreateEntry<bool>("EnableOutsidePlacement", true, "Enable Outside Placement", "Enables or disables the ability to place buildable items anywhere on the map. When enabled, players can place items outside of approved building zones.", false, false, (ValueValidator)null, (string)null); MelonPreferences.Save(); } } } namespace SidewalkEconomy.Saveables { public sealed class OutsideBuildablesSaveable : Saveable { private sealed class OutsideBuildableRecordWithOrder { public OutsideBuildableRecord Record { get; set; } public int LoadOrder { get; set; } } private sealed class PendingRestoreRecord { public OutsideBuildableRecord Record { get; set; } public int SourceIndex { get; set; } public int Attempts { get; set; } public string LastDeferredReason { get; set; } } private enum RestoreOutcome { Restored, Deferred, PermanentFailure } private enum BuildableCaptureState { Valid, Transient, Invalid } [CompilerGenerated] private sealed class <RestoreRoutine>d__15 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public OutsideBuildablesSaveable <>4__this; private LoadManager <loadManager>5__1; private List<PendingRestoreRecord> <pending>5__2; private int <restoredCount>5__3; private int <permanentlyFailedCount>5__4; private int <pass>5__5; private bool <restoredAnyThisPass>5__6; private int <passCount>5__7; private List<PendingRestoreRecord> <nextPending>5__8; private List<PendingRestoreRecord>.Enumerator <>s__9; private PendingRestoreRecord <pendingRecord>5__10; private RestoreOutcome <outcome>5__11; private string <reason>5__12; private RestoreOutcome <>s__13; private List<PendingRestoreRecord>.Enumerator <>s__14; private PendingRestoreRecord <pendingRecord>5__15; private string <reason>5__16; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RestoreRoutine>d__15(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 4) { try { } finally { <>m__Finally1(); } } <loadManager>5__1 = null; <pending>5__2 = null; <nextPending>5__8 = null; <>s__9 = default(List<PendingRestoreRecord>.Enumerator); <pendingRecord>5__10 = null; <reason>5__12 = null; <>s__14 = default(List<PendingRestoreRecord>.Enumerator); <pendingRecord>5__15 = null; <reason>5__16 = null; <>1__state = -2; } private bool MoveNext() { //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_03ed: Unknown result type (might be due to invalid IL or missing references) //IL_03f7: Expected O, but got Unknown try { Scene activeScene; switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (!InstanceFinder.IsServer) { ModLogger.Debug("Outside buildable restore skipped - not server"); return false; } goto IL_008d; case 1: <>1__state = -1; goto IL_008d; case 2: <>1__state = -1; goto IL_00c9; case 3: <>1__state = -1; goto IL_00f7; case 4: <>1__state = -3; <reason>5__12 = null; <pendingRecord>5__10 = null; goto IL_037f; case 5: { <>1__state = -1; goto IL_040d; } IL_0427: if (<pass>5__5 > 6 || <pending>5__2.Count <= 0) { break; } <restoredAnyThisPass>5__6 = false; <passCount>5__7 = <pending>5__2.Count; <nextPending>5__8 = new List<PendingRestoreRecord>(); ModLogger.Info((<pass>5__5 == 1) ? $"Restoring {<passCount>5__7} outside buildable(s)..." : $"Retrying {<passCount>5__7} deferred outside buildable restore(s) (pass {<pass>5__5}/{6})"); <>s__9 = <pending>5__2.GetEnumerator(); <>1__state = -3; goto IL_037f; IL_008d: activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).name != "Main") { <>2__current = null; <>1__state = 1; return true; } goto IL_00c9; IL_00c9: if (!NetworkSingleton<GameManager>.InstanceExists) { <>2__current = null; <>1__state = 2; return true; } goto IL_00f7; IL_00f7: if ((Object)(object)Singleton<LoadManager>.Instance == (Object)null) { <>2__current = null; <>1__state = 3; return true; } <loadManager>5__1 = Singleton<LoadManager>.Instance; <pending>5__2 = <>4__this._records.Select((OutsideBuildableRecord record, int index) => new PendingRestoreRecord { Record = record, SourceIndex = index + 1 }).ToList(); <restoredCount>5__3 = 0; <permanentlyFailedCount>5__4 = 0; <pass>5__5 = 1; goto IL_0427; IL_040d: <nextPending>5__8 = null; <pass>5__5++; goto IL_0427; IL_037f: if (<>s__9.MoveNext()) { <pendingRecord>5__10 = <>s__9.Current; <pendingRecord>5__10.Attempts++; <outcome>5__11 = TryRestoreRecord(<loadManager>5__1, <pendingRecord>5__10, out <reason>5__12); RestoreOutcome restoreOutcome = <outcome>5__11; <>s__13 = restoreOutcome; switch (<>s__13) { case RestoreOutcome.Restored: <restoredAnyThisPass>5__6 = true; <restoredCount>5__3++; break; case RestoreOutcome.Deferred: if (!string.Equals(<pendingRecord>5__10.LastDeferredReason, <reason>5__12, StringComparison.Ordinal)) { ModLogger.Warn("Deferring restore for " + DescribeRecord(<pendingRecord>5__10.Record, <pendingRecord>5__10.SourceIndex) + ": " + <reason>5__12); <pendingRecord>5__10.LastDeferredReason = <reason>5__12; } <nextPending>5__8.Add(<pendingRecord>5__10); break; case RestoreOutcome.PermanentFailure: <permanentlyFailedCount>5__4++; ModLogger.Warn("Failed to restore " + DescribeRecord(<pendingRecord>5__10.Record, <pendingRecord>5__10.SourceIndex) + ": " + <reason>5__12); break; } <>2__current = null; <>1__state = 4; return true; } <>m__Finally1(); <>s__9 = default(List<PendingRestoreRecord>.Enumerator); <pending>5__2 = <nextPending>5__8; if (<pending>5__2.Count == 0) { break; } if (<pass>5__5 < 6) { <>2__current = (object)new WaitForSeconds(<restoredAnyThisPass>5__6 ? 0.25f : 1f); <>1__state = 5; return true; } goto IL_040d; } <>s__14 = <pending>5__2.GetEnumerator(); try { while (<>s__14.MoveNext()) { <pendingRecord>5__15 = <>s__14.Current; <permanentlyFailedCount>5__4++; <reason>5__16 = (string.IsNullOrWhiteSpace(<pendingRecord>5__15.LastDeferredReason) ? "dependencies never reached a ready state" : <pendingRecord>5__15.LastDeferredReason); ModLogger.Warn($"Giving up on deferred restore for {DescribeRecord(<pendingRecord>5__15.Record, <pendingRecord>5__15.SourceIndex)} after {<pendingRecord>5__15.Attempts} attempt(s): {<reason>5__16}"); <reason>5__16 = null; <pendingRecord>5__15 = null; } } finally { ((IDisposable)<>s__14).Dispose(); } <>s__14 = default(List<PendingRestoreRecord>.Enumerator); ModLogger.Info($"Outside buildables restore complete ({<restoredCount>5__3} restored, {<permanentlyFailedCount>5__4} unresolved)"); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>s__9).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const int RestoreRetryAttempts = 3; private const int MaxDeferredRestorePasses = 6; private const float DeferredRestoreRetryDelaySeconds = 1f; [SaveableField("outside_buildables")] private List<OutsideBuildableRecord> _records = new List<OutsideBuildableRecord>(); public static OutsideBuildablesSaveable Instance { get; private set; } public override SaveableLoadOrder LoadOrder => (SaveableLoadOrder)1; public OutsideBuildablesSaveable() { Instance = this; } public IReadOnlyList<OutsideBuildableRecord> GetRecords() { return _records; } public void SetRecords(List<OutsideBuildableRecord> records) { _records = records ?? new List<OutsideBuildableRecord>(); } public void CaptureFromWorld() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (!InstanceFinder.IsServer) { ModLogger.Debug("Outside buildable capture skipped - not server"); return; } Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).name != "Main") { ModLogger.Debug("Outside buildable capture skipped - not in Main scene"); return; } List<OutsideBuildableRecord> list = CloneRecords(_records); int num = 0; int num2 = 0; foreach (Property item in Property.Properties.AsEnumerable()) { if ((Object)(object)item == (Object)null || (Object)(object)InjectedComponentHelper.GetInjectedComponent<SyntheticPropertyMarker>((Component)(object)item) == (Object)null) { continue; } if (!TryGetPropertyGridGuids(item, out var gridGuids)) { ModLogger.Warn("Preserving outside buildable snapshot for property '" + item.PropertyCode + "' because no grid GUIDs were available"); num2++; continue; } List<BuildableItem> list2 = new List<BuildableItem>(); List<OutsideBuildableRecordWithOrder> list3 = new List<OutsideBuildableRecordWithOrder>(); string text = string.Empty; foreach (BuildableItem item2 in item.BuildableItems.AsEnumerable().ToList()) { string reason; bool pruneFromProperty; switch (EvaluateBuildableCaptureState(item, item2, out reason, out pruneFromProperty)) { case BuildableCaptureState.Transient: text = reason; break; case BuildableCaptureState.Invalid: ModLogger.Warn("Skipping outside buildable capture for " + DescribeBuildable(item2) + ": " + reason); if (pruneFromProperty && (Object)(object)item2 != (Object)null) { list2.Add(item2); } continue; default: { DynamicSaveData val = null; try { val = item2.GetSaveData(); } catch (Exception ex) { text = "save data capture failed for " + DescribeBuildable(item2) + ": " + ex.Message; break; } if (val == null) { text = "save data was null for " + DescribeBuildable(item2); break; } OutsideBuildableRecord record2 = CreateRecord(val); list3.Add(new OutsideBuildableRecordWithOrder { Record = record2, LoadOrder = GetLoadOrder(val.BaseData) }); continue; } } break; } if (!string.IsNullOrWhiteSpace(text)) { ModLogger.Warn("Preserving outside buildable snapshot for property '" + item.PropertyCode + "' because " + text); num2++; continue; } RemoveRecordsForGridGuids(list, gridGuids); list.AddRange(from item in list3 orderby item.LoadOrder select item.Record); num++; PruneInvalidBuildables(item, list2); } _records = list.OrderBy((OutsideBuildableRecord record) => GetLoadOrder(record?.BaseData)).ToList(); ModLogger.Info($"Captured {_records.Count} outside buildable(s) for save across {num} stable property snapshot(s); preserved {num2} property snapshot(s)"); } protected override void OnLoaded() { ModLogger.Info($"Outside buildables loaded ({_records?.Count ?? 0} record(s))"); if (_records != null && _records.Count != 0) { MelonCoroutines.Start(Utils.WaitForPlayer(RestoreRoutine())); } } [IteratorStateMachine(typeof(<RestoreRoutine>d__15))] private IEnumerator RestoreRoutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <RestoreRoutine>d__15(0) { <>4__this = this }; } private static DynamicSaveData BuildDynamicSaveData(OutsideBuildableRecord record) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown DynamicSaveData val = new DynamicSaveData(new SaveData()) { DataType = (record.DataType ?? string.Empty), BaseData = (record.BaseData ?? string.Empty) }; val.AdditionalDatas.Clear(); if (record.AdditionalDatas != null) { foreach (AdditionalDataRecord additionalData in record.AdditionalDatas) { if (additionalData != null) { val.AdditionalDatas.Add(new AdditionalData { Name = (additionalData.Name ?? string.Empty), Contents = (additionalData.Contents ?? string.Empty) }); } } } return val; } private static OutsideBuildableRecord CreateRecord(DynamicSaveData saveData) { return new OutsideBuildableRecord { DataType = ((SaveData)saveData).DataType, BaseData = saveData.BaseData, AdditionalDatas = ConvertAdditionalDatas(saveData.AdditionalDatas.AsEnumerable()) }; } private static List<AdditionalDataRecord> ConvertAdditionalDatas(IEnumerable<AdditionalData> additionalDatas) { List<AdditionalDataRecord> list = new List<AdditionalDataRecord>(); if (additionalDatas == null) { return list; } foreach (AdditionalData additionalData in additionalDatas) { if (additionalData != null) { list.Add(new AdditionalDataRecord { Name = (additionalData.Name ?? string.Empty), Contents = (additionalData.Contents ?? string.Empty) }); } } return list; } private static bool TryGetGridGuid(string baseDataJson, out Guid guid) { guid = default(Guid); if (string.IsNullOrEmpty(baseDataJson)) { return false; } try { GridItemData val = JsonUtility.FromJson<GridItemData>(baseDataJson); if (val != null && !string.IsNullOrEmpty(val.GridGUID) && Guid.TryParse(val.GridGUID, out guid)) { return true; } } catch (Exception arg) { ModLogger.Warn($"Failed to read grid GUID from base data: {arg}"); } return false; } private static bool TryGetBuildableGuid(string baseDataJson, out Guid guid) { guid = default(Guid); if (string.IsNullOrEmpty(baseDataJson)) { return false; } try { BuildableItemData val = JsonUtility.FromJson<BuildableItemData>(baseDataJson); if (val != null && !string.IsNullOrEmpty(val.GUID) && Guid.TryParse(val.GUID, out guid)) { return true; } } catch (Exception arg) { ModLogger.Warn($"Failed to read buildable GUID from base data: {arg}"); } return false; } private static T GetObjectByGuid<T>(Guid guid) { return GUIDManager.GetObject<T>(guid); } private static bool TryParseProceduralGridItemData(string baseDataJson, out ProceduralGridItemData proceduralData) { proceduralData = null; if (string.IsNullOrEmpty(baseDataJson)) { return false; } try { proceduralData = JsonUtility.FromJson<ProceduralGridItemData>(baseDataJson); if (proceduralData == null || proceduralData.FootprintMatches == null || proceduralData.FootprintMatches.Length == 0) { proceduralData = null; return false; } return true; } catch { proceduralData = null; return false; } } private static bool AreProceduralDependenciesReady(ProceduralGridItemData proceduralData, out string reason) { //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Expected O, but got Unknown //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) reason = string.Empty; if (proceduralData == null || proceduralData.FootprintMatches == null || proceduralData.FootprintMatches.Length == 0) { reason = "procedural footprint match data is missing"; return false; } for (int i = 0; i < proceduralData.FootprintMatches.Length; i++) { FootprintMatchData val = proceduralData.FootprintMatches[i]; if (!Guid.TryParse(val.TileOwnerGUID, out var result)) { reason = $"invalid tile owner GUID at footprint index {i}"; return false; } BuildableItem objectByGuid = GetObjectByGuid<BuildableItem>(result); if ((Object)(object)objectByGuid == (Object)null || objectByGuid.IsDestroyed || (Object)(object)((NetworkBehaviour)objectByGuid).NetworkObject == (Object)null) { reason = "tile owner " + val.TileOwnerGUID + " is missing"; return false; } CoordinateProceduralTilePair val2 = default(CoordinateProceduralTilePair); val2.coord = new Coordinate(Mathf.RoundToInt(val.FootprintCoordinate.x), Mathf.RoundToInt(val.FootprintCoordinate.y)); val2.tileParent = ((NetworkBehaviour)objectByGuid).NetworkObject; val2.tileIndex = val.TileIndex; CoordinateProceduralTilePair val3 = val2; ProceduralTile tile; try { tile = ((CoordinateProceduralTilePair)(ref val3)).tile; } catch { reason = $"tile lookup failed for owner {val.TileOwnerGUID} at index {val.TileIndex}"; return false; } if ((Object)(object)tile == (Object)null) { reason = $"tile lookup returned null for owner {val.TileOwnerGUID} at index {val.TileIndex}"; return false; } if ((Object)(object)tile.MatchedFootprintTile == (Object)null) { reason = $"tile {val.TileIndex} on owner {val.TileOwnerGUID} is not matched to a footprint tile"; return false; } if ((Object)(object)tile.MatchedFootprintTile.MatchedStandardTile == (Object)null) { reason = $"tile {val.TileIndex} on owner {val.TileOwnerGUID} has no matched standard tile"; return false; } if ((Object)(object)tile.MatchedFootprintTile.MatchedStandardTile.LightExposureNode == (Object)null) { reason = $"tile {val.TileIndex} on owner {val.TileOwnerGUID} has no light exposure node"; return false; } } return true; } private static int GetLoadOrder(string baseDataJson) { if (string.IsNullOrEmpty(baseDataJson)) { return 0; } try { return JsonUtility.FromJson<BuildableItemData>(baseDataJson)?.LoadOrder ?? 0; } catch (Exception arg) { ModLogger.Warn($"Failed to read load order from base data: {arg}"); } return 0; } private static BuildableCaptureState EvaluateBuildableCaptureState(Property property, BuildableItem buildable, out string reason, out bool pruneFromProperty) { reason = string.Empty; pruneFromProperty = false; if ((Object)(object)buildable == (Object)null) { reason = "buildable was null"; return BuildableCaptureState.Invalid; } if ((Object)(object)((Component)buildable).gameObject == (Object)null) { reason = "buildable game object missing"; pruneFromProperty = true; return BuildableCaptureState.Invalid; } if (buildable.IsDestroyed) { reason = "buildable is destroyed"; pruneFromProperty = true; return BuildableCaptureState.Invalid; } if (buildable.isGhost) { reason = "buildable is still ghost-only"; return BuildableCaptureState.Transient; } if (!buildable.Initialized) { reason = "buildable was never initialized"; return BuildableCaptureState.Transient; } if ((Object)(object)buildable.ParentProperty == (Object)null) { reason = "buildable parent property is missing"; pruneFromProperty = true; return BuildableCaptureState.Invalid; } if ((Object)(object)buildable.ParentProperty != (Object)(object)property) { reason = "buildable belongs to a different property"; pruneFromProperty = true; return BuildableCaptureState.Invalid; } GridItem val = (GridItem)(object)((buildable is GridItem) ? buildable : null); if (val != null && (Object)(object)val.OwnerGrid == (Object)null) { reason = "grid item owner grid is missing"; return BuildableCaptureState.Transient; } Pot val2 = (Pot)(object)((buildable is Pot) ? buildable : null); if (val2 != null && val2.Configuration == null) { reason = "pot configuration is missing"; return BuildableCaptureState.Transient; } return BuildableCaptureState.Valid; } private static void PruneInvalidBuildables(Property property, List<BuildableItem> invalidBuildables) { if ((Object)(object)property == (Object)null || property.BuildableItems == null) { return; } if (invalidBuildables == null) { invalidBuildables = new List<BuildableItem>(); } int num = 0; for (int num2 = property.BuildableItems.Count - 1; num2 >= 0; num2--) { if ((Object)(object)property.BuildableItems[num2] == (Object)null) { property.BuildableItems.RemoveAt(num2); num++; } } foreach (BuildableItem item in invalidBuildables.Distinct().ToList()) { if (!((Object)(object)item == (Object)null) && property.BuildableItems.Remove(item)) { num++; } } if (num > 0) { ModLogger.Warn($"Pruned {num} invalid outside buildable(s) from property '{property.PropertyCode}'"); } } private static string DescribeBuildable(BuildableItem buildable) { if ((Object)(object)buildable == (Object)null) { return "<null buildable>"; } string text = (((Object)(object)((Component)buildable).gameObject != (Object)null) ? ((Object)((Component)buildable).gameObject).name : ((object)buildable).GetType().Name); string text2 = "no-guid"; try { string text3 = buildable.GUID.ToString(); if (!string.IsNullOrWhiteSpace(text3) && !text3.Equals("00000000-0000-0000-0000-000000000000", StringComparison.Ordinal)) { text2 = text3; } } catch { } return text + " (" + text2 + ")"; } private static RestoreOutcome TryRestoreRecord(LoadManager loadManager, PendingRestoreRecord pendingRecord, out string reason) { reason = string.Empty; if (pendingRecord?.Record == null) { reason = "record was null"; return RestoreOutcome.PermanentFailure; } OutsideBuildableRecord record = pendingRecord.Record; if (string.IsNullOrEmpty(record.BaseData)) { reason = "record had empty base data"; return RestoreOutcome.PermanentFailure; } DynamicSaveData val = BuildDynamicSaveData(record); if (string.IsNullOrEmpty(((SaveData)val).DataType)) { reason = "record was missing data type"; return RestoreOutcome.PermanentFailure; } if (!TryGetBuildableGuid(val.BaseData, out var guid)) { reason = "record had invalid buildable GUID"; return RestoreOutcome.PermanentFailure; } if (TryGetGridGuid(val.BaseData, out var guid2) && (Object)(object)GetObjectByGuid<Grid>(guid2) == (Object)null) { reason = $"grid {guid2} is not ready"; return RestoreOutcome.Deferred; } BuildableItemLoader objectLoader = loadManager.GetObjectLoader(((SaveData)val).DataType); if (objectLoader == null) { reason = "object loader for " + ((SaveData)val).DataType + " is not ready"; return RestoreOutcome.Deferred; } if (TryParseProceduralGridItemData(val.BaseData, out var proceduralData) && !AreProceduralDependenciesReady(proceduralData, out var reason2)) { reason = "procedural dependencies are not ready: " + reason2; return RestoreOutcome.Deferred; } try { objectLoader.Load(val); ModLogger.Info($"Restored outside buildable {((SaveData)val).DataType} ({guid})"); return RestoreOutcome.Restored; } catch (Exception ex) { reason = ((SaveData)val).DataType + " restore threw: " + ex.Message; return (pendingRecord.Attempts < 3) ? RestoreOutcome.Deferred : RestoreOutcome.PermanentFailure; } } private static List<OutsideBuildableRecord> CloneRecords(IEnumerable<OutsideBuildableRecord> records) { List<OutsideBuildableRecord> list = new List<OutsideBuildableRecord>(); if (records == null) { return list; } foreach (OutsideBuildableRecord record in records) { if (record != null) { list.Add(new OutsideBuildableRecord { DataType = record.DataType, BaseData = record.BaseData, AdditionalDatas = ((record.AdditionalDatas != null) ? record.AdditionalDatas.Select((AdditionalDataRecord additional) => new AdditionalDataRecord { Name = (additional?.Name ?? string.Empty), Contents = (additional?.Contents ?? string.Empty) }).ToList() : new List<AdditionalDataRecord>()) }); } } return list; } private static bool TryGetPropertyGridGuids(Property property, out HashSet<Guid> gridGuids) { gridGuids = new HashSet<Guid>(); if (property?.Grids == null) { return false; } foreach (Grid item in property.Grids.AsEnumerable()) { if ((Object)(object)item == (Object)null) { continue; } try { string input = item.GUID.ToString(); if (Guid.TryParse(input, out var result) && result != Guid.Empty) { gridGuids.Add(result); } } catch { } } return gridGuids.Count > 0; } private static void RemoveRecordsForGridGuids(List<OutsideBuildableRecord> records, HashSet<Guid> gridGuids) { if (records == null || records.Count == 0 || gridGuids == null || gridGuids.Count == 0) { return; } for (int num = records.Count - 1; num >= 0; num--) { OutsideBuildableRecord outsideBuildableRecord = records[num]; Guid guid; if (outsideBuildableRecord == null) { records.RemoveAt(num); } else if (TryGetGridGuid(outsideBuildableRecord.BaseData, out guid) && gridGuids.Contains(guid)) { records.RemoveAt(num); } } } private static string DescribeRecord(OutsideBuildableRecord record, int sourceIndex) { if (record == null) { return $"outside buildable record #{sourceIndex}"; } string text = ((!string.IsNullOrWhiteSpace(record.DataType)) ? record.DataType : $"record #{sourceIndex}"); if (TryGetBuildableGuid(record.BaseData, out var guid)) { return $"{text} ({guid})"; } return text; } } public sealed class OutsideBuildableRecord { public string DataType { get; set; } public string BaseData { get; set; } public List<AdditionalDataRecord> AdditionalDatas { get; set; } = new List<AdditionalDataRecord>(); } public sealed class AdditionalDataRecord { public string Name { get; set; } public string Contents { get; set; } } public sealed class SyntheticGridSaveable : Saveable { [SaveableField("synthetic_grids")] private List<SyntheticGridRecord> _records = new List<SyntheticGridRecord>(); public static SyntheticGridSaveable Instance { get; private set; } public SyntheticGridSaveable() { Instance = this; } public IReadOnlyList<SyntheticGridRecord> GetRecords() { return _records; } public void SetRecords(List<SyntheticGridRecord> records) { _records = records ?? new List<SyntheticGridRecord>(); } protected override void OnLoaded() { if (SyntheticGridManager.TryMigrateLegacySyntheticGridRecords(_records, out var migratedRecords, out var mergedPropertiesCount, out var mergedRecordCount)) { _records = migratedRecords; ModLogger.Warn($"Migrated legacy synthetic properties: merged {mergedRecordCount} record(s) across {mergedPropertiesCount} nearby cluster(s). Changes will persist on the next save."); } SyntheticGridManager.RestoreFromSave(_records); } } public sealed class SyntheticGridRecord { public string PropertyCode { get; set; } public string PropertyName { get; set; } public string GridGuid { get; set; } public Vector3 Origin { get; set; } public int MinX { get; set; } public int MaxX { get; set; } public int MinY { get; set; } public int MaxY { get; set; } public bool HasManualIdlePoint { get; set; } public Vector3 ManualIdlePointPosition { get; set; } public float ManualIdlePointYaw { get; set; } } public sealed class TentOwnershipSaveable : Saveable { private bool _isReady = false; [SaveableField("tent_owned")] private bool _tentOwned = false; [SaveableField("quest_completed")] private bool _questCompleted = false; [SaveableField("npc_relocated")] private bool _npcRelocated = false; public static TentOwnershipSaveable Instance { get; private set; } public override SaveableLoadOrder LoadOrder => (SaveableLoadOrder)1; public bool IsTentOwned => _tentOwned; public bool IsQuestCompleted => _questCompleted; public bool IsNPCRelocated => _npcRelocated; public bool IsReady => _isReady; public TentOwnershipSaveable() { Instance = this; } protected override void OnCreated() { _isReady = true; } protected override void OnLoaded() { _isReady = true; } public void SetTentOwned(bool owned) { _tentOwned = owned; } public void SetQuestCompleted(bool completed) { _questCompleted = completed; if (completed) { _tentOwned = true; } } public void SetNPCRelocated(bool relocated) { _npcRelocated = relocated; } } public sealed class TentStorageSaveable : Saveable { private bool _isReady; [SaveableField("tent_storage_items")] private List<TentStoredItem> _items = new List<TentStoredItem>(); public static TentStorageSaveable Instance { get; private set; } public override SaveableLoadOrder LoadOrder => (SaveableLoadOrder)1; public bool IsReady => _isReady; public TentStorageSaveable() { Instance = this; } public IReadOnlyList<TentStoredItem> GetItems() { return _items; } public void SetItems(List<TentStoredItem> items) { _items = items ?? new List<TentStoredItem>(); } protected override void OnCreated() { _isReady = true; ModLogger.Info("Tent storage saveable created"); } protected override void OnLoaded() { _isReady = true; ModLogger.Info($"Tent storage loaded ({_items?.Count ?? 0} item(s))"); } protected override void OnSaved() { ModLogger.Info($"Tent storage saved ({_items?.Count ?? 0} item(s))"); } } public sealed class TentStoredItem { public string ItemId { get; set; } public int Quantity { get; set; } } } namespace SidewalkEconomy.Quests { public sealed class TentInheritanceQuest : Quest { private const string QUEST_ID = "reginald_tent_inheritance_quest"; [SaveableField("rewardGranted")] private bool _rewardGranted = false; [SaveableField("requiredItems")] private Dictionary<string, int> _requiredItems = new Dictionary<string, int>(); private QuestEntry _itemEntry; private QuestEntry _returnEntry; public IReadOnlyDictionary<string, int> RequiredItems => _requiredItems; protected override string Title => "New Beginnings"; protected override string Description => ""; protected override bool AutoBegin => false; protected override void OnCreated() { ((Registerable)this).OnCreated(); if (base.QuestEntries.Count == 0) { if (_requiredItems.Count == 0) { _requiredItems["growtent"] = 1; _requiredItems["ogkushseed"] = 3; } _itemEntry = ((Quest)this).AddEntry("Bring " + PrintRequiredItems() + " for Reggie", (Vector3?)null); _itemEntry.Begin(); _returnEntry = ((Quest)this).AddEntry("Return to Reggie with the supplies", (Vector3?)null); _returnEntry.SetState((QuestState)0); } else { if (base.QuestEntries.Count >= 1) { _itemEntry = base.QuestEntries[0]; } if (base.QuestEntries.Count >= 2) { _returnEntry = base.QuestEntries[1]; } } } public string PrintRequiredItems() { return string.Join(", ", _requiredItems.Select(delegate(KeyValuePair<string, int> entry) { string key = entry.Key; int value = entry.Value; ItemDefinition itemDefinition = ItemManager.GetItemDefinition(key); string arg = ((itemDefinition != null) ? itemDefinition.Name : null) ?? ("Unknown Item (" + key + ")"); return $"{value} {arg}"; })); } public void SetRequiredItems(Dictionary<string, int> requiredItems) { if (requiredItems == null) { ModLogger.Warn("Required items cannot be null. Quest setup aborted."); } else { _requiredItems = requiredItems; } } } } namespace SidewalkEconomy.NPCs { public sealed class ReginaldIterson : NPC { [Serializable] private class PersistedData { public bool QuestCompleted = false; public bool NPCRelocated = false; } [SaveableField("ReginaldItersonData")] private PersistedData _data = new PersistedData(); public override bool IsPhysical => true; public ReginaldIterson() : base("reginald_iterson", "Reginald", "Iterson", (Sprite)null) { } protected override void ConfigurePrefab(NPCPrefabBuilder builder) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) Vector3 val = CalculateSpawnPosition(); Building val2 = Building.Get<NorthApartments>(); Building val3 = Building.Get<Arcade>(); Building val4 = Building.Get<BudsBar>(); builder.WithIdentity("reginald_iterson", "Reginald", "Iterson").WithAppearanceDefaults((Action<AvatarDefaultsBuilder>)delegate(AvatarDefaultsBuilder av) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) av.Gender = 0f; av.Height = 1f; av.Weight = 0.1f; av.SkinColor = new Color32((byte)211, (byte)181, (byte)143, byte.MaxValue); av.LeftEyeLidColor = new Color(0.827f, 0.71f, 0.561f); av.RightEyeLidColor = new Color(0.827f, 0.71f, 0.561f); av.EyeBallTint = new Color(1f, 1f, 1f); av.HairColor = new Color(0.176f, 0.125f, 0.075f); av.HairPath = "Avatar/Hair/closebuzzcut/CloseBuzzCut"; av.EyeballMaterialIdentifier = "Default"; av.PupilDilation = 0.5f; av.EyebrowScale = 1f; av.EyebrowThickness = 1f; av.EyebrowRestingHeight = -0.75f; av.EyebrowRestingAngle = 0.3f; av.LeftEye = (0.5f, 0.35f); av.RightEye = (0.555f, 0.35f); av.WithFaceLayer("Avatar/Layers/Face/Face_Agape", new Color(1f, 1f, 1f)); av.WithFaceLayer("Avatar/Layers/Face/FacialHair_Stubble", new Color(0f, 0f, 0f)); av.WithFaceLayer("Avatar/Layers/Face/FacialHair_Goatee", new Color(0.325f, 0.282f, 0.192f)); av.WithBodyLayer("Avatar/Layers/Top/ChestHair1", new Color(0.318f, 0.294f, 0.2f)); av.WithBodyLayer("Avatar/Layers/Bottom/CargoPants", new Color(0.125f, 0.125f, 0.125f)); av.WithBodyLayer("Avatar/Layers/Bottom/MaleUnderwear", new Color(1f, 1f, 1f)); av.WithBodyLayer("Avatar/Layers/Top/FlannelButtonUp", new Color(0.541f, 0f, 0f)); av.WithAccessoryLayer("Avatar/Accessories/Chest/OpenVest/OpenVest", new Color(0.592f, 0.569f, 0.341f)); av.WithAccessoryLayer("Avatar/Accessories/Head/Cap/Cap", new Color(0.384f, 0.369f, 0.216f)); }).WithSpawnPosition(val) .EnsureCustomer() .WithCustomerDefaults((Action<CustomerDataBuilder>)delegate(CustomerDataBuilder cd) { cd.WithSpending(400f, 900f).WithOrdersPerWeek(1, 4).WithPreferredOrderDay((Day)6) .WithOrderTime(900) .WithStandards((CustomerStandard)1) .WithMutualRelationRequirement(2.5f, 4f) .AllowDirectApproach(true) .WithCallPoliceChance(0.7f) .WithDependence(0.15f, 1f) .WithAffinities((IEnumerable<ValueTuple<DrugType, float>>)new(DrugType, float)[2] { ((DrugType)0, 0.5f), ((DrugType)4, 0.5f) }); }) .WithRelationshipDefaults((Action<NPCRelationshipDataBuilder>)delegate(NPCRelationshipDataBuilder r) { r.WithDelta(1f).SetUnlocked(false).SetUnlockType((UnlockType)1) .WithConnectionsById(new string[1] { "kyle_cooley" }); }) .WithInventoryDefaults((Action<RandomInventoryItemsBuilder>)delegate(RandomInventoryItemsBuilder inv) { inv.WithStartupItems(new string[2] { "machete", "donut" }).WithRandomCash(50, 500); }); } private Vector3 CalculateSpawnPosition() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) Vector3 tENT_POSITION = Constants.WorldSpawns.TENT_POSITION; return new Vector3(500f, 0f, 500f); } protected override void OnLoaded() { ((Saveable)this).OnLoaded(); } protected override void OnCreated() { ((NPC)this).OnCreated(); ((NPC)this).Appearance.Build(); ((NPC)this).Schedule.Enable(); ((NPC)this).Region = (Region)0; SetupDialogue(); ((NPC)this).RequiresRegionUnlocked = false; ((NPC)this).Region = (Region)0; ((NPC)this).Aggressiveness = 0f; } private void SetupDialogue() { } } } namespace SidewalkEconomy.Helpers { public static class AssetBundleUtils { private static readonly SidewalkEconomyMod mod = MelonAssembly.FindMelonInstance<SidewalkEconomyMod>(); private static readonly MelonAssembly melonAssembly = ((MelonBase)mod).MelonAssembly; private static readonly Assembly modAssembly = melonAssembly.Assembly; private static Dictionary<string, WrappedAssetBundle> _bundleCache = new Dictionary<string, WrappedAssetBundle>(); public static WrappedAssetBundle LoadAssetBundle(string bundleFileName) { try { if (_bundleCache.TryGetValue(bundleFileName, out var value)) { if (value != null) { ModLogger.Debug("Using cached asset bundle: " + bundleFileName); return value; } _bundleCache.Remove(bundleFileName); } string text = (bundleFileName.Contains(".") ? bundleFileName : (modAssembly.GetName().Name + "." + bundleFileName)); ModLogger.Debug("Loading asset bundle from embedded resource: " + text); WrappedAssetBundle assetBundleFromStream = AssetLoader.GetAssetBundleFromStream(text, modAssembly); if (assetBundleFromStream == null) { if (modAssembly != null) { string[] manifestResourceNames = modAssembly.GetManifestResourceNames(); ModLogger.Error("Failed to load AssetBundle from resource: '" + text + "'. Make sure the bundle file '" + bundleFileName + "' is set as 'EmbeddedResource' in your .csproj file."); ModLogger.Error($"Available embedded resources ({manifestResourceNames.Length}):"); string[] array = manifestResourceNames; foreach (string text2 in array) { ModLogger.Error(" - " + text2); } } else { ModLogger.Error("Failed to load AssetBundle from resource: '" + text + "'. Make sure the bundle file '" + bundleFileName + "' is set as 'EmbeddedResource' in your .csproj file."); } return null; } _bundleCache[bundleFileName] = assetBundleFromStream; ModLogger.Debug("✓ Successfully loaded and cached asset bundle: " + bundleFileName); return assetBundleFromStream; } catch (Exception ex) { ModLogger.Error("Failed to load AssetBundle '" + bundleFileName + "': " + ex.Message); ModLogger.Error("Stack trace: " + ex.StackTrace); return null; } } public static WrappedAssetBundle GetLoadedAssetBundle(string asset_name_flag) { if (_bundleCache.TryGetValue(asset_name_flag, out var value)) { if (value != null) { return value; } _bundleCache.Remove(asset_name_flag); } IEnumerable<AssetBundle> allLoadedAssetBundles = AssetBundle.GetAllLoadedAssetBundles(); AssetBundle[] array = allLoadedAssetBundles.ToArray(); try { AssetBundle[] array2 = array; foreach (AssetBundle val in array2) { if (!((Object)(object)val == (Object)null) && val.Contains(asset_name_flag)) { string name = ((Object)val).name; if (_bundleCache.TryGetValue(name, out var value2)) { return value2; } ModLogger.Debug("Found bundle '" + name + "' but it's not in cache as WrappedAssetBundle"); } } string text = ""; AssetBundle[] array3 = array; foreach (AssetBundle val2 in array3) { if (!((Object)(object)val2 == (Object)null)) { try { string[] allAssetNames = val2.GetAllAssetNames(); string arg = string.Join("\n\r -", allAssetNames); text += $"{((Object)val2).name}({allAssetNames.Length} assets):{arg}\n"; } catch { text = text + ((Object)val2).name + "(error getting asset names)\n"; } } } ModLogger.Error($"Asset '{asset_name_flag}' not found in {array.Length} bundle(s).\n{text}"); return null; } catch (Exception ex) { ModLogger.Error("Failed to get loaded AssetBundle: " + ex.Message); ModLogger.Error("Stack trace: " + ex.StackTrace); return null; } } public static GameObject LoadAssetFromBundle(string asset_name) { WrappedAssetBundle loadedAssetBundle = GetLoadedAssetBundle(asset_name); if (loadedAssetBundle == null) { ModLogger.Error("Cannot load asset '" + asset_name + "': bundle not found"); return null; } try { return loadedAssetBundle.LoadAsset<GameObject>(asset_name); } catch (Exception ex) { ModLogger.Error("Failed to load asset '" + asset_name + "' from bundle: " + ex.Message); return null; } } public static void ClearBundleCache(string bundleFileName = null) { if (bundleFileName == null) { _bundleCache.Clear(); ModLogger.Debug("Cleared entire asset bundle cache"); } else if (_bundleCache.Remove(bundleFileName)) { ModLogger.Debug("Removed " + bundleFileName + " from asset bundle cache"); } } } internal static class BuildModeRecovery { private const float OutsidePlacementHeartbeatWindowSeconds = 0.35f; private static float _outsidePlacementHeartbeatExpiry; internal static void ReportOutsidePlacementHeartbeat() { _outsidePlacementHeartbeatExpiry = Time.unscaledTime + 0.35f; } internal static bool OwnsOutsidePlacementFlow() { return Time.unscaledTime <= _outsidePlacementHeartbeatExpiry && IsBuildModeActive(); } internal static bool IsBuildModeActive() { if (!NetworkSingleton<BuildManager>.InstanceExists) { _outsidePlacementHeartbeatExpiry = 0f; return false; } BuildManager instance = NetworkSingleton<BuildManager>.Instance; if ((Object)(object)instance == (Object)null) { _outsidePlacementHeartbeatExpiry = 0f; return false; } if (instance.isBuilding) { return true; } return (Object)(object)GetCurrentBuildHandler(instance) != (Object)null; } internal static bool TryExitBuildMode(string reason, bool force) { if (!NetworkSingleton<BuildManager>.InstanceExists) { _outsidePlacementHeartbeatExpiry = 0f; return false; } BuildManager instance = NetworkSingleton<BuildManager>.Instance; if ((Object)(object)instance == (Object)null) { return false; } GameObject currentBuildHandler = GetCurrentBuildHandler(instance); bool isBuilding = instance.isBuilding; if (!force && !isBuilding && (Object)(object)currentBuildHandler == (Object)null) { _outsidePlacementHeartbeatExpiry = 0f; return false; } try { if (isBuilding && (Object)(object)currentBuildHandler != (Object)null && (Object)(object)currentBuildHandler.GetComponent<BuildStop_Base>() != (Object)null) { instance.StopBuilding(); if (!IsBuildModeStillActive(instance)) { _outsidePlacementHeartbeatExpiry = 0f; ModLogger.Debug("Build mode exited: " + reason); return true; } ModLogger.Warn("BuildManager.StopBuilding did not fully clear build mode (" + reason + "); escalating to forced reset"); } } catch (Exception arg) { ModLogger.Warn($"BuildManager.StopBuilding failed during recovery ({reason}): {arg}"); } ForceResetBuildMode(instance, currentBuildHandler, reason); return true; } private static GameObject GetCurrentBuildHandler(BuildManager buildManager) { return ((Object)(object)buildManager != (Object)null) ? buildManager.currentBuildHandler : null; } private static void ForceResetBuildMode(BuildManager buildManager, GameObject handler, string reason) { try { if ((Object)(object)handler != (Object)null) { BuildStop_Base component = handler.GetComponent<BuildStop_Base>(); if ((Object)(object)component != (Object)null) { component.Stop_Building(); } else { Object.Destroy((Object)(object)handler); } } TrySetPropertyValue(buildManager, "isBuilding", value: false); TrySetPropertyValue<GameObject>(buildManager, "currentBuildHandler", null); if (Singleton<InputPromptsCanvas>.InstanceExists) { Singleton<InputPromptsCanvas>.Instance.UnloadModule(); } if (Singleton<HeatmapManager>.InstanceExists) { Singleton<HeatmapManager>.Instance.SetAllHeatmapsActive(false); } if (PlayerSingleton<PlayerCamera>.InstanceExists && Singleton<HUD>.InstanceExists && PlayerSingleton<PlayerCamera>.Instance.activeUIElementCount == 0) { Singleton<HUD>.Instance.SetCrosshairVisible(true); } _outsidePlacementHeartbeatExpiry = 0f; if (IsBuildModeStillActive(buildManager)) { ModLogger.Warn("Forced build mode reset completed with residual active state: " + reason); } else { ModLogger.Warn("Forced build mode reset: " + reason); } } catch (Exception arg) { ModLogger.Error($"Forced build mode reset failed ({reason}): {arg}"); } } private static bool IsBuildModeStillActive(BuildManager buildManager) { return (Object)(object)buildManager != (Object)null && (buildManager.isBuilding || (Object)(object)GetCurrentBuildHandler(buildManager) != (Object)null); } private static bool TrySetPropertyValue<T>(BuildManager buildManager, string propertyName, T value) { if ((Object)(object)buildManager == (Object)null) { return false; } PropertyInfo property = typeof(BuildManager).GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if ((object)property == null || !property.CanWrite) { return false; } try { property.SetValue(buildManager, value, null); return true; } catch { return false; } } } public static class Constants { public static class AssetBundle { public const string ASSETBUNDLE_NAME = "SidewalkEconomy.sidewalkeconomy"; public const string ASSETBUNDLE_FILE_NAME = "sidewalkeconomy"; public const string SLEEPINGBAG_PREFAB_NAME = "assets/sidewalk economy/sleepingbag.prefab"; public const string TENT_PREFAB_NAME = "assets/sidewalk economy/tent.prefab"; } public static class CustomItems { public const string TENT_ID = "sidewalkeconomy.tent"; public const string SLEEPINGBAG_ID = "sidewalkeconomy.sleepingbag"; public const string TENT_NAME = "Sidewalk Tent"; public const string SLEEPINGBAG_NAME = "Sleeping Bag"; public const string TENT_DESCRIPTION = "A portable shelter for outdoor living. Provides basic protection from the elements."; public const string SLEEPINGBAG_DESCRIPTION = "A warm sleeping bag for rough nights on the streets."; public const string CATEGORY = "Survival Gear"; public const int TENT_PRICE = 150; public const int SLEEPINGBAG_PRICE = 75; public const ushort TENT_PREFAB_ID = 9001; public const ushort SLEEPINGBAG_PREFAB_ID = 9002; public const string TENT_ICON_PATH = "SidewalkEconomy.Icons.tent.png"; public const string SLEEPINGBAG_ICON_PATH = "SidewalkEconomy.Icons.sleepingbag.png"; } public static class WorldSpawns { public const string SLEEPING_BAG_SPAWN_NAME = "SidewalkEconomy_SleepingBag_Spawn"; public const string TENT_SPAWN_NAME = "SidewalkEconomy_Tent_Spawn"; public const string TENT_STORAGE_ANCHOR_NAME = "SidewalkEconomy_TentStorage"; public static readonly Vector3 SLEEPING_BAG_POSITION = new Vector3(-90.5f, -3.85f, 69.728f); public static readonly Vector3 SLEEPING_BAG_ROTATION_EULER = Vector3.zero; public static readonly Vector3 TENT_POSITION = new Vector3(10f, 0.65f, -76f); public static readonly Vector3 TENT_ROTATION_EULER = new Vector3(0f, 180f, 0f); public static readonly Vector3 MARCUS_RELOCATE_POSITION = new Vector3(25f, 0.65f, -60f); public static readonly Vector3 MARCUS_RELOCATE_ROTATION_EULER = new Vector3(0f, 90f, 0f); public const float TENT_ENTRANCE_ANGLE_DEGREES = 30f; public const float TENT_ENTRANCE_YAW_OFFSET_DEGREES = 20f; public static readonly Vector3 TENT_SLEEP_OFFSET = new Vector3(0f, 0.9f, 1.35f); public static readonly Vector3 TENT_SLEEP_COLLIDER_SIZE = new Vector3(1.1f, 1.4f, 0.75f); public static readonly Vector3 TENT_STORAGE_OFFSET = new Vector3(1.25f, 0f, 0f); public static readonly Vector3 TENT_STORAGE_COLLIDER_SIZE = new Vector3(0.6f, 1f, 0.6f); } public static class NPCs { public const string MARCUS_ID = "reginald_iterson"; public const string MARCUS_FIRST_NAME = "Reginald"; public const string MARCUS_LAST_NAME = "Iterson"; } public static class Quests { public const string TENT_INHERITANCE_ID = "tent_inheritance_quest"; public const string TENT_INHERITANCE_TITLE = "New Beginnings"; public const string TENT_INHERITANCE_GROW_TENT_ID = "growtent"; public const string TENT_INHERITANCE_GROW_TENT_NAME = "Grow Tent"; public const int TENT_INHERITANCE_GROW_TENT_AMOUNT = 1; public const string TENT_INHERITANCE_OG_KUSH_SEED_ID = "ogkushseed"; public const string TENT_INHERITANCE_OG_KUSH_SEED_NAME = "OG Kush Seeds"; public const int TENT_INHERITANCE_OG_KUSH_SEED_AMOUNT = 3; } } public sealed class GameTimeManager { [CompilerGenerated] private sealed class <UpdateGameTime>d__30 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public GameTimeManager <>4__this; private float <gameMinutes>5__1; private int <newGameDay>5__2; private float <dayMinutes>5__3; private int <newGameHour>5__4; private int <newGameMinute>5__5; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <UpdateGameTime>d__30(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } <gameMinutes>5__1 = <>4__this.GetCurrentGameTimeInMinutes(); <newGameDay>5__2 = Mathf.FloorToInt(GameMinutesToGameDays(<gameMinutes>5__1)) + 1; <dayMinutes>5__3 = <gameMinutes>5__1 % 1440f; <newGameHour>5__4 = Mathf.FloorToInt(<dayMinutes>5__3 / 60f); <newGameMinute>5__5 = Mathf.FloorToInt(<dayMinutes>5__3 % 60f); if (<newGameDay>5__2 != <>4__this._currentGameDay) { <>4__this._currentGameDay = <newGameDay>5__2; <>4__this.OnGameDayChanged?.Invoke(<>4__this._currentGameDay); } if (<newGameHour>5__4 != <>4__this._currentGameHour) { <>4__this._currentGameHour = <newGameHour>5__4; <>4__this.OnGameHourChanged?.Invoke(<>4__this._currentGameHour); } if (<newGameMinute>5__5 != <>4__this._currentGameMinute) { <>4__this._currentGameMinute = <newGameMinute>5__5; <>4__this.OnGameMinuteChanged?.Invoke(<>4__this._currentGameMinute); } <>2__current = (object)new WaitForSeconds(1f); <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static GameTimeManager _instance; public c