Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of MultiDelivery v1.0.0
MultiDelivery-IL2CPP.dll
Decompiled 3 hours agousing 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 System.Text; using System.Threading.Tasks; using HarmonyLib; using Il2Cpp; using Il2CppFishNet; using Il2CppFishNet.Connection; using Il2CppFishNet.Object; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.Attributes; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppScheduleOne; using Il2CppScheduleOne.Core.Items.Framework; using Il2CppScheduleOne.Delivery; using Il2CppScheduleOne.DevUtilities; using Il2CppScheduleOne.Graffiti; using Il2CppScheduleOne.ItemFramework; using Il2CppScheduleOne.Map; using Il2CppScheduleOne.Money; using Il2CppScheduleOne.NPCs.CharacterClasses; using Il2CppScheduleOne.Persistence.Datas; using Il2CppScheduleOne.Persistence.Loaders; using Il2CppScheduleOne.PlayerScripts; using Il2CppScheduleOne.UI.Phone.Delivery; using Il2CppScheduleOne.UI.Shop; using Il2CppScheduleOne.Vehicles; using Il2CppScheduleOne.Vehicles.Modification; using Il2CppScheduleOne.Weather; using Il2CppSteamworks; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Il2CppSystem.IO; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using MultiDelivery; using MultiDelivery.Builders; using MultiDelivery.Helpers; using MultiDelivery.Network; using MultiDelivery.Persistence; using MultiDelivery.Pool; using MultiDelivery.Quest; using S1API.Dialogues; using S1API.Entities; using S1API.Entities.Dialogue; using S1API.Entities.NPCs.Suburbia; using S1API.Internal.Abstraction; using S1API.Leveling; using S1API.Messaging; using S1API.Money; using S1API.Quests; using S1API.Quests.Constants; using S1API.Saveables; using S1API.Utils; using SteamNetworkLib; using SteamNetworkLib.Core; using SteamNetworkLib.Events; using SteamNetworkLib.Models; using UnityEngine; 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(global::MultiDelivery.MultiDelivery), "MultiDelivery", "1.0.1", "k073l", null)] [assembly: MelonColor(1, 0, 255, 0)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: MelonPlatformDomain(/*Could not decode attribute arguments.*/)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("MultiDelivery-IL2CPP")] [assembly: AssemblyConfiguration("IL2CPP")] [assembly: AssemblyDescription("Add vehicles, order multiple deliveries from the same place!")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+9f266827b45c3676261f34c577e88b8249083816")] [assembly: AssemblyProduct("MultiDelivery-IL2CPP")] [assembly: AssemblyTitle("MultiDelivery-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 MultiDelivery { public class Logger { [CompilerGenerated] [DebuggerBrowsable(DebuggerBrowsableState.Never)] private string <categoryName>P; [CompilerGenerated] [DebuggerBrowsable(DebuggerBrowsableState.Never)] private LogLevel? <forceLevel>P; public Logger(string categoryName, LogLevel? forceLevel = null) { <categoryName>P = categoryName; <forceLevel>P = forceLevel; base..ctor(); } public void NetworkTrace(params object[] args) { Log(LogLevel.NetworkTrace, args); } public void Debug(params object[] args) { Log(LogLevel.Debug, args); } public void Info(params object[] args) { Log(LogLevel.Info, args); } public void Msg(params object[] args) { Log(LogLevel.Info, args); } public void Warn(params object[] args) { Log(LogLevel.Warn, args); } public void Warning(params object[] args) { Log(LogLevel.Warn, args); } public void Error(params object[] args) { Log(LogLevel.Error, args); } private void Log(LogLevel level, params object[] args) { LogLevel? logLevel = <forceLevel>P; if (logLevel.HasValue) { LogLevel valueOrDefault = logLevel.GetValueOrDefault(); if (level < LogLevel.Error) { level = valueOrDefault; } } if (args.Length == 0) { return; } string text; if (args.Length == 1) { text = args[0]?.ToString() ?? ""; } else { string format = args[0]?.ToString() ?? ""; text = string.Format(format, args.Skip(1).ToArray()); } string text2 = (string.IsNullOrWhiteSpace(<categoryName>P) ? "MultiDelivery" : ("MultiDelivery." + <categoryName>P)); string text3 = "[" + text2 + "] " + text; switch (level) { case LogLevel.NetworkTrace: if (MultiDelivery.NetworkLogging.Value) { Melon<MultiDelivery>.Logger.Msg(text3); } break; case LogLevel.Debug: MelonDebug.Msg(text3); break; case LogLevel.Info: Melon<MultiDelivery>.Logger.Msg(text3); break; case LogLevel.Warn: Melon<MultiDelivery>.Logger.Warning(text3); break; case LogLevel.Error: Melon<MultiDelivery>.Logger.Error(text3); break; } } } public enum LogLevel { NetworkTrace, Debug, Info, Warn, Error } public static class BuildInfo { public const string Name = "MultiDelivery"; public const string Description = "Add vehicles, order multiple deliveries from the same place!"; public const string Author = "k073l"; public const string Version = "1.0.1"; } public class MultiDelivery : MelonMod { [CompilerGenerated] private sealed class <InitializeNetworkManager>d__12 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public MultiDelivery <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <InitializeNetworkManager>d__12(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; if (!SteamAPI.Init()) { return false; } <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; <>4__this._networkManager = new DeliveryNetworkManager(); if (<>4__this._networkManager.Initialize()) { Logger.Msg("Network manager initialized"); NetworkConvenienceMethods.InitializeNetworking(<>4__this._networkManager); } else { <>4__this._networkManager = null; Logger.Warning("Network manager initialization failed - running in offline mode"); } 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 <WireOnXpChangedDelayed>d__16 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public MultiDelivery <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WireOnXpChangedDelayed>d__16(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitUntil(Func<bool>.op_Implicit((Func<bool>)(() => LevelManager.Exists))); <>1__state = 1; return true; case 1: <>1__state = -1; if (PersistentDropoffQuestData.Instance.HasMessaged) { DropoffQuestDialogue.Register(); return false; } Logger.Debug("Wiring on xp changed"); LevelManager.OnXPChanged += <>4__this.SendMessageIfRequiredRank; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } internal const string RequestedVehicleCode = "veeper"; private static FullRank RequiredRank = new FullRank((Rank)5, 1); private static Sprite _questIconSprite; private static readonly Logger Logger = new Logger(""); private DeliveryNetworkManager? _networkManager; private bool _networkManagerFailed; internal static MelonPreferences_Category Category = MelonPreferences.CreateCategory("MultiDeliverySettings", "MultiDelivery's Settings"); internal static MelonPreferences_Entry<bool> NetworkLogging = Category.CreateEntry<bool>("NetworkDebugLogs", false, "Enable Network Logs", "Display networking-related debug logs in MelonLoader console/log file (may be verbose)", false, false, (ValueValidator)null, (string)null); public static Sprite QuestIconSprite => GetIcon(ref _questIconSprite, "MultiDelivery.assets.quest_icon.png"); public override void OnInitializeMelon() { Logger.Msg("MultiDelivery initialized"); MelonCoroutines.Start(InitializeNetworkManager()); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { if (sceneName == "Main") { Player.LocalPlayerSpawned += WirePlayerEvent; } else if (!(sceneName != "Menu")) { PoolManager.Instance.Pool.Clear(); PoolManager.Instance.Allocations.Clear(); PoolManager.Instance.BaseVehicleAllocationsForShop.Clear(); Player.LocalPlayerSpawned -= WirePlayerEvent; LevelManager.OnXPChanged -= SendMessageIfRequiredRank; } } [IteratorStateMachine(typeof(<InitializeNetworkManager>d__12))] private IEnumerator InitializeNetworkManager() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <InitializeNetworkManager>d__12(0) { <>4__this = this }; } public override void OnUpdate() { if (_networkManagerFailed || _networkManager == null) { return; } try { _networkManager.Update(); } catch (Exception ex) { MelonLogger.Error("Network manager update failed: " + ex.Message + "\n\nYou can ignore this error if you plan on playing singleplayer only and don't want to install SteamNetworkLib"); _networkManagerFailed = true; } } public override void OnDeinitializeMelon() { _networkManager?.Dispose(); Logger.Msg("MultiDelivery deinitialized"); } private void WirePlayerEvent(Player _) { Logger.Debug("Player loaded event called"); MelonCoroutines.Start(WireOnXpChangedDelayed()); } [IteratorStateMachine(typeof(<WireOnXpChangedDelayed>d__16))] private IEnumerator WireOnXpChangedDelayed() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WireOnXpChangedDelayed>d__16(0) { <>4__this = this }; } private void SendMessageIfRequiredRank(FullRank _, FullRank current) { //IL_0027: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) Logger.Debug($"Current rank {current}, required: {RequiredRank}"); if (PersistentDropoffQuestData.Instance.HasMessaged) { MelonDebug.Msg("Xp changed wired, but already messaged - registering dialogue now."); DropoffQuestDialogue.Register(); } else { if (current < RequiredRank) { return; } NPC val = NPC.Get<JeremyWilkinson>(); if (val != null) { if (NetworkConvenienceMethods.HostOrSingleplayer) { val.SendTextMessage("Your properties are getting busy. Want to handle more than one delivery at a time? I've got an idea. Stop by the dealership.", (Response[])null, 1f, true); } PersistentDropoffQuestData.Instance.HasMessaged = true; DropoffQuestDialogue.Register(); LevelManager.OnXPChanged -= SendMessageIfRequiredRank; } } } private static Sprite LoadEmbeddedPNG(string resourceName) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); using Stream stream = executingAssembly.GetManifestResourceStream(resourceName); if (stream == null) { return null; } byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); Sprite val = ImageUtils.LoadImageRaw(array); if ((Object)(object)val != (Object)null) { ((Object)val).name = resourceName; } return val; } private static Sprite GetIcon(ref Sprite spriteField, string resourceName) { if ((Object)(object)spriteField == (Object)null) { spriteField = LoadEmbeddedPNG(resourceName); } return spriteField; } } } namespace MultiDelivery.Quest { public class DropoffQuest : Quest { [CompilerGenerated] private sealed class <NotifyCompletion>d__21 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public DropoffQuest <>4__this; private NPC <npc>5__1; private int <i>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <NotifyCompletion>d__21(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <npc>5__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <i>5__2 = 0; break; case 1: { <>1__state = -1; int num = <i>5__2 + 1; <i>5__2 = num; break; } } if (<i>5__2 < 3 && PoolManager.Instance.Pool.Count <= <>4__this._startingCapacity) { <>2__current = (object)new WaitForSeconds(3f); <>1__state = 1; return true; } <npc>5__1 = NPC.Get<JeremyWilkinson>(); if (<npc>5__1 != null) { if (PoolManager.Instance.Pool.Count <= <>4__this._startingCapacity) { <npc>5__1.SendTextMessage("Something went wrong... Vehicle got in a car crash :(", (Response[])null, 1f, true); } else { <npc>5__1.SendTextMessage($"Vehicle added, you now can order {PoolManager.Instance.Pool.Count} more deliver{((PoolManager.Instance.Pool.Count > 1) ? "y" : "ies")} from stores.", (Response[])null, 1f, true); <npc>5__1.SendTextMessage("If you want to add more, you know where to find me.", (Response[])null, 1f, true); } } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } internal const string Name = "Expanding the Fleet"; private bool _vehicleAdded; private QuestEntry _addVehicleEntry; private int _startingCapacity; private static VehicleDropoffZone dropoffZone; private static Vector3 _dropoffZonePosition; private static readonly Logger Logger = new Logger("DropoffQuest"); protected override string Title => "Expanding the Fleet"; protected override string Description => "Bring a delivery vehicle to the dropoff zone to expand your delivery capacity"; protected override bool AutoBegin => false; protected override Sprite QuestIcon => MultiDelivery.QuestIconSprite; internal QuestState State => ((Quest)this).QuestState; protected override void OnCreated() { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0097: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) ((Registerable)this).OnCreated(); _startingCapacity = PoolManager.Instance.Pool.Count; Logger.Debug($"Starting Quest with {_startingCapacity} capacity"); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(5.1f, 4.2f, 82.58f); Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(0.55f, 4.2f, 76.56f); _dropoffZonePosition = (val + val2) / 2f; if ((Object)(object)dropoffZone != (Object)null) { Object.Destroy((Object)(object)((Component)dropoffZone).gameObject); } dropoffZone = VehicleDropoffZoneFactory.CreateZone(val, val2, 5f, (Color?)new Color(0f, 1f, 0f, 0.4f), showVisuals: true, this); Logger.Debug("Dropoff zone created. Spawning " + ((Object)dropoffZone).name); ((Quest)this).OnComplete += Completed; Logger.Debug("Wired completion event"); UpdateQuestEntries(); } private void UpdateQuestEntries() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) base.QuestEntries.Clear(); if (!_vehicleAdded) { Logger.Debug("Adding add vehicle entry"); _addVehicleEntry = ((Quest)this).AddEntry("Purchase a " + "veeper".Capitalize() + " and drive it into the green dropoff zone (top floor of the parking garage, next to storage unit)", (Vector3?)_dropoffZonePosition); _addVehicleEntry.Begin(); } Logger.Debug("Entries added!"); } public void MarkAddVehicleEntryComplete() { Logger.Debug("Marked add vehicle entry as completed"); _addVehicleEntry.Complete(); } private void Completed() { Logger.Msg("Delivery vehicle dropoff quest completed!"); MelonCoroutines.Start(NotifyCompletion()); } [IteratorStateMachine(typeof(<NotifyCompletion>d__21))] private IEnumerator NotifyCompletion() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <NotifyCompletion>d__21(0) { <>4__this = this }; } } public class DropoffQuestDialogue { private static readonly Logger Logger = new Logger("DropoffQuestDialogue"); private const string ContainerName = "DeliveryExpansion"; public static void Register() { //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Expected O, but got Unknown NPC jeremy = NPC.Get<JeremyWilkinson>(); if (jeremy == null) { Logger.Warning("Jeremy Wilkinson not found"); return; } jeremy.Dialogue.BuildAndRegisterContainer("DeliveryExpansion", (Action<DialogueContainerBuilder>)delegate(DialogueContainerBuilder c) { c.AddNode("OFFER_FIRST", "Yeah! I can help with that. If you bring a " + "veeper".Capitalize() + " to the dropoff zone, I'll add it to the fleet. This will let you handle multiple deliveries at once. Want to give it a shot?", (Action<ChoiceList>)delegate(ChoiceList ch) { ch.Add("BUY_NOW", "Sure! Can I buy one from you right now?", "CHECK_FUNDS"); ch.Add("ACCEPT", "I already have one, let's do it!", "ACCEPTED"); ch.Add("DECLINE", "Maybe later.", "DECLINED"); }); c.AddNode("OFFER_REPEAT", "Want to expand your fleet even more? Just bring another vehicle to the dropoff zone and I'll add it for you.", (Action<ChoiceList>)delegate(ChoiceList ch) { ch.Add("BUY_NOW", "Yeah, can I buy another one from you?", "CHECK_FUNDS"); ch.Add("ACCEPT", "I've got one ready!", "ACCEPTED"); ch.Add("DECLINE", "Not right now.", "DECLINED"); }); c.AddNode("CHECK_FUNDS", $"A {"veeper".Capitalize()} runs <color=#19BEF0>({MoneyManager.FormatAmount(GetVehiclePrice(), false, false)})</color>. Want to pick one up?", (Action<ChoiceList>)delegate(ChoiceList ch) { ch.Add("PURCHASE", "I'll take it. <color=#19BEF0>(" + MoneyManager.FormatAmount(GetVehiclePrice(), false, false) + ")</color>", "PURCHASE_COMPLETE"); ch.Add("NEVERMIND", "Let me think about it.", "DECLINED"); }); c.AddNode("PURCHASE_COMPLETE", "All yours. You can customize it if you want. Now just drive it to the dropoff zone - I've marked it on your map.", (Action<ChoiceList>)null); c.AddNode("NOT_ENOUGH", "You don't have enough money to buy it. Come back later.", (Action<ChoiceList>)null); c.AddNode("IN_PROGRESS", "You already have an active delivery expansion going! Just bring the vehicle to the dropoff zone. Top floor of the parking garage, next to the storage units - check your map if you forgot where it is.", (Action<ChoiceList>)null); c.AddNode("ACCEPTED", "Great! I've marked the dropoff zone on your map - top floor of the parking garage, next to the storage units. Just drive the vehicle in there when you're ready.", (Action<ChoiceList>)null); c.AddNode("DECLINED", "No worries, just let me know if you change your mind!", (Action<ChoiceList>)null); }); jeremy.Dialogue.OnChoiceSelected("ACCEPT", (Action)OnAcceptQuest); jeremy.Dialogue.OnChoiceSelected("BUY_NOW", (Action)OnAcceptQuest); jeremy.Dialogue.OnChoiceSelected("DECLINE", (Action)delegate { Logger.Debug("Player declined quest"); }); jeremy.Dialogue.OnChoiceSelected("NEVERMIND", (Action)delegate { Logger.Debug("Player cancelled purchase"); }); jeremy.Dialogue.OnChoiceSelected("PURCHASE", (Action)delegate { //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) float vehiclePrice = GetVehiclePrice(); float onlineBalance = Money.GetOnlineBalance(); if (onlineBalance >= vehiclePrice) { Money.CreateOnlineTransaction("veeper".Capitalize() + " purchase", 0f - vehiclePrice, 1f, "Bought as a part of delivery expansion"); Logger.Msg($"Player purchased {"veeper"} for ${vehiclePrice:F2}"); Jeremy component = jeremy.gameObject.GetComponent<Jeremy>(); if ((Object)(object)component != (Object)null) { Dealership dealership = component.Dealership; if ((Object)(object)dealership != (Object)null) { dealership.SpawnVehicle("veeper"); return; } } NetworkSingleton<VehicleManager>.Instance.SpawnVehicle("veeper", new Vector3(9.92f, 0.54f, -33.55f), Quaternion.identity, true); } else { jeremy.Dialogue.JumpTo("DeliveryExpansion", "NOT_ENOUGH", false); } }); DialogueInjector.Register(new DialogueInjection(jeremy.ID, "Dealership_Salesman_Sell", "cc0d838e-2824-4fd5-907d-798dc0195c16", "OFFER_FIRST", "ASK_EXPANSION", "Can I expand my delivery capacity?", (Action)delegate { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 DropoffQuest dropoffQuest = QuestManager.GetQuestByName("Expanding the Fleet") as DropoffQuest; bool flag = PoolManager.Instance.Pool.Count > 0; bool flag2 = dropoffQuest != null && (int)dropoffQuest.State == 1; Logger.Debug($"Quest state - Active: {flag2}, Has expanded: {flag}"); string text = (flag2 ? "IN_PROGRESS" : (flag ? "OFFER_REPEAT" : "OFFER_FIRST")); Logger.Debug($"Jumping to '{"DeliveryExpansion"}', node '{text}'"); jeremy.Dialogue.JumpTo("DeliveryExpansion", text, false); })); Logger.Msg("Registered delivery expansion dialogue"); } private static void OnAcceptQuest() { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Invalid comparison between Unknown and I4 if (!(QuestManager.GetQuestByName("Expanding the Fleet") is DropoffQuest dropoffQuest)) { if (QuestManager.CreateQuest<DropoffQuest>((string)null) is DropoffQuest dropoffQuest2) { ((Quest)dropoffQuest2).Begin(); } Logger.Msg("Started delivery expansion quest"); } else if (dropoffQuest != null && (int)dropoffQuest.State == 2) { ((Quest)dropoffQuest).Begin(); Logger.Msg("Restarted delivery expansion quest"); } } private static float GetVehiclePrice() { LandVehicle vehiclePrefab = NetworkSingleton<VehicleManager>.Instance.GetVehiclePrefab("veeper"); return (vehiclePrefab != null) ? vehiclePrefab.VehiclePrice : 5000f; } } [RegisterTypeInIl2Cpp] public class VehicleDropoffZone : MonoBehaviour { private VehicleDetector _detector; private Logger _logger; private GameObject _visualPlane; private Material _visualMaterial; private Color _baseColor; private DropoffQuest? _quest; public Vector3 Corner1 { get; private set; } public Vector3 Corner2 { get; private set; } public bool ShowVisuals { get; set; } = true; private void Awake() { _logger = new Logger("VehicleDropoffZone"); } private void Start() { _detector = ((Component)this).gameObject.GetComponent<VehicleDetector>(); if ((Object)(object)_detector == (Object)null) { _detector = ((Component)this).gameObject.AddComponent<VehicleDetector>(); } } private void Update() { if (_detector.vehicles.Count <= 0) { return; } foreach (LandVehicle item in _detector.vehicles.AsEnumerable<LandVehicle>()) { OnVehicleEntered(item); } } private void OnVehicleEntered(LandVehicle vehicle) { _logger.Debug("Vehicle entered dropoff zone: " + vehicle.vehicleName); if (!IsCorrectVehicleType(vehicle)) { if (Time.frameCount % 60 == 0) { _logger.Warning("Wrong vehicle type: " + vehicle.vehicleCode); } return; } if (vehicle.IsOccupied) { _logger.Msg("Ejecting player from vehicle"); vehicle.ExitVehicle(); } ProcessAndAddToPool(vehicle); _detector.vehicles.Remove(vehicle); Object.Destroy((Object)(object)((Component)this).gameObject); } private static bool IsCorrectVehicleType(LandVehicle vehicle) { return vehicle.vehicleCode == "veeper"; } private void ProcessAndAddToPool(LandVehicle vehicle) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) _logger.Debug($"Adding vehicle to pool: {vehicle.GUID}"); DeliveryVehicle val = ((Component)vehicle).GetComponent<DeliveryVehicle>(); if ((Object)(object)val == (Object)null) { Guid gUID = vehicle.GUID; val = new DeliveryVehicleBuilder().WithLandVehicle(vehicle).WithGuid(gUID).Build(); } vehicle.IsPlayerOwned = false; vehicle.SetIsPlayerOwned((NetworkConnection)null, false); vehicle.SetVisible(false); vehicle.IsPhysicallySimulated = false; ((Component)vehicle).transform.position = new Vector3(0f, -100f, 0f); PoolManager.Instance.AddToSaveData(val); PoolManager.Instance.AddToPool(val); _quest?.MarkAddVehicleEntryComplete(); _logger.Msg($"Vehicle added to pool. Total vehicles: {PoolManager.Instance.Pool.Count}"); } public void SetupZone(Vector3 corner1, Vector3 corner2, float height = 5f, Color? visualColor = null) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_003e: 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_008a: 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_0115: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) Corner1 = corner1; Corner2 = corner2; Vector3 val = (corner1 + corner2) / 2f; Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(Mathf.Abs(corner2.x - corner1.x), height, Mathf.Abs(corner2.z - corner1.z)); ((Component)this).transform.position = val; BoxCollider val3 = ((Component)this).gameObject.GetComponent<BoxCollider>(); if ((Object)(object)val3 == (Object)null) { val3 = ((Component)this).gameObject.AddComponent<BoxCollider>(); } ((Collider)val3).isTrigger = true; val3.size = val2; val3.center = Vector3.zero; if (ShowVisuals) { _baseColor = (Color)(((??)visualColor) ?? new Color(0f, 1f, 1f, 0.3f)); CreateVisualPlane(val2, _baseColor); } _logger.Debug($"Dropoff zone created: Center={val}, Size={val2}"); } private void CreateVisualPlane(Vector3 size, Color color) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) _visualPlane = GameObject.CreatePrimitive((PrimitiveType)3); ((Object)_visualPlane).name = "DropoffZoneVisual"; _visualPlane.transform.SetParent(((Component)this).transform); _visualPlane.transform.localPosition = Vector3.zero; _visualPlane.transform.localScale = new Vector3(size.x, 0.1f, size.z); Collider component = _visualPlane.GetComponent<Collider>(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } ApplyDebugMaterial(_visualPlane, color); } private void ApplyDebugMaterial(GameObject obj, Color color) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_006b: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: 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_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) Renderer component = obj.GetComponent<Renderer>(); if ((Object)(object)component == (Object)null) { return; } Shader val = Shader.Find("Universal Render Pipeline/Lit"); if (!((Object)(object)val == (Object)null)) { _visualMaterial = new Material(val); if (_visualMaterial.HasProperty("_Surface")) { _visualMaterial.SetFloat("_Surface", 1f); } if (color.a <= 0f) { color.a = 0.3f; } if (_visualMaterial.HasProperty("_BaseColor")) { _visualMaterial.SetColor("_BaseColor", color); } if (_visualMaterial.HasProperty("_EmissionColor")) { _visualMaterial.EnableKeyword("_EMISSION"); _visualMaterial.SetColor("_EmissionColor", new Color(color.r, color.g, color.b) * 1.5f); } _visualMaterial.SetInt("_ZWrite", 0); _visualMaterial.renderQueue = 3000; component.material = _visualMaterial; } } public void SetVisualsEnabled(bool enabled) { ShowVisuals = enabled; if ((Object)(object)_visualPlane != (Object)null) { _visualPlane.SetActive(enabled); } } [HideFromIl2Cpp] public void SetQuest(DropoffQuest quest) { _quest = quest; } private void OnDestroy() { if ((Object)(object)_visualPlane != (Object)null) { Object.Destroy((Object)(object)_visualPlane); } } } public static class VehicleDropoffZoneFactory { public static VehicleDropoffZone CreateZone(Vector3 corner1, Vector3 corner2, float height = 5f, Color? visualColor = null, bool showVisuals = true, DropoffQuest? attachedQuest = null) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_001d: 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) GameObject val = new GameObject("VehicleDropoffZone"); VehicleDropoffZone vehicleDropoffZone = val.AddComponent<VehicleDropoffZone>(); vehicleDropoffZone.ShowVisuals = showVisuals; vehicleDropoffZone.SetupZone(corner1, corner2, height, visualColor); if (attachedQuest != null) { vehicleDropoffZone.SetQuest(attachedQuest); } return vehicleDropoffZone; } public static VehicleDropoffZone CreateZoneNear(Transform reference, Vector3 offset, Vector3 size, Color? visualColor = null) { //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_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) Vector3 val = reference.position + offset; Vector3 corner = val - size / 2f; Vector3 corner2 = val + size / 2f; return CreateZone(corner, corner2, size.y, visualColor); } } } namespace MultiDelivery.Pool { [HarmonyPatch(typeof(DeliveryManager))] internal static class ActiveDeliveryPatch { private static readonly Logger Logger = new Logger("ActiveDeliveryPatch"); [HarmonyPatch("GetActiveShopDelivery")] [HarmonyPostfix] private static void AllowIfPoolAssigmentAvailable(DeliveryManager __instance, DeliveryShop shop, ref DeliveryInstance __result) { if (__result == null) { return; } if (PoolManager.Instance.BaseVehicleAllocationsForShop.TryGetValue(shop.MatchingShopInterfaceName, out var value)) { if (Time.frameCount % 30 == 0) { Logger.Debug($"Base: {value}"); } if (!value) { __result = null; return; } DeliveryVehicle firstFree = PoolManager.Instance.GetFirstFree(); if (!((Object)(object)firstFree == (Object)null)) { Logger.Debug("Free pool vehicle found"); __result = null; } } else { DeliveryVehicle firstFree2 = PoolManager.Instance.GetFirstFree(); if (!((Object)(object)firstFree2 == (Object)null)) { Logger.Debug("Free pool vehicle found"); __result = null; } } } [HarmonyPatch("SendDelivery")] [HarmonyPostfix] private static void AllocateVehicle(DeliveryManager __instance, DeliveryInstance delivery) { PoolManager.Instance.BaseVehicleAllocationsForShop.TryAdd(delivery.StoreName, value: false); Logger.Debug($"Base allocation: {PoolManager.Instance.BaseVehicleAllocationsForShop[delivery.StoreName]}"); if (!PoolManager.Instance.BaseVehicleAllocationsForShop[delivery.StoreName]) { Logger.Debug("Base vehicle allocating"); PoolManager.Instance.BaseVehicleAllocationsForShop[delivery.StoreName] = true; NetworkConvenienceMethods.NotifyBaseAllocation(delivery.StoreName, isAllocated: true); } else { PoolManager.Instance.GetOrAllocateFirstFree(delivery.DeliveryID); Logger.Debug("Allocated for " + delivery.DeliveryID); } } } [HarmonyPatch(typeof(DeliveryInstance))] internal static class DeliveryInstancePatches { [HarmonyPatch("SetStatus")] [HarmonyPrefix] private static bool UsePoolSetStatus(DeliveryInstance __instance, EDeliveryStatus status) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Invalid comparison between Unknown and I4 //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Invalid comparison between Unknown and I4 Console.Log(Object.op_Implicit($"Setting delivery status to {status} for delivery {__instance.DeliveryID}"), (Object)null); __instance.Status = status; ShopInterface shopInterface = NetworkSingleton<DeliveryManager>.Instance.GetShopInterface(__instance.StoreName); if ((int)status != 2) { if ((int)status == 3) { if ((Object)(object)__instance.ActiveVehicle == (Object)(object)shopInterface.DeliveryVehicle) { PoolManager.Instance.BaseVehicleAllocationsForShop[__instance.StoreName] = false; NetworkConvenienceMethods.NotifyBaseAllocation(__instance.StoreName, isAllocated: false); } else { PoolManager.Instance.FreeAllocation(__instance.DeliveryID); } if ((Object)(object)__instance.ActiveVehicle != (Object)null) { __instance.ActiveVehicle.Deactivate(); } UnityEvent onDeliveryCompleted = __instance.onDeliveryCompleted; if (onDeliveryCompleted != null) { onDeliveryCompleted.Invoke(); } } } else { if (PoolManager.Instance.Allocations.TryGetValue(__instance.DeliveryID, out DeliveryVehicle value)) { __instance.ActiveVehicle = value; } else { __instance.ActiveVehicle = shopInterface.DeliveryVehicle; } __instance.ActiveVehicle.Activate(__instance); } return false; } [HarmonyPatch("AddItemsToDeliveryVehicle")] [HarmonyPrefix] private static bool UsePoolAddItemsToDeliveryVehicle(DeliveryInstance __instance) { ShopInterface shopInterface = NetworkSingleton<DeliveryManager>.Instance.GetShopInterface(__instance.StoreName); if (!PoolManager.Instance.Allocations.TryGetValue(__instance.DeliveryID, out DeliveryVehicle value)) { value = ((shopInterface != null) ? shopInterface.DeliveryVehicle : null); } Il2CppReferenceArray<StringIntPair> items = __instance.Items; foreach (StringIntPair item2 in (Il2CppArrayBase<StringIntPair>)(object)items) { ItemDefinition item = Registry.GetItem(item2.String); int num = item2.Int; while (num > 0) { int num2 = Mathf.Min(num, ((BaseItemDefinition)item).StackLimit); num -= num2; ItemInstance defaultInstance = item.GetDefaultInstance(num2); value.Vehicle.Storage.InsertItem(defaultInstance, Object.op_Implicit((Object)(object)item)); } } return false; } } [HarmonyPatch(typeof(DeliveryVehicle))] internal class DeliveryVehiclePatch { [HarmonyPatch("Deactivate")] [HarmonyPostfix] private static void NullActiveDelivery(DeliveryVehicle __instance) { DeliveryInstance activeDelivery = __instance.ActiveDelivery; object obj; if (activeDelivery == null) { obj = null; } else { LoadingDock loadingDock = activeDelivery.LoadingDock; obj = ((loadingDock != null) ? loadingDock.VehicleDetector : null); } if ((Object)obj != (Object)null) { __instance.ActiveDelivery.LoadingDock.SetOccupant((LandVehicle)null); __instance.ActiveDelivery.LoadingDock.VehicleDetector.Clear(); } if (__instance.ActiveDelivery != null) { __instance.ActiveDelivery = null; } } } [HarmonyPatch(typeof(DeliveriesLoader))] internal static class LoaderPatch { private static readonly Logger Logger = new Logger("LoaderPatch"); [HarmonyPatch("Load")] [HarmonyPrefix] private static bool Load(DeliveriesLoader __instance, string mainPath) { bool flag = false; string text = default(string); if (((Loader)__instance).TryLoadFile(Path.Combine(mainPath, "Deliveries"), ref text, true) || ((Loader)__instance).TryLoadFile(mainPath, ref text, true)) { DeliveriesData val = null; try { val = JsonUtility.FromJson<DeliveriesData>(text); } catch (Exception ex) { Debug.LogError(Object.op_Implicit("Error loading data: " + ex.Message)); } if (val != null && val.ActiveDeliveries != null) { LoadDelivery(val); if (val.DeliveryVehicles != null) { flag = true; VehicleData[] array = Il2CppArrayBase<VehicleData>.op_Implicit((Il2CppArrayBase<VehicleData>)(object)val.DeliveryVehicles); VehicleData[] array2 = array; foreach (VehicleData data in array2) { LoadVehicle(data, mainPath); } } } } if (!flag && Directory.Exists(mainPath)) { Console.Log(Object.op_Implicit("Loading legacy delivery vehicles at: " + mainPath), (Object)null); string text2 = Path.Combine(mainPath, "DeliveryVehicles"); List<DirectoryInfo> directories = ((Loader)__instance).GetDirectories(text2); for (int j = 0; j < directories.Count; j++) { __instance.LoadVehicle(((FileSystemInfo)directories[j]).FullName); } } return false; } private static void LoadVehicle(VehicleData data, string path) { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) VehicleData data2 = data; Logger.Debug("Processing GUID " + data2.GUID); DeliveryVehicle? obj = ((IEnumerable<DeliveryVehicle>)PoolManager.Instance.Pool).FirstOrDefault((Func<DeliveryVehicle, bool>)delegate(DeliveryVehicle dv) { //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) Guid gUID = dv.Vehicle.GUID; return ((object)(Guid)(ref gUID)).ToString() == data2.GUID; }); LandVehicle val = ((obj != null) ? obj.Vehicle : null); if ((Object)(object)val == (Object)null) { Logger.Debug("GUID " + data2.GUID + " not found in Pool, lookup via GUIDManager"); val = GUIDManager.GetObject<LandVehicle>(new Guid(data2.GUID)); } if ((Object)(object)val == (Object)null) { Logger.Error("Vehicle not found with GUID", data2.GUID); Console.LogError(Object.op_Implicit("LoadVehicle: Vehicle not found with GUID " + data2.GUID), (Object)null); } else { LoadVehicle(val, data2, path); } } private static void LoadVehicle(LandVehicle vehicle, VehicleData data, string containerPath) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) Logger.Debug($"Processing vehicle {((Object)vehicle).name} with GUID {vehicle.GUID}"); if ((Object)(object)vehicle.Storage != (Object)null) { if (data.VehicleContents != null && data.VehicleContents.Items != null) { DeserializedItemSet val = default(DeserializedItemSet); if (ItemSet.TryDeserialize(data.VehicleContents, ref val)) { val.LoadTo(vehicle.Storage.ItemSlots); } } else if (File.Exists(Path.Combine(containerPath, "Contents.json"))) { Console.LogWarning(Object.op_Implicit("Loading legacy vehicle contents."), (Object)null); string text = default(string); DeserializedItemSet val2 = default(DeserializedItemSet); if (vehicle.Loader.TryLoadFile(containerPath, "Contents", ref text) && ItemSet.TryDeserialize(text, ref val2)) { val2.LoadTo(vehicle.Storage.ItemSlots); } } } if (data.SpraySurfaces == null) { return; } try { for (int i = 0; i < data.SpraySurfaces.Count; i++) { if (((Il2CppArrayBase<SpraySurface>)(object)vehicle._spraySurfaces).Length > i) { SpraySurface obj = ((Il2CppArrayBase<SpraySurface>)(object)vehicle._spraySurfaces)[i]; if (obj != null) { obj.Set((NetworkConnection)null, ((Il2CppObjectBase)data.SpraySurfaces[i].Strokes.ToArray()).Cast<Il2CppReferenceArray<SprayStroke>>(), data.SpraySurfaces[i].ContainsCartelGraffiti); } } } } catch (Exception ex) { Logger.Error("Exception thrown while loading saved graffities", ex); } } private static void LoadDelivery(DeliveriesData data) { if (data == null) { return; } if (data.ActiveDeliveries != null) { DeliveryInstance[] array = Il2CppArrayBase<DeliveryInstance>.op_Implicit((Il2CppArrayBase<DeliveryInstance>)(object)data.ActiveDeliveries); DeliveryInstance[] array2 = array; foreach (DeliveryInstance val in array2) { NetworkSingleton<DeliveryManager>.Instance.SendDelivery(val); } } if (data.DeliveryHistory != null) { foreach (DeliveryReceipt item in (Il2CppArrayBase<DeliveryReceipt>)(object)data.DeliveryHistory) { NetworkSingleton<DeliveryManager>.Instance._deliveryHistory.Add(item); } } if (data.DisplayedDeliveryHistory == null) { return; } foreach (DeliveryReceipt item2 in (Il2CppArrayBase<DeliveryReceipt>)(object)data.DisplayedDeliveryHistory) { NetworkSingleton<DeliveryManager>.Instance._displayedDeliveryHistory.Add(item2); } } } public class PoolManager { private static readonly Logger Logger = new Logger("PoolManager"); public static PoolManager Instance { get; } = new PoolManager(); public HashSet<DeliveryVehicle> Pool { get; } = new HashSet<DeliveryVehicle>(); internal Dictionary<string, DeliveryVehicle> Allocations { get; } = new Dictionary<string, DeliveryVehicle>(); internal Dictionary<string, bool> BaseVehicleAllocationsForShop { get; } = new Dictionary<string, bool>(); public void AddToPool(DeliveryVehicle deliveryVehicle, bool notify = true) { Pool.Add(deliveryVehicle); if (notify) { NetworkConvenienceMethods.NotifyVehicleAdded(deliveryVehicle); } } public void AddToSaveData(DeliveryVehicle deliveryVehicle) { if ((Object)(object)deliveryVehicle == (Object)null) { throw new ArgumentNullException("deliveryVehicle"); } VehicleSave.Instance.AddVehicle(deliveryVehicle.Vehicle); NetworkConvenienceMethods.NotifyVehicleCreated(deliveryVehicle); } public DeliveryVehicle? GetFirstFree() { DeliveryVehicle val = ((IEnumerable<DeliveryVehicle>)Pool).FirstOrDefault((Func<DeliveryVehicle, bool>)((DeliveryVehicle dv) => dv.ActiveDelivery == null && !Allocations.ContainsValue(dv))); if (Time.frameCount % 30 == 0) { Logger.Debug("Pool lookup: " + (((Object)(object)val == (Object)null) ? "null" : "not null")); } return val; } public DeliveryVehicle GetOrAllocateFirstFree(string deliveryId) { Logger.Debug("GetOrAllocateFirstFree called for: " + deliveryId); if (Allocations.TryGetValue(deliveryId, out DeliveryVehicle value)) { Logger.Debug("Already allocated, returning existing"); return value; } DeliveryVehicle firstFree = GetFirstFree(); if ((Object)(object)firstFree == (Object)null) { Logger.Debug($"No free vehicle found! Pool count: {Pool.Count}, Allocations count: {Allocations.Count}"); foreach (KeyValuePair<string, DeliveryVehicle> allocation in Allocations) { Logger logger = Logger; object[] array = new object[1]; string key = allocation.Key; DeliveryInstance activeDelivery = allocation.Value.ActiveDelivery; array[0] = "Allocation: " + key + " -> Vehicle has ActiveDelivery: " + (((activeDelivery != null) ? activeDelivery.DeliveryID : null) ?? "null"); logger.Debug(array); } throw new ArgumentException("Tried to allocate a non-free vehicle"); } Allocations.Add(deliveryId, firstFree); Logger.Debug("Allocated new vehicle for " + deliveryId + ", vehicle: " + firstFree.GUID); NetworkConvenienceMethods.NotifyAllocation(deliveryId, firstFree, isAllocated: true); return firstFree; } public void FreeAllocation(string deliveryId) { Logger.Debug("Free custom allocation: " + deliveryId); if (Allocations.TryGetValue(deliveryId, out DeliveryVehicle value)) { Allocations.Remove(deliveryId); NetworkConvenienceMethods.NotifyAllocation(deliveryId, value, isAllocated: false); } } } [HarmonyPatch(typeof(Wheel))] internal class WheelPatch { [HarmonyPatch("OnWeatherChange")] [HarmonyPrefix] private static bool ExitIfNull(Wheel __instance, WeatherConditions newConditions) { if ((Object)(object)((__instance != null) ? __instance.vehicle : null) == (Object)null) { return false; } if (newConditions != null) { _ = newConditions.Rainy; if (0 == 0) { return true; } } return false; } } [HarmonyPatch(typeof(DeliveryVehicle))] internal static class DeliveryVehicleAwakePatch { [HarmonyPatch("Awake")] [HarmonyPrefix] private static bool ExitIfNull(DeliveryVehicle __instance) { Guid val = default(Guid); if (Guid.TryParse(__instance.GUID, ref val)) { return true; } if ((Object)(object)((Component)__instance).GetComponent<LandVehicle>() == (Object)null) { return false; } __instance.Vehicle = ((Component)__instance).GetComponent<LandVehicle>(); __instance.Deactivate(); return false; } } } namespace MultiDelivery.Persistence { public class PersistentDropoffQuestData : Saveable { [SaveableField("MessageData")] public bool HasMessaged; public static PersistentDropoffQuestData Instance { get; private set; } = new PersistentDropoffQuestData(); public PersistentDropoffQuestData() { Instance = this; } } public class VehicleSave : Saveable { [CompilerGenerated] private sealed class <DeferredSetColor>d__12 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public LandVehicle vehicle; public EVehicleColor color; public VehicleSave <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DeferredSetColor>d__12(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0086: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; goto IL_0044; case 1: <>1__state = -1; goto IL_0044; case 2: { <>1__state = -1; vehicle.ApplyColor(color); return false; } IL_0044: if ((Object)(object)Player.Local == (Object)null || (Object)(object)((Component)Player.Local).gameObject == (Object)null) { <>2__current = null; <>1__state = 1; return true; } <>2__current = null; <>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(); } } [SaveableField("VehicleSaveData")] private List<VehicleSaveDto> _dtos = new List<VehicleSaveDto>(); private static readonly Logger Logger = new Logger("VehicleSave"); private static Transform _parent; public override SaveableLoadOrder LoadOrder => (SaveableLoadOrder)0; public static VehicleSave Instance { get; set; } = new VehicleSave(); public VehicleSave() { Instance = this; } public void AddVehicle(LandVehicle vehicle) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) VehicleSaveDto vehicleSaveDto = new VehicleSaveDto(); Guid gUID = vehicle.GUID; vehicleSaveDto.Guid = ((object)(Guid)(ref gUID)).ToString(); vehicleSaveDto.VehicleType = vehicle.VehicleCode; vehicleSaveDto.Color = vehicle.Color.displayedColor; VehicleSaveDto item = vehicleSaveDto; if (!_dtos.Contains(item)) { _dtos.Add(item); } } protected override void OnLoaded() { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) Melon<MultiDelivery>.Logger.Msg($"VehicleSave.OnLoaded: Loading {_dtos.Count} vehicles"); if ((Object)(object)_parent == (Object)null) { GameObject val = GameObject.Find("VehiclePool"); if ((Object)(object)val == (Object)null) { val = new GameObject("VehiclePool"); } _parent = val.transform; } Guid guid = default(Guid); for (int i = 0; i < _dtos.Count; i++) { Logger.Debug($"Loading vehicle {i}: {_dtos[i].Guid}"); ((Guid)(ref guid))..ctor(_dtos[i].Guid); LandVehicle val2 = new LandVehicleBuilder().WithVehicleCode(_dtos[i].VehicleType).WithVehicleName($"Additional Delivery Vehicle {i + 1}").WithGuid(guid) .WithColor(_dtos[i].Color) .WithParent(_parent) .Build(); MelonCoroutines.Start(DeferredSetColor(val2, _dtos[i].Color)); Logger.Debug($"Built LandVehicle: {val2.vehicleName}, ObjectId: {((NetworkBehaviour)val2).ObjectId}"); DeliveryVehicle val3 = new DeliveryVehicleBuilder().WithLandVehicle(val2).WithGuid(guid).Build(); Logger.Debug("Built DeliveryVehicle: " + val3.GUID); PoolManager.Instance.AddToPool(val3); Logger.Debug($"Added to pool. Pool count now: {PoolManager.Instance.Pool.Count}"); } Logger.Msg($"VehicleSave.OnLoaded complete. Final pool count: {PoolManager.Instance.Pool.Count}"); } [IteratorStateMachine(typeof(<DeferredSetColor>d__12))] private IEnumerator DeferredSetColor(LandVehicle vehicle, EVehicleColor color) { //IL_0015: 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) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DeferredSetColor>d__12(0) { <>4__this = this, vehicle = vehicle, color = color }; } } public record VehicleSaveDto { public string Guid { get; set; } public string VehicleType { get; set; } public EVehicleColor Color { get; set; } [CompilerGenerated] protected virtual bool PrintMembers(StringBuilder builder) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) RuntimeHelpers.EnsureSufficientExecutionStack(); builder.Append("Guid = "); builder.Append((object?)Guid); builder.Append(", VehicleType = "); builder.Append((object?)VehicleType); builder.Append(", Color = "); EVehicleColor color = Color; builder.Append(((object)(EVehicleColor)(ref color)).ToString()); return true; } } } namespace MultiDelivery.Network { public class DeliveryNetworkManager { [CompilerGenerated] private sealed class <>c__DisplayClass22_0 { public DeliveryNetworkManager <>4__this; public VehicleAddedMessage message; internal bool <OnVehicleAdded>b__2() { return (Object)(object)<>4__this.FindLandVehicleByObjectId(message.ObjectId) != (Object)null; } } [CompilerGenerated] private sealed class <>c__DisplayClass23_0 { public DeliveryNetworkManager <>4__this; public VehicleCreatedMessage message; internal bool <OnVehicleCreated>b__2() { return (Object)(object)<>4__this.FindLandVehicleByObjectId(message.ObjectId) != (Object)null; } } [CompilerGenerated] private sealed class <>c__DisplayClass25_0 { public VehiclePoolSyncResponse message; public DeliveryNetworkManager <>4__this; public Func<VehiclePoolSyncResponse.VehicleData, bool> <>9__3; internal bool <OnPoolSyncResponse>b__2() { return message.Vehicles.All((VehiclePoolSyncResponse.VehicleData v) => (Object)(object)<>4__this.FindLandVehicleByObjectId(v.ObjectId) != (Object)null); } internal bool <OnPoolSyncResponse>b__3(VehiclePoolSyncResponse.VehicleData v) { return (Object)(object)<>4__this.FindLandVehicleByObjectId(v.ObjectId) != (Object)null; } } [CompilerGenerated] private sealed class <>c__DisplayClass26_0 { public VehicleAllocationMessage message; public DeliveryNetworkManager <>4__this; public Func<DeliveryVehicle, bool> <>9__3; internal bool <OnVehicleAllocation>b__2() { return (Object)(object)((IEnumerable<DeliveryVehicle>)PoolManager.Instance.Pool).FirstOrDefault((Func<DeliveryVehicle, bool>)((DeliveryVehicle v) => v.GUID == message.VehicleGuid)) != (Object)null; } internal bool <OnVehicleAllocation>b__3(DeliveryVehicle v) { return v.GUID == message.VehicleGuid; } internal bool <OnVehicleAllocation>b__4(DeliveryVehicle v) { return v.GUID == message.VehicleGuid; } } [CompilerGenerated] private sealed class <ExponentialBackoff>d__34 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Func<bool> predicate; public float initialDelay; public float finalDelay; public float timeout; private float <delay>5__1; private float <elapsed>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ExponentialBackoff>d__34(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <delay>5__1 = initialDelay; <elapsed>5__2 = 0f; break; case 1: <>1__state = -1; <elapsed>5__2 += <delay>5__1; <delay>5__1 = Mathf.Min(<delay>5__1 * 2f, finalDelay); break; } if (!predicate() && <elapsed>5__2 < timeout) { <>2__current = (object)new WaitForSeconds(<delay>5__1); <>1__state = 1; return true; } 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 SteamNetworkClient _client; private readonly Logger _logger; private const string ModDataKey = "MultiDelivery_Version"; private const string ModVersion = "1.0.0"; private bool IsInLobby { get { SteamNetworkClient client = _client; return client != null && client.IsInLobby; } } private bool IsHost { get { SteamNetworkClient client = _client; return client != null && client.IsHost; } } private bool IsSingleplayer => !IsInLobby; internal bool HostOrSingleplayer => IsHost || IsSingleplayer; public DeliveryNetworkManager() { _logger = new Logger("Network", LogLevel.NetworkTrace); } public bool Initialize() { //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_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown try { NetworkRules val = new NetworkRules { EnableRelay = true, AcceptOnlyFriends = false }; _client = new SteamNetworkClient(val); if (!_client.Initialize()) { _logger.Error("Failed to initialize SteamNetworkClient"); return false; } RegisterMessageHandlers(); SubscribeToEvents(); _logger.Msg("Network manager initialized successfully"); return true; } catch (Exception value) { _client = null; _logger.Error($"Failed to initialize network manager: {value}"); return false; } } private void RegisterMessageHandlers() { _client.RegisterMessageHandler<VehicleAddedMessage>((Action<VehicleAddedMessage, CSteamID>)OnVehicleAdded); _client.RegisterMessageHandler<VehicleCreatedMessage>((Action<VehicleCreatedMessage, CSteamID>)OnVehicleCreated); _client.RegisterMessageHandler<VehiclePoolSyncRequest>((Action<VehiclePoolSyncRequest, CSteamID>)OnPoolSyncRequest); _client.RegisterMessageHandler<VehiclePoolSyncResponse>((Action<VehiclePoolSyncResponse, CSteamID>)OnPoolSyncResponse); _client.RegisterMessageHandler<VehicleAllocationMessage>((Action<VehicleAllocationMessage, CSteamID>)OnVehicleAllocation); _client.RegisterMessageHandler<BaseVehicleAllocationMessage>((Action<BaseVehicleAllocationMessage, CSteamID>)OnBaseVehicleAllocation); } private void SubscribeToEvents() { _client.OnLobbyCreated += OnLobbyCreated; _client.OnLobbyJoined += OnLobbyJoined; _client.OnMemberJoined += OnMemberJoined; _client.OnLobbyLeft += OnLobbyLeft; } public void Update() { SteamNetworkClient client = _client; if (client != null) { client.ProcessIncomingMessages(); } } public void Dispose() { SteamNetworkClient client = _client; if (client != null) { client.Dispose(); } } public async void BroadcastVehicleAdded(DeliveryVehicle vehicle) { if (!IsSingleplayer) { VehicleAddedMessage message = new VehicleAddedMessage { ObjectId = ((NetworkBehaviour)vehicle.Vehicle).ObjectId, VehicleGuid = vehicle.GUID, VehicleName = vehicle.Vehicle.vehicleName, VehicleCode = vehicle.Vehicle.VehicleCode, VehicleColor = (int)vehicle.Vehicle.Color.displayedColor }; _logger.Msg($"Broadcasting vehicle added: ObjectId={message.ObjectId}, GUID={message.VehicleGuid}"); await _client.BroadcastMessageAsync((P2PMessage)(object)message); } } public async void BroadcastVehicleCreated(DeliveryVehicle vehicle) { if (!IsSingleplayer && !IsHost) { VehicleCreatedMessage message = new VehicleCreatedMessage { ObjectId = ((NetworkBehaviour)vehicle.Vehicle).ObjectId, VehicleGuid = vehicle.GUID }; _logger.Msg($"Broadcasting vehicle created: ObjectId={message.ObjectId}"); await _client.BroadcastMessageAsync((P2PMessage)(object)message); } } public async void BroadcastVehicleAllocation(string deliveryId, DeliveryVehicle vehicle, bool isAllocated) { if (!IsSingleplayer) { VehicleAllocationMessage message = new VehicleAllocationMessage { DeliveryId = deliveryId, VehicleGuid = vehicle.GUID, IsAllocated = isAllocated }; _logger.Msg($"Broadcasting allocation: Delivery={deliveryId}, Vehicle={vehicle.GUID}, Allocated={isAllocated}"); await _client.BroadcastMessageAsync((P2PMessage)(object)message); } } public async void BroadcastBaseVehicleAllocation(string shopName, bool isAllocated) { if (!IsSingleplayer) { BaseVehicleAllocationMessage message = new BaseVehicleAllocationMessage { ShopName = shopName, IsAllocated = isAllocated }; _logger.Msg($"Broadcasting base allocation: Shop={shopName}, Allocated={isAllocated}"); await _client.BroadcastMessageAsync((P2PMessage)(object)message); } } private void OnVehicleAdded(VehicleAddedMessage message, CSteamID cSteamID) { <>c__DisplayClass22_0 CS$<>8__locals0 = new <>c__DisplayClass22_0(); CS$<>8__locals0.<>4__this = this; CS$<>8__locals0.message = message; _logger.Msg($"Received VehicleAdded: ObjectId={CS$<>8__locals0.message.ObjectId}, GUID={CS$<>8__locals0.message.VehicleGuid}"); MelonCoroutines.Start(ProcessMessage()); [IteratorStateMachine(typeof(<>c__DisplayClass22_0.<<OnVehicleAdded>g__ProcessMessage|0>d))] IEnumerator ProcessMessage() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <>c__DisplayClass22_0.<<OnVehicleAdded>g__ProcessMessage|0>d(0) { <>4__this = CS$<>8__locals0 }; } } private void OnVehicleCreated(VehicleCreatedMessage message, CSteamID senderId) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) <>c__DisplayClass23_0 CS$<>8__locals0 = new <>c__DisplayClass23_0(); CS$<>8__locals0.<>4__this = this; CS$<>8__locals0.message = message; if (IsHost) { _logger.Msg($"Received vehicle created message from {senderId}"); MelonCoroutines.Start(ProcessMessage()); } [IteratorStateMachine(typeof(<>c__DisplayClass23_0.<<OnVehicleCreated>g__ProcessMessage|0>d))] IEnumerator ProcessMessage() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <>c__DisplayClass23_0.<<OnVehicleCreated>g__ProcessMessage|0>d(0) { <>4__this = CS$<>8__locals0 }; } } private async void OnPoolSyncRequest(VehiclePoolSyncRequest message, CSteamID senderId) { //IL_0020: 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) if (!IsHost) { return; } _logger.Msg($"Received pool sync request from {senderId}"); try { VehiclePoolSyncResponse response = new VehiclePoolSyncResponse(); foreach (DeliveryVehicle vehicle in PoolManager.Instance.Pool) { response.Vehicles.Add(new VehiclePoolSyncResponse.VehicleData { ObjectId = ((NetworkBehaviour)vehicle.Vehicle).ObjectId, Guid = vehicle.GUID, Name = vehicle.Vehicle.vehicleName, Code = vehicle.Vehicle.VehicleCode, Color = (int)vehicle.Vehicle.Color.displayedColor }); } _logger.Msg($"Sending pool sync with {response.Vehicles.Count} vehicles"); await _client.SendMessageToPlayerAsync(senderId, (P2PMessage)(object)response); } catch (Exception ex) { _logger.Error($"Failed to send pool sync: {ex}"); } } private void OnPoolSyncResponse(VehiclePoolSyncResponse message, CSteamID senderId) { <>c__DisplayClass25_0 CS$<>8__locals0 = new <>c__DisplayClass25_0(); CS$<>8__locals0.message = message; CS$<>8__locals0.<>4__this = this; if (!IsHost) { _logger.Msg($"Received pool sync response with {CS$<>8__locals0.message.Vehicles.Count} vehicles"); MelonCoroutines.Start(ProcessMessage()); } [IteratorStateMachine(typeof(<>c__DisplayClass25_0.<<OnPoolSyncResponse>g__ProcessMessage|0>d))] IEnumerator ProcessMessage() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <>c__DisplayClass25_0.<<OnPoolSyncResponse>g__ProcessMessage|0>d(0) { <>4__this = CS$<>8__locals0 }; } } private void OnVehicleAllocation(VehicleAllocationMessage message, CSteamID senderId) { <>c__DisplayClass26_0 CS$<>8__locals0 = new <>c__DisplayClass26_0(); CS$<>8__locals0.message = message; CS$<>8__locals0.<>4__this = this; _logger.Msg($"Received allocation: Delivery={CS$<>8__locals0.message.DeliveryId}, Vehicle={CS$<>8__locals0.message.VehicleGuid}, Allocated={CS$<>8__locals0.message.IsAllocated}"); MelonCoroutines.Start(ProcessMessage()); [IteratorStateMachine(typeof(<>c__DisplayClass26_0.<<OnVehicleAllocation>g__ProcessMessage|0>d))] IEnumerator ProcessMessage() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <>c__DisplayClass26_0.<<OnVehicleAllocation>g__ProcessMessage|0>d(0) { <>4__this = CS$<>8__locals0 }; } } private void OnBaseVehicleAllocation(BaseVehicleAllocationMessage message, CSteamID senderId) { _logger.Msg($"Received base allocation: Shop={message.ShopName}, Allocated={message.IsAllocated}"); try { PoolManager.Instance.BaseVehicleAllocationsForShop[message.ShopName] = message.IsAllocated; } catch (Exception value) { _logger.Error($"Failed to process base allocation: {value}"); } } private void OnLobbyCreated(object sender, LobbyCreatedEventArgs e) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) _logger.Msg($"Lobby created: {e.Lobby.LobbyId}"); _client.SetMyData("MultiDelivery_Version", "1.0.0"); } private void OnLobbyJoined(object sender, LobbyJoinedEventArgs e) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) _logger.Msg($"Joined lobby: {e.Lobby.LobbyId}"); _client.SetMyData("MultiDelivery_Version", "1.0.0"); if (!IsHost) { RequestPoolSync(); } } private async void OnMemberJoined(object sender, MemberJoinedEventArgs e) { if (!IsHost) { return; } _logger.Msg("Member joined: " + e.Member.DisplayName); await Task.Delay(1000); VehiclePoolSyncResponse response = new VehiclePoolSyncResponse(); foreach (DeliveryVehicle vehicle in PoolManager.Instance.Pool) { response.Vehicles.Add(new VehiclePoolSyncResponse.VehicleData { ObjectId = ((NetworkBehaviour)vehicle.Vehicle).ObjectId, Guid = vehicle.GUID, Name = vehicle.Vehicle.vehicleName, Code = vehicle.Vehicle.VehicleCode, Color = (int)vehicle.Vehicle.Color.displayedColor }); } _logger.Msg($"Sending pool sync to new member ({response.Vehicles.Count} vehicles)"); await _client.SendMessageToPlayerAsync(e.Member.SteamId, (P2PMessage)(object)response); } private void OnLobbyLeft(object sender, LobbyLeftEventArgs e) { _logger.Msg("Left lobby: " + e.Reason); } private async void RequestPoolSync() { if (!IsSingleplayer && !IsHost) { List<MemberInfo> members = _client.GetLobbyMembers(); MemberInfo host = ((IEnumerable<MemberInfo>)members).FirstOrDefault((Func<MemberInfo, bool>)((MemberInfo m) => m.IsOwner)); if (host == null) { _logger.Error("Cannot request pool sync - no host found"); return; } VehiclePoolSyncRequest vehiclePoolSyncRequest = new VehiclePoolSyncRequest(); CSteamID localPlayerId = _client.LocalPlayerId; vehiclePoolSyncRequest.RequesterId = ((object)(CSteamID)(ref localPlayerId)).ToString(); VehiclePoolSyncRequest message = vehiclePoolSyncRequest; _logger.Msg("Requesting pool sync from host"); await _client.SendMessageToPlayerAsync(host.SteamId, (P2PMessage)(object)message); } } private LandVehicle? FindLandVehicleByObjectId(int objectId) { //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) Scene sceneByName = SceneManager.GetSceneByName("Main"); if (!((Scene)(ref sceneByName)).isLoaded) { _logger.Error("Main scene is not loaded"); return null; } Il2CppReferenceArray<GameObject> rootGameObjects = ((Scene)(ref sceneByName)).GetRootGameObjects(); foreach (GameObject item in (Il2CppArrayBase<GameObject>)(object)rootGameObjects) { Il2CppArrayBase<LandVehicle> componentsInChildren = item.GetComponentsInChildren<LandVehicle>(true); foreach (LandVehicle item2 in componentsInChildren) { if (((NetworkBehaviour)item2).ObjectId == objectId) { _logger.Msg($"Found LandVehicle: ObjectId={objectId}, Name={item2.vehicleName}"); return item2; } } } _logger.Warning($"LandVehicle with ObjectId {objectId} not found in Main scene"); return null; } [IteratorStateMachine(typeof(<ExponentialBackoff>d__34))] private static IEnumerator ExponentialBackoff(Func<bool> predicate, float initialDelay, float finalDelay, float timeout) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ExponentialBackoff>d__34(0) { predicate = predicate, initialDelay = initialDelay, finalDelay = finalDelay, timeout = timeout }; } } public class VehicleAddedMessage : P2PMessage { public override string MessageType => "VehicleAdded"; public int ObjectId { get; set; } public string VehicleGuid { get; set; } public string VehicleName { get; set; } public string VehicleCode { get; set; } public int VehicleColor { get; set; } public override byte[] Serialize() { string s = ((P2PMessage)this).CreateJsonBase($"\"ObjectId\":{ObjectId},\"VehicleGuid\":\"{VehicleGuid}\",\"VehicleName\":\"{VehicleName}\",\"VehicleCode\":\"{VehicleCode}\",\"VehicleColor\":{VehicleColor}"); return Encoding.UTF8.GetBytes(s); } public override void Deserialize(byte[] data) { string @string = Encoding.UTF8.GetString(data); ((P2PMessage)this).ParseJsonBase(@string); ObjectId = int.Parse(((P2PMessage)this).ExtractJsonValue(@string, "ObjectId")); VehicleGuid = ((P2PMessage)this).ExtractJsonValue(@string, "VehicleGuid"); VehicleName = ((P2PMessage)this).ExtractJsonValue(@string, "VehicleName"); VehicleCode = ((P2PMessage)this).ExtractJsonValue(@string, "VehicleCode"); VehicleColor = int.Parse(((P2PMessage)this).ExtractJsonValue(@string, "VehicleColor")); } } public class VehicleCreatedMessage : P2PMessage { public override string MessageType => "VehicleCreated"; public int ObjectId { get; set; } public string VehicleGuid { get; set; } public override byte[] Serialize() { string s = ((P2PMessage)this).CreateJsonBase($"\"ObjectId\":{ObjectId},\"VehicleGuid\":\"{VehicleGuid}\""); return Encoding.UTF8.GetBytes(s); } public override void Deserialize(byte[] data) { string @string = Encoding.UTF8.GetString(data); ((P2PMessage)this).ParseJsonBase(@string); ObjectId = int.Parse(((P2PMessage)this).ExtractJsonValue(@string, "ObjectId")); VehicleGuid = ((P2PMessage)this).ExtractJsonValue(@string, "VehicleGuid"); } } public class VehiclePoolSyncRequest : P2PMessage { public override string MessageType => "VehiclePoolSyncRequest"; public string RequesterId { get; set; } public override byte[] Serialize() { string s = ((P2PMessage)this).CreateJsonBase("\"RequesterId\":\"" + RequesterId + "\""); return Encoding.UTF8.GetBytes(s); } public override void Deserialize(byte[] data) { string @string = Encoding.UTF8.GetString(data); ((P2PMessage)this).ParseJsonBase(@string); RequesterId = ((P2PMessage)this).ExtractJsonValue(@string, "RequesterId"); } } public class VehiclePoolSyncResponse : P2PMessage { [Serializable] public class VehicleData { public int ObjectId { get; set; } public string Guid { get; set; } public string Name { get; set; } public string Code { get; set; } public int Color { get; set; } } public override string MessageType => "VehiclePoolSyncResponse"; public List<VehicleData> Vehicles { get; set; } = new List<VehicleData>(); public override byte[] Serialize() { string text = string.Join(",", Vehicles.Select((VehicleData v) => $"{{\"ObjectId\":{v.ObjectId},\"Guid\":\"{v.Guid}\",\"Name\":\"{v.Name}\",\"Code\":\"{v.Code}\",\"Color\":{v.Color}}}")); string s = ((P2PMessage)this).CreateJsonBase("\"Vehicles\":[" + text + "]"); return Encoding.UTF8.GetBytes(s); } public override void Deserialize(byte[] data) { string @string = Encoding.UTF8.GetString(data); ((P2PMessage)this).ParseJsonBase(@string); int num = @string.IndexOf("\"Vehicles\":[", StringComparison.Ordinal) + 12; int num2 = @string.IndexOf("]", num, StringComparison.Ordinal); string text = @string.Substring(num, num2 - num); Vehicles.Clear(); if (string.IsNullOrWhiteSpace(text)) { return; } string[] array = text.Split(new string[1] { "}," }, StringSplitOptions.None); string[] array2 = array; foreach (string text2 in array2) { string text3 = text2.TrimStart('{').TrimEnd('}') + "}"; if (text3.Contains("ObjectId")) { Vehicles.Add(new VehicleData { ObjectId = int.Parse(((P2PMessage)this).ExtractJsonValue(text3, "ObjectId")), Guid = ((P2PMessage)this).ExtractJsonValue(text3, "Guid"), Name = ((P2PMessage)this).ExtractJsonValue(text3, "Name"), Code = ((P2PMessage)this).ExtractJsonValue(text3, "Code"), Color = int.Parse(((P2PMessage)this).ExtractJsonValue(text3, "Color")) }); } } } } public class VehicleAllocationMessage : P2PMessage { public override string MessageType => "VehicleAllocation"; public string DeliveryId { get; set; } public string VehicleGuid { get; set; } public bool IsAllocated { get; set; } public override byte[] Serialize() { string s = ((P2PMessage)this).CreateJsonBase($"\"DeliveryId\":\"{DeliveryId}\",\"VehicleGuid\":\"{VehicleGuid}\",\"IsAllocated\":{IsAllocated.ToString().ToLower()}"); return Encoding.UTF8.GetBytes(s); } public override void Deserialize(byte[] data) { string @string = Encoding.UTF8.GetString(data); ((P2PMessage)this).ParseJsonBase(@string); DeliveryId = ((P2PMessage)this).ExtractJsonValue(@string, "DeliveryId"); VehicleGuid = ((P2PMessage)this).ExtractJsonValue(@string, "VehicleGuid"); IsAllocated = bool.Parse(((P2PMessage)this).ExtractJsonValue(@string, "IsAllocated")); } } public class BaseVehicleAllocationMessage : P2PMessage { public override string MessageType => "BaseVehicleAllocation"; public string ShopName { get; set; } public bool IsAllocated { get; set; } public override byte[] Serialize() { string s = ((P2PMessage)this).CreateJsonBase("\"ShopName\":\"" + ShopName + "\",\"IsAllocated\":" + IsAllocated.ToString().ToLower()); return Encoding.UTF8.GetBytes(s); } public override void Deserialize(byte[] data) { string @string = Encoding.UTF8.GetString(data); ((P2PMessage)this).ParseJsonBase(@string); ShopName = ((P2PMessage)this).ExtractJsonValue(@string, "ShopName"); IsAllocated = bool.Parse(((P2PMessage)this).ExtractJsonValue(@string, "IsAllocated")); } } public static class NetworkConvenienceMethods { private static DeliveryNetworkManager? _networkManager; public static bool HostOrSingleplayer => _networkManager?.HostOrSingleplayer ?? true; public static void InitializeNetworking(DeliveryNetworkManager networkManager) { _networkManager = networkManager; } public static void NotifyVehicleAdded(DeliveryVehicle vehicle) { _networkManager?.BroadcastVehicleAdded(vehicle); } public static void NotifyVehicleCreated(DeliveryVehicle vehicle) { _networkManager?.BroadcastVehicleCreated(vehicle); } public static void NotifyAllocation(string deliveryId, DeliveryVehicle vehicle, bool isAllocated) { _networkManager?.BroadcastVehicleAllocation(deliveryId, vehicle, isAllocated); } public static void NotifyBaseAllocation(string shopName, bool isAllocated) { _networkManager?.BroadcastBaseVehicleAllocation(shopName, isAllocated); } } } namespace MultiDelivery.Helpers { public static class MelonLoggerExtensions { public static void Debug(this Instance logger, string message, bool stacktrace = true) { MelonDebug.Msg(stacktrace ? ("[" + GetCallerInfo() + "] " + message) : message); } private static string GetCallerInfo() { StackTrace stackTrace = new StackTrace(); for (int i = 2; i < stackTrace.FrameCount; i++) { StackFrame frame = stackTrace.GetFrame(i); MethodBase method = frame.GetMethod(); if (!(method?.DeclaringType == null)) { return method.DeclaringType.FullName + "." + method.Name; } } return "unknown"; } } public static class Il2CppListExtensions { public static IEnumerable<T> AsEnumerable<T>(this List<T> list) { return list ?? new List<T>(); } public static object ToNativeList<T>(this List<T> source) { return source.ToIl2CppList(); } public static List<T> ToIl2CppList<T>(this IEnumerable<T> source) { List<T> val = new List<T>(); foreach (T item in source) { val.Add(item); } return val; } public static List<T> ConvertToList<T>(List<T> il2CppList) { List<T> list = new List<T>(); T[] collection = Il2CppArrayBase<T>.op_Implicit(il2CppList.ToArray()); list.AddRange(collection); return list; } public static IEnumerable<T> AsEnumerable<T>(this List<T> list) { IEnumerable<T> result; if (list != null) { result = ((IEnumerable<T>)list._items).Take(list._size); } else { IEnumerable<T> enumerable = Array.Empty<T>(); result = enumerable; } return result; } public static object ToNativeList<T>(this List<T> source) { return source; } } public static class Utils { [CompilerGenerated] private sealed class <WaitForCondition>d__6 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Func<bool> condition; public float timeout; public Action onTimeout; public Action onFinish; private float <startTime>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WaitForCondition>d__6(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 (!condition()) { if (!float.IsNaN(timeout) && Time.time - <startTime>5__1 > timeout) { onTimeout?.Invoke(); return false; } <>2__current = null; <>1__state = 1; return true; } onFinish?.Invoke(); 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 <WaitForNetwork>d__5 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public IEnumerator routine; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WaitForNetwork>d__5(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; break; case 1: <>1__state = -1; break; } if (!InstanceFinder.IsServer && !InstanceFinder.IsClient) { <>2__current = null; <>1__state = 1; return true; } MelonCoroutines.Start(routine); 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 <WaitForPlayer>d__4 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public IEnumerator routine; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WaitForPlayer>d__4(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; break; case 1: <>1__state = -1; break; } if ((Object)(object)Player.Local == (Object)null || (Object)(object)((Component)Player.Local).gameObject == (Object)null) { <>2__current = null; <>1__state = 1; return true; } MelonCoroutines.Start(routine); 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 static readonly Instance Logger = new Instance("MultiDelivery-Utils"); public static T? FindObjectByName<T>(string objectName) where T : Object { try { foreach (T item in Resources.FindObjectsOfTypeAll<T>()) { if (((Object)item).name != objectName) { continue; } Logger.Debug($"Found {typeof(T).Name} '{objectName}' directly in loaded objects"); return item; } return default(T); } catch (Exception ex) { Logger.Error($"Error finding {typeof(T).Name} '{objectName}': {ex.Message}"); return default(T); } } public static List<T> GetAllComponentsInChildrenRecursive<T>(GameObject obj) where T : Component { List<T> list = new List<T>(); if ((Object)(object)obj == (Object)null) { return list; } T[] array = Il2CppArrayBase<T>.op_Implicit(obj.GetComponents<T>()); if (array.Length != 0) { list.AddRange(array); } for (int i = 0; i < obj.transform.childCount; i++) { Transform child = obj.transform.GetChild(i); list.AddRange(GetAllComponentsInChildrenRecursive<T>(((Component)child).gameObject)); } return list; } public static bool Is<T>(object obj, out T? result) where T : Object { Object val = (Object)((obj is Object) ? obj : null); if (val != null) { Type val2 = Il2CppType.Of<T>(); Type il2CppType = val.GetIl2CppType(); if (val2.IsAssignableFrom(il2CppType)) { result = ((Il2CppObjectBase)val).TryCast<T>(); return result != null; } } result = default(T); return false; } [IteratorStateMachine(typeof(<WaitForPlayer>d__4))] public static IEnumerator WaitForPlayer(IEnumerator routine) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WaitForPlayer>d__4(0) { routine = routine }; } [IteratorStateMachine(typeof(<WaitForNetwork>d__5))] public static IEnumerator WaitForNetwork(IEnumerator routine) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WaitForNetwork>d__5(0) { routine = routine }; } [IteratorStateMachine(typeof(<WaitForCondition>d__6))] public static IEnumerator WaitForCondition(Func<bool> condition, float timeout = float.NaN, Action? onTimeout = null, Action? onFinish = null) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WaitForCondition>d__6(0) { condition = condition, timeout = timeout, onTimeout = onTimeout, onFinish = onFinish }; } public static string GetHierarchyPath(this Transform transform) { if ((Object)(object)transform == (Object)null) { return "null"; } string text = ((Object)transform).name; Transform parent = transform.parent; while ((Object)(object)parent != (Object)null) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } public static T GetOrAddComponent<T>(this GameObject gameObject) where T : Component { T component = gameObject.GetComponent<T>(); if ((Object)(object)component != (Object)null) { return component; } component = gameObject.AddComponent<T>(); Logger.Debug("Added component " + typeof(T).Name + " to GameObject " + ((Object)gameObject).name); return component; } public static Material? DrawDebugVisuals(this GameObject gameObject, Color? color = null) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) Renderer component = gameObject.GetComponent<Renderer>(); if ((Object)(object)component == (Object)null) { Logger.Error("GameObject " + ((Object)gameObject).name + " has no Renderer component"); return null; } Color valueOrDefault = color.GetValueOrDefault(); if (!color.HasValue) { ((Color)(ref valueOrDefault))..ctor(1f, 0f, 1f, 0.5f); color = valueOrDefault; } Shader val = Shader.Find("Universal Render Pipeline/Lit"); if ((Object)(object)val == (Object)null) { return null; } Material val2 = new Material(val); if (val2.HasProperty("_Surface")) { val2.SetFloat("_Surface", 1f); } Color value = color.Value; if (value.a <= 0f) { value.a = 0.2f; } if (val2.HasProperty("_BaseColor")) { val2.SetColor("_BaseColor", value); } if (val2.HasProperty("_EmissionColor")) { val2.EnableKeyword("_EMISSION"); val2.SetColor("_EmissionColor", new Color(value.r, value.g, value.b) * 1.5f); } val2.SetInt("_ZWrite", 0); val2.renderQueue = 3000; Material material = component.material; component.material = val2; return material; } public static string Capitalize(this string str) { if (str.Length < 1) { throw new ArgumentOutOfRangeException("str"); } return char.ToUpper(str[0]) + str.Substring(1, str.Length - 1); } } } namespace MultiDelivery.Builders { public class DeliveryVehicleBuilder { private Guid _guid; private LandVehicle _landVehicle; public DeliveryVehicleBuilder WithGuid(Guid guid) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) _guid = guid; return this; } public DeliveryVehicleBuilder WithGuid(string guid) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) _guid = new Guid(guid); return this; } public DeliveryVehicleBuilder WithLandVehicle(LandVehicle landVehicle) { _landVehicle = landVehicle; return this; } public DeliveryVehicleBuilder WithLandVehicle(GameObject landVehicle) { _landVehicle = landVehicle.GetComponent<LandVehicle>(); return this; } public DeliveryVehicle Build() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) DeliveryVehicle val = ((Component)_landVehicle).gameObject.AddComponent<DeliveryVehicle>(); val.GUID = ((object)(Guid)(ref _guid)).ToString(); _landVehicle.SetGUID(_guid); return val; } } public class LandVehicleBuilder { private string _vehicleName = "CustomVehicle"; private string _vehicleCode = "veeper"; private EVehicleColor _color = (EVehicleColor)16; private Guid _guid = GUIDManager.GenerateUniqueGUID(); private static Transform? _parent; public LandVehicleBuilder WithVehicleName(string vehicleName) { _vehicleName = vehicleName; return this; } public LandVehicleBuilder WithVehicleCode(string vehicleCode) { _vehicleCode = vehicleCode; return this; } public LandVehicleBuilder WithColor(EVehicleColor color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) _color = color; return this; } public LandVehicleBuilder WithGuid(Guid guid) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) _guid = guid; return this; } public LandVehicleBuilder WithGuid(string guid) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) _guid = new Guid(guid); return this; } public LandVehicleBuilder WithParent(Transform parent) { _parent = parent; return this; } public LandVehicle Build() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_parent == (Object)null) { GameObject val = GameObject.Find("VehiclePool"); if ((Object)(object)val == (Object)null) { val = new GameObject("VehiclePool"); } _parent = val.transform; } Vector3 position = default(Vector3); ((Vector3)(ref position))..ctor(0f, -100f, 0f); Quaternion identity = Quaternion.identity; if (!InstanceFinder.IsServer) { throw new ArgumentException("LandVehicleBuilder can only be used on the server"); } LandVehicle vehiclePrefab = NetworkSingleton<VehicleManager>.Instance.GetVehiclePrefab(_vehicleCode); if ((Object)(object)vehiclePrefab == (Object)null) { throw new ArgumentException("Vehicle prefab with code '" + _vehicleCode + "' not found."); } GameObject val2 = Object.Instantiate<GameObject>(((Component)vehiclePrefab).gameObject, _parent, true); LandVehicle component = val2.GetComponent<LandVehicle>(); component.IsPlayerOwned = false; component.SetVisible(false); component.IsPhysicallySimulated = false; ((Component)component).transform.position = position; ((Component)component).transform.rotation = identity; component.SetGUID(_guid); ((Object)component).name = _vehicleName; ((Object)((Component)component).gameObject).name = _vehicleName; component.vehicleName = _vehicleName; component.SetIsPlayerOwned((NetworkConnection)null, false); component.Rb.isKinematic = false; ((NetworkBehaviour)component).Owner.ClientId = -1; component.ApplyColor(_color); NetworkSingleton<VehicleManager>.Instance.AllVehicles.Add(component); ((NetworkBehaviour)NetworkSingleton<VehicleManager>.Instance).NetworkObject.Spawn(((Component)component).gameObject, (NetworkConnection)null, default(Scene)); return component; } } }
MultiDelivery-Mono.dll
Decompiled 3 hours agousing 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 System.Text; using System.Threading.Tasks; using FishNet; using FishNet.Connection; using FishNet.Object; using HarmonyLib; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using MultiDelivery; using MultiDelivery.Builders; using MultiDelivery.Helpers; using MultiDelivery.Network; using MultiDelivery.Persistence; using MultiDelivery.Pool; using MultiDelivery.Quest; using S1API.Dialogues; using S1API.Entities; using S1API.Entities.Dialogue; using S1API.Entities.NPCs.Suburbia; using S1API.Internal.Abstraction; using S1API.Leveling; using S1API.Messaging; using S1API.Money; using S1API.Quests; using S1API.Quests.Constants; using S1API.Saveables; using S1API.Utils; using ScheduleOne; using ScheduleOne.Core.Items.Framework; using ScheduleOne.Delivery; using ScheduleOne.DevUtilities; using ScheduleOne.Graffiti; using ScheduleOne.ItemFramework; using ScheduleOne.Map; using ScheduleOne.Money; using ScheduleOne.NPCs.CharacterClasses; using ScheduleOne.Persistence.Datas; using ScheduleOne.Persistence.Loaders; using ScheduleOne.PlayerScripts; using ScheduleOne.UI.Phone.Delivery; using ScheduleOne.UI.Shop; using ScheduleOne.Vehicles; using ScheduleOne.Vehicles.Modification; using ScheduleOne.Weather; using SteamNetworkLib; using SteamNetworkLib.Core; using SteamNetworkLib.Events; using SteamNetworkLib.Models; using Steamworks; using UnityEngine; 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(global::MultiDelivery.MultiDelivery), "MultiDelivery", "1.0.1", "k073l", null)] [assembly: MelonColor(1, 0, 255, 0)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: MelonPlatformDomain(/*Could not decode attribute arguments.*/)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyCompany("MultiDelivery-Mono")] [assembly: AssemblyConfiguration("Mono")] [assembly: AssemblyDescription("Add vehicles, order multiple deliveries from the same place!")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+9f266827b45c3676261f34c577e88b8249083816")] [assembly: AssemblyProduct("MultiDelivery-Mono")] [assembly: AssemblyTitle("MultiDelivery-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 MultiDelivery { public class Logger { [CompilerGenerated] [DebuggerBrowsable(DebuggerBrowsableState.Never)] private string <categoryName>P; [CompilerGenerated] [DebuggerBrowsable(DebuggerBrowsableState.Never)] private LogLevel? <forceLevel>P; public Logger(string categoryName, LogLevel? forceLevel = null) { <categoryName>P = categoryName; <forceLevel>P = forceLevel; base..ctor(); } public void NetworkTrace(params object[] args) { Log(LogLevel.NetworkTrace, args); } public void Debug(params object[] args) { Log(LogLevel.Debug, args); } public void Info(params object[] args) { Log(LogLevel.Info, args); } public void Msg(params object[] args) { Log(LogLevel.Info, args); } public void Warn(params object[] args) { Log(LogLevel.Warn, args); } public void Warning(params object[] args) { Log(LogLevel.Warn, args); } public void Error(params object[] args) { Log(LogLevel.Error, args); } private void Log(LogLevel level, params object[] args) { LogLevel? logLevel = <forceLevel>P; if (logLevel.HasValue) { LogLevel valueOrDefault = logLevel.GetValueOrDefault(); if (level < LogLevel.Error) { level = valueOrDefault; } } if (args.Length == 0) { return; } string text; if (args.Length == 1) { text = args[0]?.ToString() ?? ""; } else { string format = args[0]?.ToString() ?? ""; text = string.Format(format, args.Skip(1).ToArray()); } string text2 = (string.IsNullOrWhiteSpace(<categoryName>P) ? "MultiDelivery" : ("MultiDelivery." + <categoryName>P)); string text3 = "[" + text2 + "] " + text; switch (level) { case LogLevel.NetworkTrace: if (MultiDelivery.NetworkLogging.Value) { Melon<MultiDelivery>.Logger.Msg(text3); } break; case LogLevel.Debug: MelonDebug.Msg(text3); break; case LogLevel.Info: Melon<MultiDelivery>.Logger.Msg(text3); break; case LogLevel.Warn: Melon<MultiDelivery>.Logger.Warning(text3); break; case LogLevel.Error: Melon<MultiDelivery>.Logger.Error(text3); break; } } } public enum LogLevel { NetworkTrace, Debug, Info, Warn, Error } public static class BuildInfo { public const string Name = "MultiDelivery"; public const string Description = "Add vehicles, order multiple deliveries from the same place!"; public const string Author = "k073l"; public const string Version = "1.0.1"; } public class MultiDelivery : MelonMod { [CompilerGenerated] private sealed class <InitializeNetworkManager>d__12 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public MultiDelivery <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <InitializeNetworkManager>d__12(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; if (!SteamAPI.Init()) { return false; } <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; <>4__this._networkManager = new DeliveryNetworkManager(); if (<>4__this._networkManager.Initialize()) { Logger.Msg("Network manager initialized"); NetworkConvenienceMethods.InitializeNetworking(<>4__this._networkManager); } else { <>4__this._networkManager = null; Logger.Warning("Network manager initialization failed - running in offline mode"); } 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 <WireOnXpChangedDelayed>d__16 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public MultiDelivery <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WireOnXpChangedDelayed>d__16(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitUntil((Func<bool>)(() => LevelManager.Exists)); <>1__state = 1; return true; case 1: <>1__state = -1; if (PersistentDropoffQuestData.Instance.HasMessaged) { DropoffQuestDialogue.Register(); return false; } Logger.Debug("Wiring on xp changed"); LevelManager.OnXPChanged += <>4__this.SendMessageIfRequiredRank; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } internal const string RequestedVehicleCode = "veeper"; private static FullRank RequiredRank = new FullRank((Rank)5, 1); private static Sprite _questIconSprite; private static readonly Logger Logger = new Logger(""); private DeliveryNetworkManager? _networkManager; private bool _networkManagerFailed; internal static MelonPreferences_Category Category = MelonPreferences.CreateCategory("MultiDeliverySettings", "MultiDelivery's Settings"); internal static MelonPreferences_Entry<bool> NetworkLogging = Category.CreateEntry<bool>("NetworkDebugLogs", false, "Enable Network Logs", "Display networking-related debug logs in MelonLoader console/log file (may be verbose)", false, false, (ValueValidator)null, (string)null); public static Sprite QuestIconSprite => GetIcon(ref _questIconSprite, "MultiDelivery.assets.quest_icon.png"); public override void OnInitializeMelon() { Logger.Msg("MultiDelivery initialized"); MelonCoroutines.Start(InitializeNetworkManager()); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { if (sceneName == "Main") { Player.LocalPlayerSpawned += WirePlayerEvent; } else if (!(sceneName != "Menu")) { PoolManager.Instance.Pool.Clear(); PoolManager.Instance.Allocations.Clear(); PoolManager.Instance.BaseVehicleAllocationsForShop.Clear(); Player.LocalPlayerSpawned -= WirePlayerEvent; LevelManager.OnXPChanged -= SendMessageIfRequiredRank; } } [IteratorStateMachine(typeof(<InitializeNetworkManager>d__12))] private IEnumerator InitializeNetworkManager() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <InitializeNetworkManager>d__12(0) { <>4__this = this }; } public override void OnUpdate() { if (_networkManagerFailed || _networkManager == null) { return; } try { _networkManager.Update(); } catch (Exception ex) { MelonLogger.Error("Network manager update failed: " + ex.Message + "\n\nYou can ignore this error if you plan on playing singleplayer only and don't want to install SteamNetworkLib"); _networkManagerFailed = true; } } public override void OnDeinitializeMelon() { _networkManager?.Dispose(); Logger.Msg("MultiDelivery deinitialized"); } private void WirePlayerEvent(Player _) { Logger.Debug("Player loaded event called"); MelonCoroutines.Start(WireOnXpChangedDelayed()); } [IteratorStateMachine(typeof(<WireOnXpChangedDelayed>d__16))] private IEnumerator WireOnXpChangedDelayed() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WireOnXpChangedDelayed>d__16(0) { <>4__this = this }; } private void SendMessageIfRequiredRank(FullRank _, FullRank current) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) Logger.Debug($"Current rank {current}, required: {RequiredRank}"); if (PersistentDropoffQuestData.Instance.HasMessaged) { MelonDebug.Msg("Xp changed wired, but already messaged - registering dialogue now."); DropoffQuestDialogue.Register(); } else { if (current < RequiredRank) { return; } NPC val = NPC.Get<JeremyWilkinson>(); if (val != null) { if (NetworkConvenienceMethods.HostOrSingleplayer) { val.SendTextMessage("Your properties are getting busy. Want to handle more than one delivery at a time? I've got an idea. Stop by the dealership.", (Response[])null, 1f, true); } PersistentDropoffQuestData.Instance.HasMessaged = true; DropoffQuestDialogue.Register(); LevelManager.OnXPChanged -= SendMessageIfRequiredRank; } } } private static Sprite LoadEmbeddedPNG(string resourceName) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); using Stream stream = executingAssembly.GetManifestResourceStream(resourceName); if (stream == null) { return null; } byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); Sprite val = ImageUtils.LoadImageRaw(array); if ((Object)(object)val != (Object)null) { ((Object)val).name = resourceName; } return val; } private static Sprite GetIcon(ref Sprite spriteField, string resourceName) { if ((Object)(object)spriteField == (Object)null) { spriteField = LoadEmbeddedPNG(resourceName); } return spriteField; } } } namespace MultiDelivery.Quest { public class DropoffQuest : Quest { [CompilerGenerated] private sealed class <NotifyCompletion>d__21 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public DropoffQuest <>4__this; private NPC <npc>5__1; private int <i>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <NotifyCompletion>d__21(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <npc>5__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <i>5__2 = 0; break; case 1: { <>1__state = -1; int num = <i>5__2 + 1; <i>5__2 = num; break; } } if (<i>5__2 < 3 && PoolManager.Instance.Pool.Count <= <>4__this._startingCapacity) { <>2__current = (object)new WaitForSeconds(3f); <>1__state = 1; return true; } <npc>5__1 = NPC.Get<JeremyWilkinson>(); if (<npc>5__1 != null) { if (PoolManager.Instance.Pool.Count <= <>4__this._startingCapacity) { <npc>5__1.SendTextMessage("Something went wrong... Vehicle got in a car crash :(", (Response[])null, 1f, true); } else { <npc>5__1.SendTextMessage($"Vehicle added, you now can order {PoolManager.Instance.Pool.Count} more " + "deliver" + ((PoolManager.Instance.Pool.Count > 1) ? "y" : "ies") + " from stores.", (Response[])null, 1f, true); <npc>5__1.SendTextMessage("If you want to add more, you know where to find me.", (Response[])null, 1f, true); } } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } internal const string Name = "Expanding the Fleet"; private bool _vehicleAdded; private QuestEntry _addVehicleEntry; private int _startingCapacity; private static VehicleDropoffZone dropoffZone; private static Vector3 _dropoffZonePosition; private static readonly Logger Logger = new Logger("DropoffQuest"); protected override string Title => "Expanding the Fleet"; protected override string Description => "Bring a delivery vehicle to the dropoff zone to expand your delivery capacity"; protected override bool AutoBegin => false; protected override Sprite QuestIcon => MultiDelivery.QuestIconSprite; internal QuestState State => ((Quest)this).QuestState; protected override void OnCreated() { //IL_0072: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) ((Registerable)this).OnCreated(); _startingCapacity = PoolManager.Instance.Pool.Count; Logger.Debug($"Starting Quest with {_startingCapacity} capacity"); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(5.1f, 4.2f, 82.58f); Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(0.55f, 4.2f, 76.56f); _dropoffZonePosition = (val + val2) / 2f; if ((Object)(object)dropoffZone != (Object)null) { Object.Destroy((Object)(object)((Component)dropoffZone).gameObject); } dropoffZone = VehicleDropoffZoneFactory.CreateZone(val, val2, 5f, (Color?)new Color(0f, 1f, 0f, 0.4f), showVisuals: true, this); Logger.Debug("Dropoff zone created. Spawning " + ((Object)dropoffZone).name); ((Quest)this).OnComplete += Completed; Logger.Debug("Wired completion event"); UpdateQuestEntries(); } private void UpdateQuestEntries() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) base.QuestEntries.Clear(); if (!_vehicleAdded) { Logger.Debug("Adding add vehicle entry"); _addVehicleEntry = ((Quest)this).AddEntry("Purchase a " + "veeper".Capitalize() + " and drive it into the green dropoff zone (top floor of the parking garage, next to storage unit)", (Vector3?)_dropoffZonePosition); _addVehicleEntry.Begin(); } Logger.Debug("Entries added!"); } public void MarkAddVehicleEntryComplete() { Logger.Debug("Marked add vehicle entry as completed"); _addVehicleEntry.Complete(); } private void Completed() { Logger.Msg("Delivery vehicle dropoff quest completed!"); MelonCoroutines.Start(NotifyCompletion()); } [IteratorStateMachine(typeof(<NotifyCompletion>d__21))] private IEnumerator NotifyCompletion() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <NotifyCompletion>d__21(0) { <>4__this = this }; } } public class DropoffQuestDialogue { private static readonly Logger Logger = new Logger("DropoffQuestDialogue"); private const string ContainerName = "DeliveryExpansion"; public static void Register() { //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Expected O, but got Unknown NPC jeremy = NPC.Get<JeremyWilkinson>(); if (jeremy == null) { Logger.Warning("Jeremy Wilkinson not found"); return; } jeremy.Dialogue.BuildAndRegisterContainer("DeliveryExpansion", (Action<DialogueContainerBuilder>)delegate(DialogueContainerBuilder c) { c.AddNode("OFFER_FIRST", "Yeah! I can help with that. If you bring a " + "veeper".Capitalize() + " to the dropoff zone, I'll add it to the fleet. This will let you handle multiple deliveries at once. Want to give it a shot?", (Action<ChoiceList>)delegate(ChoiceList ch) { ch.Add("BUY_NOW", "Sure! Can I buy one from you right now?", "CHECK_FUNDS"); ch.Add("ACCEPT", "I already have one, let's do it!", "ACCEPTED"); ch.Add("DECLINE", "Maybe later.", "DECLINED"); }); c.AddNode("OFFER_REPEAT", "Want to expand your fleet even more? Just bring another vehicle to the dropoff zone and I'll add it for you.", (Action<ChoiceList>)delegate(ChoiceList ch) { ch.Add("BUY_NOW", "Yeah, can I buy another one from you?", "CHECK_FUNDS"); ch.Add("ACCEPT", "I've got one ready!", "ACCEPTED"); ch.Add("DECLINE", "Not right now.", "DECLINED"); }); c.AddNode("CHECK_FUNDS", "A " + "veeper".Capitalize() + " runs <color=#19BEF0>(" + MoneyManager.FormatAmount(GetVehiclePrice(), false, false) + ")</color>. Want to pick one up?", (Action<ChoiceList>)delegate(ChoiceList ch) { ch.Add("PURCHASE", "I'll take it. <color=#19BEF0>(" + MoneyManager.FormatAmount(GetVehiclePrice(), false, false) + ")</color>", "PURCHASE_COMPLETE"); ch.Add("NEVERMIND", "Let me think about it.", "DECLINED"); }); c.AddNode("PURCHASE_COMPLETE", "All yours. You can customize it if you want. Now just drive it to the dropoff zone - I've marked it on your map.", (Action<ChoiceList>)null); c.AddNode("NOT_ENOUGH", "You don't have enough money to buy it. Come back later.", (Action<ChoiceList>)null); c.AddNode("IN_PROGRESS", "You already have an active delivery expansion going! Just bring the vehicle to the dropoff zone. Top floor of the parking garage, next to the storage units - check your map if you forgot where it is.", (Action<ChoiceList>)null); c.AddNode("ACCEPTED", "Great! I've marked the dropoff zone on your map - top floor of the parking garage, next to the storage units. Just drive the vehicle in there when you're ready.", (Action<ChoiceList>)null); c.AddNode("DECLINED", "No worries, just let me know if you change your mind!", (Action<ChoiceList>)null); }); jeremy.Dialogue.OnChoiceSelected("ACCEPT", (Action)OnAcceptQuest); jeremy.Dialogue.OnChoiceSelected("BUY_NOW", (Action)OnAcceptQuest); jeremy.Dialogue.OnChoiceSelected("DECLINE", (Action)delegate { Logger.Debug("Player declined quest"); }); jeremy.Dialogue.OnChoiceSelected("NEVERMIND", (Action)delegate { Logger.Debug("Player cancelled purchase"); }); jeremy.Dialogue.OnChoiceSelected("PURCHASE", (Action)delegate { //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) float vehiclePrice = GetVehiclePrice(); float onlineBalance = Money.GetOnlineBalance(); if (onlineBalance >= vehiclePrice) { Money.CreateOnlineTransaction("veeper".Capitalize() + " purchase", 0f - vehiclePrice, 1f, "Bought as a part of delivery expansion"); Logger.Msg(string.Format("Player purchased {0} for ${1:F2}", "veeper", vehiclePrice)); Jeremy component = jeremy.gameObject.GetComponent<Jeremy>(); if ((Object)(object)component != (Object)null) { Dealership dealership = component.Dealership; if ((Object)(object)dealership != (Object)null) { dealership.SpawnVehicle("veeper"); return; } } NetworkSingleton<VehicleManager>.Instance.SpawnVehicle("veeper", new Vector3(9.92f, 0.54f, -33.55f), Quaternion.identity, true); } else { jeremy.Dialogue.JumpTo("DeliveryExpansion", "NOT_ENOUGH", false); } }); DialogueInjector.Register(new DialogueInjection(jeremy.ID, "Dealership_Salesman_Sell", "cc0d838e-2824-4fd5-907d-798dc0195c16", "OFFER_FIRST", "ASK_EXPANSION", "Can I expand my delivery capacity?", (Action)delegate { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 DropoffQuest dropoffQuest = QuestManager.GetQuestByName("Expanding the Fleet") as DropoffQuest; bool flag = PoolManager.Instance.Pool.Count > 0; bool flag2 = dropoffQuest != null && (int)dropoffQuest.State == 1; Logger.Debug($"Quest state - Active: {flag2}, Has expanded: {flag}"); string text = (flag2 ? "IN_PROGRESS" : (flag ? "OFFER_REPEAT" : "OFFER_FIRST")); Logger.Debug("Jumping to 'DeliveryExpansion', node '" + text + "'"); jeremy.Dialogue.JumpTo("DeliveryExpansion", text, false); })); Logger.Msg("Registered delivery expansion dialogue"); } private static void OnAcceptQuest() { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Invalid comparison between Unknown and I4 if (!(QuestManager.GetQuestByName("Expanding the Fleet") is DropoffQuest dropoffQuest)) { if (QuestManager.CreateQuest<DropoffQuest>((string)null) is DropoffQuest dropoffQuest2) { ((Quest)dropoffQuest2).Begin(); } Logger.Msg("Started delivery expansion quest"); } else if (dropoffQuest != null && (int)dropoffQuest.State == 2) { ((Quest)dropoffQuest).Begin(); Logger.Msg("Restarted delivery expansion quest"); } } private static float GetVehiclePrice() { LandVehicle vehiclePrefab = NetworkSingleton<VehicleManager>.Instance.GetVehiclePrefab("veeper"); return (vehiclePrefab != null) ? vehiclePrefab.VehiclePrice : 5000f; } } [RegisterTypeInIl2Cpp] public class VehicleDropoffZone : MonoBehaviour { private VehicleDetector _detector; private Logger _logger; private GameObject _visualPlane; private Material _visualMaterial; private Color _baseColor; private DropoffQuest? _quest; public Vector3 Corner1 { get; private set; } public Vector3 Corner2 { get; private set; } public bool ShowVisuals { get; set; } = true; private void Awake() { _logger = new Logger("VehicleDropoffZone"); } private void Start() { _detector = ((Component)this).gameObject.GetComponent<VehicleDetector>(); if ((Object)(object)_detector == (Object)null) { _detector = ((Component)this).gameObject.AddComponent<VehicleDetector>(); } } private void Update() { if (_detector.vehicles.Count <= 0) { return; } foreach (LandVehicle item in _detector.vehicles.AsEnumerable()) { OnVehicleEntered(item); } } private void OnVehicleEntered(LandVehicle vehicle) { _logger.Debug("Vehicle entered dropoff zone: " + vehicle.vehicleName); if (!IsCorrectVehicleType(vehicle)) { if (Time.frameCount % 60 == 0) { _logger.Warning("Wrong vehicle type: " + vehicle.vehicleCode); } return; } if (vehicle.IsOccupied) { _logger.Msg("Ejecting player from vehicle"); vehicle.ExitVehicle(); } ProcessAndAddToPool(vehicle); _detector.vehicles.Remove(vehicle); Object.Destroy((Object)(object)((Component)this).gameObject); } private static bool IsCorrectVehicleType(LandVehicle vehicle) { return vehicle.vehicleCode == "veeper"; } private void ProcessAndAddToPool(LandVehicle vehicle) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) _logger.Debug($"Adding vehicle to pool: {vehicle.GUID}"); DeliveryVehicle val = ((Component)vehicle).GetComponent<DeliveryVehicle>(); if ((Object)(object)val == (Object)null) { Guid gUID = vehicle.GUID; val = new DeliveryVehicleBuilder().WithLandVehicle(vehicle).WithGuid(gUID).Build(); } vehicle.IsPlayerOwned = false; vehicle.SetIsPlayerOwned((NetworkConnection)null, false); vehicle.SetVisible(false); vehicle.IsPhysicallySimulated = false; ((Component)vehicle).transform.position = new Vector3(0f, -100f, 0f); PoolManager.Instance.AddToSaveData(val); PoolManager.Instance.AddToPool(val); _quest?.MarkAddVehicleEntryComplete(); _logger.Msg($"Vehicle added to pool. Total vehicles: {PoolManager.Instance.Pool.Count}"); } public void SetupZone(Vector3 corner1, Vector3 corner2, float height = 5f, Color? visualColor = null) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_003e: 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_008a: 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_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) Corner1 = corner1; Corner2 = corner2; Vector3 val = (corner1 + corner2) / 2f; Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(Mathf.Abs(corner2.x - corner1.x), height, Mathf.Abs(corner2.z - corner1.z)); ((Component)this).transform.position = val; BoxCollider val3 = ((Component)this).gameObject.GetComponent<BoxCollider>(); if ((Object)(object)val3 == (Object)null) { val3 = ((Component)this).gameObject.AddComponent<BoxCollider>(); } ((Collider)val3).isTrigger = true; val3.size = val2; val3.center = Vector3.zero; if (ShowVisuals) { _baseColor = (Color)(((??)visualColor) ?? new Color(0f, 1f, 1f, 0.3f)); CreateVisualPlane(val2, _baseColor); } _logger.Debug($"Dropoff zone created: Center={val}, Size={val2}"); } private void CreateVisualPlane(Vector3 size, Color color) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) _visualPlane = GameObject.CreatePrimitive((PrimitiveType)3); ((Object)_visualPlane).name = "DropoffZoneVisual"; _visualPlane.transform.SetParent(((Component)this).transform); _visualPlane.transform.localPosition = Vector3.zero; _visualPlane.transform.localScale = new Vector3(size.x, 0.1f, size.z); Collider component = _visualPlane.GetComponent<Collider>(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } ApplyDebugMaterial(_visualPlane, color); } private void ApplyDebugMaterial(GameObject obj, Color color) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_006b: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: 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_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) Renderer component = obj.GetComponent<Renderer>(); if ((Object)(object)component == (Object)null) { return; } Shader val = Shader.Find("Universal Render Pipeline/Lit"); if (!((Object)(object)val == (Object)null)) { _visualMaterial = new Material(val); if (_visualMaterial.HasProperty("_Surface")) { _visualMaterial.SetFloat("_Surface", 1f); } if (color.a <= 0f) { color.a = 0.3f; } if (_visualMaterial.HasProperty("_BaseColor")) { _visualMaterial.SetColor("_BaseColor", color); } if (_visualMaterial.HasProperty("_EmissionColor")) { _visualMaterial.EnableKeyword("_EMISSION"); _visualMaterial.SetColor("_EmissionColor", new Color(color.r, color.g, color.b) * 1.5f); } _visualMaterial.SetInt("_ZWrite", 0); _visualMaterial.renderQueue = 3000; component.material = _visualMaterial; } } public void SetVisualsEnabled(bool enabled) { ShowVisuals = enabled; if ((Object)(object)_visualPlane != (Object)null) { _visualPlane.SetActive(enabled); } } public void SetQuest(DropoffQuest quest) { _quest = quest; } private void OnDestroy() { if ((Object)(object)_visualPlane != (Object)null) { Object.Destroy((Object)(object)_visualPlane); } } } public static class VehicleDropoffZoneFactory { public static VehicleDropoffZone CreateZone(Vector3 corner1, Vector3 corner2, float height = 5f, Color? visualColor = null, bool showVisuals = true, DropoffQuest? attachedQuest = null) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_001d: 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) GameObject val = new GameObject("VehicleDropoffZone"); VehicleDropoffZone vehicleDropoffZone = val.AddComponent<VehicleDropoffZone>(); vehicleDropoffZone.ShowVisuals = showVisuals; vehicleDropoffZone.SetupZone(corner1, corner2, height, visualColor); if (attachedQuest != null) { vehicleDropoffZone.SetQuest(attachedQuest); } return vehicleDropoffZone; } public static VehicleDropoffZone CreateZoneNear(Transform reference, Vector3 offset, Vector3 size, Color? visualColor = null) { //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_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) Vector3 val = reference.position + offset; Vector3 corner = val - size / 2f; Vector3 corner2 = val + size / 2f; return CreateZone(corner, corner2, size.y, visualColor); } } } namespace MultiDelivery.Pool { [HarmonyPatch(typeof(DeliveryManager))] internal static class ActiveDeliveryPatch { private static readonly Logger Logger = new Logger("ActiveDeliveryPatch"); [HarmonyPatch("GetActiveShopDelivery")] [HarmonyPostfix] private static void AllowIfPoolAssigmentAvailable(DeliveryManager __instance, DeliveryShop shop, ref DeliveryInstance __result) { if (__result == null) { return; } if (PoolManager.Instance.BaseVehicleAllocationsForShop.TryGetValue(shop.MatchingShopInterfaceName, out var value)) { if (Time.frameCount % 30 == 0) { Logger.Debug($"Base: {value}"); } if (!value) { __result = null; return; } DeliveryVehicle firstFree = PoolManager.Instance.GetFirstFree(); if (!((Object)(object)firstFree == (Object)null)) { Logger.Debug("Free pool vehicle found"); __result = null; } } else { DeliveryVehicle firstFree2 = PoolManager.Instance.GetFirstFree(); if (!((Object)(object)firstFree2 == (Object)null)) { Logger.Debug("Free pool vehicle found"); __result = null; } } } [HarmonyPatch("SendDelivery")] [HarmonyPostfix] private static void AllocateVehicle(DeliveryManager __instance, DeliveryInstance delivery) { PoolManager.Instance.BaseVehicleAllocationsForShop.TryAdd(delivery.StoreName, value: false); Logger.Debug($"Base allocation: {PoolManager.Instance.BaseVehicleAllocationsForShop[delivery.StoreName]}"); if (!PoolManager.Instance.BaseVehicleAllocationsForShop[delivery.StoreName]) { Logger.Debug("Base vehicle allocating"); PoolManager.Instance.BaseVehicleAllocationsForShop[delivery.StoreName] = true; NetworkConvenienceMethods.NotifyBaseAllocation(delivery.StoreName, isAllocated: true); } else { PoolManager.Instance.GetOrAllocateFirstFree(delivery.DeliveryID); Logger.Debug("Allocated for " + delivery.DeliveryID); } } } [HarmonyPatch(typeof(DeliveryInstance))] internal static class DeliveryInstancePatches { [HarmonyPatch("SetStatus")] [HarmonyPrefix] private static bool UsePoolSetStatus(DeliveryInstance __instance, EDeliveryStatus status) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Invalid comparison between Unknown and I4 //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Invalid comparison between Unknown and I4 Console.Log((object)$"Setting delivery status to {status} for delivery {__instance.DeliveryID}", (Object)null); __instance.Status = status; ShopInterface shopInterface = NetworkSingleton<DeliveryManager>.Instance.GetShopInterface(__instance.StoreName); if ((int)status != 2) { if ((int)status == 3) { if ((Object)(object)__instance.ActiveVehicle == (Object)(object)shopInterface.DeliveryVehicle) { PoolManager.Instance.BaseVehicleAllocationsForShop[__instance.StoreName] = false; NetworkConvenienceMethods.NotifyBaseAllocation(__instance.StoreName, isAllocated: false); } else { PoolManager.Instance.FreeAllocation(__instance.DeliveryID); } if ((Object)(object)__instance.ActiveVehicle != (Object)null) { __instance.ActiveVehicle.Deactivate(); } UnityEvent onDeliveryCompleted = __instance.onDeliveryCompleted; if (onDeliveryCompleted != null) { onDeliveryCompleted.Invoke(); } } } else { if (PoolManager.Instance.Allocations.TryGetValue(__instance.DeliveryID, out DeliveryVehicle value)) { __instance.ActiveVehicle = value; } else { __instance.ActiveVehicle = shopInterface.DeliveryVehicle; } __instance.ActiveVehicle.Activate(__instance); } return false; } [HarmonyPatch("AddItemsToDeliveryVehicle")] [HarmonyPrefix] private static bool UsePoolAddItemsToDeliveryVehicle(DeliveryInstance __instance) { ShopInterface shopInterface = NetworkSingleton<DeliveryManager>.Instance.GetShopInterface(__instance.StoreName); if (!PoolManager.Instance.Allocations.TryGetValue(__instance.DeliveryID, out DeliveryVehicle value)) { value = shopInterface?.DeliveryVehicle; } StringIntPair[] items = __instance.Items; StringIntPair[] array = items; foreach (StringIntPair val in array) { ItemDefinition item = Registry.GetItem(val.String); int num = val.Int; while (num > 0) { int num2 = Mathf.Min(num, ((BaseItemDefinition)item).StackLimit); num -= num2; ItemInstance defaultInstance = item.GetDefaultInstance(num2); value.Vehicle.Storage.InsertItem(defaultInstance, Object.op_Implicit((Object)(object)item)); } } return false; } } [HarmonyPatch(typeof(DeliveryVehicle))] internal class DeliveryVehiclePatch { [HarmonyPatch("Deactivate")] [HarmonyPostfix] private static void NullActiveDelivery(DeliveryVehicle __instance) { DeliveryInstance activeDelivery = __instance.ActiveDelivery; if ((Object)(object)((activeDelivery == null) ? null : activeDelivery.LoadingDock?.VehicleDetector) != (Object)null) { __instance.ActiveDelivery.LoadingDock.SetOccupant((LandVehicle)null); __instance.ActiveDelivery.LoadingDock.VehicleDetector.Clear(); } if (__instance.ActiveDelivery != null) { __instance.ActiveDelivery = null; } } } [HarmonyPatch(typeof(DeliveriesLoader))] internal static class LoaderPatch { private static readonly Logger Logger = new Logger("LoaderPatch"); [HarmonyPatch("Load")] [HarmonyPrefix] private static bool Load(DeliveriesLoader __instance, string mainPath) { bool flag = false; string text = default(string); if (((Loader)__instance).TryLoadFile(Path.Combine(mainPath, "Deliveries"), ref text, true) || ((Loader)__instance).TryLoadFile(mainPath, ref text, true)) { DeliveriesData val = null; try { val = JsonUtility.FromJson<DeliveriesData>(text); } catch (Exception ex) { Debug.LogError((object)("Error loading data: " + ex.Message)); } if (val != null && val.ActiveDeliveries != null) { LoadDelivery(val); if (val.DeliveryVehicles != null) { flag = true; VehicleData[] deliveryVehicles = val.DeliveryVehicles; VehicleData[] array = deliveryVehicles; foreach (VehicleData data in array) { LoadVehicle(data, mainPath); } } } } if (!flag && Directory.Exists(mainPath)) { Console.Log((object)("Loading legacy delivery vehicles at: " + mainPath), (Object)null); string text2 = Path.Combine(mainPath, "DeliveryVehicles"); List<DirectoryInfo> directories = ((Loader)__instance).GetDirectories(text2); for (int j = 0; j < directories.Count; j++) { __instance.LoadVehicle(directories[j].FullName); } } return false; } private static void LoadVehicle(VehicleData data, string path) { VehicleData data2 = data; Logger.Debug("Processing GUID " + data2.GUID); DeliveryVehicle? obj = ((IEnumerable<DeliveryVehicle>)PoolManager.Instance.Pool).FirstOrDefault((Func<DeliveryVehicle, bool>)((DeliveryVehicle dv) => dv.Vehicle.GUID.ToString() == data2.GUID)); LandVehicle val = ((obj != null) ? obj.Vehicle : null); if ((Object)(object)val == (Object)null) { Logger.Debug("GUID " + data2.GUID + " not found in Pool, lookup via GUIDManager"); val = GUIDManager.GetObject<LandVehicle>(new Guid(data2.GUID)); } if ((Object)(object)val == (Object)null) { Logger.Error("Vehicle not found with GUID", data2.GUID); Console.LogError((object)("LoadVehicle: Vehicle not found with GUID " + data2.GUID), (Object)null); } else { LoadVehicle(val, data2, path); } } private static void LoadVehicle(LandVehicle vehicle, VehicleData data, string containerPath) { Logger.Debug($"Processing vehicle {((Object)vehicle).name} with GUID {vehicle.GUID}"); if ((Object)(object)vehicle.Storage != (Object)null) { if (data.VehicleContents != null && data.VehicleContents.Items != null) { DeserializedItemSet val = default(DeserializedItemSet); if (ItemSet.TryDeserialize(data.VehicleContents, ref val)) { val.LoadTo(vehicle.Storage.ItemSlots); } } else if (File.Exists(Path.Combine(containerPath, "Contents.json"))) { Console.LogWarning((object)"Loading legacy vehicle contents.", (Object)null); string text = default(string); DeserializedItemSet val2 = default(DeserializedItemSet); if (vehicle.Loader.TryLoadFile(containerPath, "Contents", ref text) && ItemSet.TryDeserialize(text, ref val2)) { val2.LoadTo(vehicle.Storage.ItemSlots); } } } if (data.SpraySurfaces == null) { return; } try { for (int i = 0; i < data.SpraySurfaces.Count; i++) { if (vehicle._spraySurfaces.Length > i) { SpraySurface obj = vehicle._spraySurfaces[i]; if (obj != null) { obj.Set((NetworkConnection)null, data.SpraySurfaces[i].Strokes.ToArray(), data.SpraySurfaces[i].ContainsCartelGraffiti); } } } } catch (Exception ex) { Logger.Error("Exception thrown while loading saved graffities", ex); } } private static void LoadDelivery(DeliveriesData data) { if (data == null) { return; } if (data.ActiveDeliveries != null) { DeliveryInstance[] activeDeliveries = data.ActiveDeliveries; DeliveryInstance[] array = activeDeliveries; foreach (DeliveryInstance val in array) { NetworkSingleton<DeliveryManager>.Instance.SendDelivery(val); } } if (data.DeliveryHistory != null) { DeliveryReceipt[] deliveryHistory = data.DeliveryHistory; foreach (DeliveryReceipt val2 in deliveryHistory) { NetworkSingleton<DeliveryManager>.Instance._deliveryHistory.Add(val2); } } if (data.DisplayedDeliveryHistory != null) { DeliveryReceipt[] displayedDeliveryHistory = data.DisplayedDeliveryHistory; foreach (DeliveryReceipt val3 in displayedDeliveryHistory) { NetworkSingleton<DeliveryManager>.Instance._displayedDeliveryHistory.Add(val3); } } } } public class PoolManager { private static readonly Logger Logger = new Logger("PoolManager"); public static PoolManager Instance { get; } = new PoolManager(); public HashSet<DeliveryVehicle> Pool { get; } = new HashSet<DeliveryVehicle>(); internal Dictionary<string, DeliveryVehicle> Allocations { get; } = new Dictionary<string, DeliveryVehicle>(); internal Dictionary<string, bool> BaseVehicleAllocationsForShop { get; } = new Dictionary<string, bool>(); public void AddToPool(DeliveryVehicle deliveryVehicle, bool notify = true) { Pool.Add(deliveryVehicle); if (notify) { NetworkConvenienceMethods.NotifyVehicleAdded(deliveryVehicle); } } public void AddToSaveData(DeliveryVehicle deliveryVehicle) { if ((Object)(object)deliveryVehicle == (Object)null) { throw new ArgumentNullException("deliveryVehicle"); } VehicleSave.Instance.AddVehicle(deliveryVehicle.Vehicle); NetworkConvenienceMethods.NotifyVehicleCreated(deliveryVehicle); } public DeliveryVehicle? GetFirstFree() { DeliveryVehicle val = ((IEnumerable<DeliveryVehicle>)Pool).FirstOrDefault((Func<DeliveryVehicle, bool>)((DeliveryVehicle dv) => dv.ActiveDelivery == null && !Allocations.ContainsValue(dv))); if (Time.frameCount % 30 == 0) { Logger.Debug("Pool lookup: " + (((Object)(object)val == (Object)null) ? "null" : "not null")); } return val; } public DeliveryVehicle GetOrAllocateFirstFree(string deliveryId) { Logger.Debug("GetOrAllocateFirstFree called for: " + deliveryId); if (Allocations.TryGetValue(deliveryId, out DeliveryVehicle value)) { Logger.Debug("Already allocated, returning existing"); return value; } DeliveryVehicle firstFree = GetFirstFree(); if ((Object)(object)firstFree == (Object)null) { Logger.Debug($"No free vehicle found! Pool count: {Pool.Count}, Allocations count: {Allocations.Count}"); foreach (KeyValuePair<string, DeliveryVehicle> allocation in Allocations) { Logger.Debug("Allocation: " + allocation.Key + " -> Vehicle has ActiveDelivery: " + (allocation.Value.ActiveDelivery?.DeliveryID ?? "null")); } throw new ArgumentException("Tried to allocate a non-free vehicle"); } Allocations.Add(deliveryId, firstFree); Logger.Debug("Allocated new vehicle for " + deliveryId + ", vehicle: " + firstFree.GUID); NetworkConvenienceMethods.NotifyAllocation(deliveryId, firstFree, isAllocated: true); return firstFree; } public void FreeAllocation(string deliveryId) { Logger.Debug("Free custom allocation: " + deliveryId); if (Allocations.TryGetValue(deliveryId, out DeliveryVehicle value)) { Allocations.Remove(deliveryId); NetworkConvenienceMethods.NotifyAllocation(deliveryId, value, isAllocated: false); } } } [HarmonyPatch(typeof(Wheel))] internal class WheelPatch { [HarmonyPatch("OnWeatherChange")] [HarmonyPrefix] private static bool ExitIfNull(Wheel __instance, WeatherConditions newConditions) { if ((Object)(object)__instance?.vehicle == (Object)null) { return false; } if (newConditions != null) { _ = newConditions.Rainy; if (0 == 0) { return true; } } return false; } } [HarmonyPatch(typeof(DeliveryVehicle))] internal static class DeliveryVehicleAwakePatch { [HarmonyPatch("Awake")] [HarmonyPrefix] private static bool ExitIfNull(DeliveryVehicle __instance) { if (Guid.TryParse(__instance.GUID, out var _)) { return true; } if ((Object)(object)((Component)__instance).GetComponent<LandVehicle>() == (Object)null) { return false; } __instance.Vehicle = ((Component)__instance).GetComponent<LandVehicle>(); __instance.Deactivate(); return false; } } } namespace MultiDelivery.Persistence { public class PersistentDropoffQuestData : Saveable { [SaveableField("MessageData")] public bool HasMessaged; public static PersistentDropoffQuestData Instance { get; private set; } = new PersistentDropoffQuestData(); public PersistentDropoffQuestData() { Instance = this; } } public class VehicleSave : Saveable { [CompilerGenerated] private sealed class <DeferredSetColor>d__12 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public LandVehicle vehicle; public EVehicleColor color; public VehicleSave <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DeferredSetColor>d__12(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0086: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; goto IL_0044; case 1: <>1__state = -1; goto IL_0044; case 2: { <>1__state = -1; vehicle.ApplyColor(color); return false; } IL_0044: if ((Object)(object)Player.Local == (Object)null || (Object)(object)((Component)Player.Local).gameObject == (Object)null) { <>2__current = null; <>1__state = 1; return true; } <>2__current = null; <>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(); } } [SaveableField("VehicleSaveData")] private List<VehicleSaveDto> _dtos = new List<VehicleSaveDto>(); private static readonly Logger Logger = new Logger("VehicleSave"); private static Transform _parent; public override SaveableLoadOrder LoadOrder => (SaveableLoadOrder)0; public static VehicleSave Instance { get; set; } = new VehicleSave(); public VehicleSave() { Instance = this; } public void AddVehicle(LandVehicle vehicle) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) VehicleSaveDto item = new VehicleSaveDto { Guid = vehicle.GUID.ToString(), VehicleType = vehicle.VehicleCode, Color = vehicle.Color.displayedColor }; if (!_dtos.Contains(item)) { _dtos.Add(item); } } protected override void OnLoaded() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) Melon<MultiDelivery>.Logger.Msg($"VehicleSave.OnLoaded: Loading {_dtos.Count} vehicles"); if ((Object)(object)_parent == (Object)null) { GameObject val = GameObject.Find("VehiclePool"); if ((Object)(object)val == (Object)null) { val = new GameObject("VehiclePool"); } _parent = val.transform; } for (int i = 0; i < _dtos.Count; i++) { Logger.Debug($"Loading vehicle {i}: {_dtos[i].Guid}"); Guid guid = new Guid(_dtos[i].Guid); LandVehicle val2 = new LandVehicleBuilder().WithVehicleCode(_dtos[i].VehicleType).WithVehicleName($"Additional Delivery Vehicle {i + 1}").WithGuid(guid) .WithColor(_dtos[i].Color) .WithParent(_parent) .Build(); MelonCoroutines.Start(DeferredSetColor(val2, _dtos[i].Color)); Logger.Debug($"Built LandVehicle: {val2.vehicleName}, ObjectId: {((NetworkBehaviour)val2).ObjectId}"); DeliveryVehicle val3 = new DeliveryVehicleBuilder().WithLandVehicle(val2).WithGuid(guid).Build(); Logger.Debug("Built DeliveryVehicle: " + val3.GUID); PoolManager.Instance.AddToPool(val3); Logger.Debug($"Added to pool. Pool count now: {PoolManager.Instance.Pool.Count}"); } Logger.Msg($"VehicleSave.OnLoaded complete. Final pool count: {PoolManager.Instance.Pool.Count}"); } [IteratorStateMachine(typeof(<DeferredSetColor>d__12))] private IEnumerator DeferredSetColor(LandVehicle vehicle, EVehicleColor color) { //IL_0015: 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) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DeferredSetColor>d__12(0) { <>4__this = this, vehicle = vehicle, color = color }; } } public record VehicleSaveDto { public string Guid { get; set; } public string VehicleType { get; set; } public EVehicleColor Color { get; set; } [CompilerGenerated] protected virtual bool PrintMembers(StringBuilder builder) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) RuntimeHelpers.EnsureSufficientExecutionStack(); builder.Append("Guid = "); builder.Append((object?)Guid); builder.Append(", VehicleType = "); builder.Append((object?)VehicleType); builder.Append(", Color = "); EVehicleColor color = Color; builder.Append(((object)(EVehicleColor)(ref color)).ToString()); return true; } } } namespace MultiDelivery.Network { public class DeliveryNetworkManager { [CompilerGenerated] private sealed class <>c__DisplayClass22_0 { public DeliveryNetworkManager <>4__this; public VehicleAddedMessage message; internal bool <OnVehicleAdded>b__2() { return (Object)(object)<>4__this.FindLandVehicleByObjectId(message.ObjectId) != (Object)null; } } [CompilerGenerated] private sealed class <>c__DisplayClass23_0 { public DeliveryNetworkManager <>4__this; public VehicleCreatedMessage message; internal bool <OnVehicleCreated>b__2() { return (Object)(object)<>4__this.FindLandVehicleByObjectId(message.ObjectId) != (Object)null; } } [CompilerGenerated] private sealed class <>c__DisplayClass25_0 { public VehiclePoolSyncResponse message; public DeliveryNetworkManager <>4__this; public Func<VehiclePoolSyncResponse.VehicleData, bool> <>9__3; internal bool <OnPoolSyncResponse>b__2() { return message.Vehicles.All((VehiclePoolSyncResponse.VehicleData v) => (Object)(object)<>4__this.FindLandVehicleByObjectId(v.ObjectId) != (Object)null); } internal bool <OnPoolSyncResponse>b__3(VehiclePoolSyncResponse.VehicleData v) { return (Object)(object)<>4__this.FindLandVehicleByObjectId(v.ObjectId) != (Object)null; } } [CompilerGenerated] private sealed class <>c__DisplayClass26_0 { public VehicleAllocationMessage message; public DeliveryNetworkManager <>4__this; public Func<DeliveryVehicle, bool> <>9__3; internal bool <OnVehicleAllocation>b__2() { return (Object)(object)((IEnumerable<DeliveryVehicle>)PoolManager.Instance.Pool).FirstOrDefault((Func<DeliveryVehicle, bool>)((DeliveryVehicle v) => v.GUID == message.VehicleGuid)) != (Object)null; } internal bool <OnVehicleAllocation>b__3(DeliveryVehicle v) { return v.GUID == message.VehicleGuid; } internal bool <OnVehicleAllocation>b__4(DeliveryVehicle v) { return v.GUID == message.VehicleGuid; } } [CompilerGenerated] private sealed class <ExponentialBackoff>d__34 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Func<bool> predicate; public float initialDelay; public float finalDelay; public float timeout; private float <delay>5__1; private float <elapsed>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ExponentialBackoff>d__34(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <delay>5__1 = initialDelay; <elapsed>5__2 = 0f; break; case 1: <>1__state = -1; <elapsed>5__2 += <delay>5__1; <delay>5__1 = Mathf.Min(<delay>5__1 * 2f, finalDelay); break; } if (!predicate() && <elapsed>5__2 < timeout) { <>2__current = (object)new WaitForSeconds(<delay>5__1); <>1__state = 1; return true; } 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 SteamNetworkClient _client; private readonly Logger _logger; private const string ModDataKey = "MultiDelivery_Version"; private const string ModVersion = "1.0.0"; private bool IsInLobby { get { SteamNetworkClient client = _client; return client != null && client.IsInLobby; } } private bool IsHost { get { SteamNetworkClient client = _client; return client != null && client.IsHost; } } private bool IsSingleplayer => !IsInLobby; internal bool HostOrSingleplayer => IsHost || IsSingleplayer; public DeliveryNetworkManager() { _logger = new Logger("Network", LogLevel.NetworkTrace); } public bool Initialize() { //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_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown try { NetworkRules val = new NetworkRules { EnableRelay = true, AcceptOnlyFriends = false }; _client = new SteamNetworkClient(val); if (!_client.Initialize()) { _logger.Error("Failed to initialize SteamNetworkClient"); return false; } RegisterMessageHandlers(); SubscribeToEvents(); _logger.Msg("Network manager initialized successfully"); return true; } catch (Exception arg) { _client = null; _logger.Error($"Failed to initialize network manager: {arg}"); return false; } } private void RegisterMessageHandlers() { _client.RegisterMessageHandler<VehicleAddedMessage>((Action<VehicleAddedMessage, CSteamID>)OnVehicleAdded); _client.RegisterMessageHandler<VehicleCreatedMessage>((Action<VehicleCreatedMessage, CSteamID>)OnVehicleCreated); _client.RegisterMessageHandler<VehiclePoolSyncRequest>((Action<VehiclePoolSyncRequest, CSteamID>)OnPoolSyncRequest); _client.RegisterMessageHandler<VehiclePoolSyncResponse>((Action<VehiclePoolSyncResponse, CSteamID>)OnPoolSyncResponse); _client.RegisterMessageHandler<VehicleAllocationMessage>((Action<VehicleAllocationMessage, CSteamID>)OnVehicleAllocation); _client.RegisterMessageHandler<BaseVehicleAllocationMessage>((Action<BaseVehicleAllocationMessage, CSteamID>)OnBaseVehicleAllocation); } private void SubscribeToEvents() { _client.OnLobbyCreated += OnLobbyCreated; _client.OnLobbyJoined += OnLobbyJoined; _client.OnMemberJoined += OnMemberJoined; _client.OnLobbyLeft += OnLobbyLeft; } public void Update() { SteamNetworkClient client = _client; if (client != null) { client.ProcessIncomingMessages(); } } public void Dispose() { SteamNetworkClient client = _client; if (client != null) { client.Dispose(); } } public async void BroadcastVehicleAdded(DeliveryVehicle vehicle) { if (!IsSingleplayer) { VehicleAddedMessage message = new VehicleAddedMessage { ObjectId = ((NetworkBehaviour)vehicle.Vehicle).ObjectId, VehicleGuid = vehicle.GUID, VehicleName = vehicle.Vehicle.vehicleName, VehicleCode = vehicle.Vehicle.VehicleCode, VehicleColor = (int)vehicle.Vehicle.Color.displayedColor }; _logger.Msg($"Broadcasting vehicle added: ObjectId={message.ObjectId}, GUID={message.VehicleGuid}"); await _client.BroadcastMessageAsync((P2PMessage)(object)message); } } public async void BroadcastVehicleCreated(DeliveryVehicle vehicle) { if (!IsSingleplayer && !IsHost) { VehicleCreatedMessage message = new VehicleCreatedMessage { ObjectId = ((NetworkBehaviour)vehicle.Vehicle).ObjectId, VehicleGuid = vehicle.GUID }; _logger.Msg($"Broadcasting vehicle created: ObjectId={message.ObjectId}"); await _client.BroadcastMessageAsync((P2PMessage)(object)message); } } public async void BroadcastVehicleAllocation(string deliveryId, DeliveryVehicle vehicle, bool isAllocated) { if (!IsSingleplayer) { VehicleAllocationMessage message = new VehicleAllocationMessage { DeliveryId = deliveryId, VehicleGuid = vehicle.GUID, IsAllocated = isAllocated }; _logger.Msg($"Broadcasting allocation: Delivery={deliveryId}, Vehicle={vehicle.GUID}, Allocated={isAllocated}"); await _client.BroadcastMessageAsync((P2PMessage)(object)message); } } public async void BroadcastBaseVehicleAllocation(string shopName, bool isAllocated) { if (!IsSingleplayer) { BaseVehicleAllocationMessage message = new BaseVehicleAllocationMessage { ShopName = shopName, IsAllocated = isAllocated }; _logger.Msg($"Broadcasting base allocation: Shop={shopName}, Allocated={isAllocated}"); await _client.BroadcastMessageAsync((P2PMessage)(object)message); } } private void OnVehicleAdded(VehicleAddedMessage message, CSteamID cSteamID) { <>c__DisplayClass22_0 CS$<>8__locals0 = new <>c__DisplayClass22_0(); CS$<>8__locals0.<>4__this = this; CS$<>8__locals0.message = message; _logger.Msg($"Received VehicleAdded: ObjectId={CS$<>8__locals0.message.ObjectId}, GUID={CS$<>8__locals0.message.VehicleGuid}"); MelonCoroutines.Start(ProcessMessage()); [IteratorStateMachine(typeof(<>c__DisplayClass22_0.<<OnVehicleAdded>g__ProcessMessage|0>d))] IEnumerator ProcessMessage() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <>c__DisplayClass22_0.<<OnVehicleAdded>g__ProcessMessage|0>d(0) { <>4__this = CS$<>8__locals0 }; } } private void OnVehicleCreated(VehicleCreatedMessage message, CSteamID senderId) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) <>c__DisplayClass23_0 CS$<>8__locals0 = new <>c__DisplayClass23_0(); CS$<>8__locals0.<>4__this = this; CS$<>8__locals0.message = message; if (IsHost) { _logger.Msg($"Received vehicle created message from {senderId}"); MelonCoroutines.Start(ProcessMessage()); } [IteratorStateMachine(typeof(<>c__DisplayClass23_0.<<OnVehicleCreated>g__ProcessMessage|0>d))] IEnumerator ProcessMessage() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <>c__DisplayClass23_0.<<OnVehicleCreated>g__ProcessMessage|0>d(0) { <>4__this = CS$<>8__locals0 }; } } private async void OnPoolSyncRequest(VehiclePoolSyncRequest message, CSteamID senderId) { //IL_0020: 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) if (!IsHost) { return; } _logger.Msg($"Received pool sync request from {senderId}"); try { VehiclePoolSyncResponse response = new VehiclePoolSyncResponse(); foreach (DeliveryVehicle vehicle in PoolManager.Instance.Pool) { response.Vehicles.Add(new VehiclePoolSyncResponse.VehicleData { ObjectId = ((NetworkBehaviour)vehicle.Vehicle).ObjectId, Guid = vehicle.GUID, Name = vehicle.Vehicle.vehicleName, Code = vehicle.Vehicle.VehicleCode, Color = (int)vehicle.Vehicle.Color.displayedColor }); } _logger.Msg($"Sending pool sync with {response.Vehicles.Count} vehicles"); await _client.SendMessageToPlayerAsync(senderId, (P2PMessage)(object)response); } catch (Exception ex) { _logger.Error($"Failed to send pool sync: {ex}"); } } private void OnPoolSyncResponse(VehiclePoolSyncResponse message, CSteamID senderId) { <>c__DisplayClass25_0 CS$<>8__locals0 = new <>c__DisplayClass25_0(); CS$<>8__locals0.message = message; CS$<>8__locals0.<>4__this = this; if (!IsHost) { _logger.Msg($"Received pool sync response with {CS$<>8__locals0.message.Vehicles.Count} vehicles"); MelonCoroutines.Start(ProcessMessage()); } [IteratorStateMachine(typeof(<>c__DisplayClass25_0.<<OnPoolSyncResponse>g__ProcessMessage|0>d))] IEnumerator ProcessMessage() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <>c__DisplayClass25_0.<<OnPoolSyncResponse>g__ProcessMessage|0>d(0) { <>4__this = CS$<>8__locals0 }; } } private void OnVehicleAllocation(VehicleAllocationMessage message, CSteamID senderId) { <>c__DisplayClass26_0 CS$<>8__locals0 = new <>c__DisplayClass26_0(); CS$<>8__locals0.message = message; CS$<>8__locals0.<>4__this = this; _logger.Msg($"Received allocation: Delivery={CS$<>8__locals0.message.DeliveryId}, Vehicle={CS$<>8__locals0.message.VehicleGuid}, Allocated={CS$<>8__locals0.message.IsAllocated}"); MelonCoroutines.Start(ProcessMessage()); [IteratorStateMachine(typeof(<>c__DisplayClass26_0.<<OnVehicleAllocation>g__ProcessMessage|0>d))] IEnumerator ProcessMessage() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <>c__DisplayClass26_0.<<OnVehicleAllocation>g__ProcessMessage|0>d(0) { <>4__this = CS$<>8__locals0 }; } } private void OnBaseVehicleAllocation(BaseVehicleAllocationMessage message, CSteamID senderId) { _logger.Msg($"Received base allocation: Shop={message.ShopName}, Allocated={message.IsAllocated}"); try { PoolManager.Instance.BaseVehicleAllocationsForShop[message.ShopName] = message.IsAllocated; } catch (Exception arg) { _logger.Error($"Failed to process base allocation: {arg}"); } } private void OnLobbyCreated(object sender, LobbyCreatedEventArgs e) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) _logger.Msg($"Lobby created: {e.Lobby.LobbyId}"); _client.SetMyData("MultiDelivery_Version", "1.0.0"); } private void OnLobbyJoined(object sender, LobbyJoinedEventArgs e) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) _logger.Msg($"Joined lobby: {e.Lobby.LobbyId}"); _client.SetMyData("MultiDelivery_Version", "1.0.0"); if (!IsHost) { RequestPoolSync(); } } private async void OnMemberJoined(object sender, MemberJoinedEventArgs e) { if (!IsHost) { return; } _logger.Msg("Member joined: " + e.Member.DisplayName); await Task.Delay(1000); VehiclePoolSyncResponse response = new VehiclePoolSyncResponse(); foreach (DeliveryVehicle vehicle in PoolManager.Instance.Pool) { response.Vehicles.Add(new VehiclePoolSyncResponse.VehicleData { ObjectId = ((NetworkBehaviour)vehicle.Vehicle).ObjectId, Guid = vehicle.GUID, Name = vehicle.Vehicle.vehicleName, Code = vehicle.Vehicle.VehicleCode, Color = (int)vehicle.Vehicle.Color.displayedColor }); } _logger.Msg($"Sending pool sync to new member ({response.Vehicles.Count} vehicles)"); await _client.SendMessageToPlayerAsync(e.Member.SteamId, (P2PMessage)(object)response); } private void OnLobbyLeft(object sender, LobbyLeftEventArgs e) { _logger.Msg("Left lobby: " + e.Reason); } private async void RequestPoolSync() { if (!IsSingleplayer && !IsHost) { List<MemberInfo> members = _client.GetLobbyMembers(); MemberInfo host = ((IEnumerable<MemberInfo>)members).FirstOrDefault((Func<MemberInfo, bool>)((MemberInfo m) => m.IsOwner)); if (host == null) { _logger.Error("Cannot request pool sync - no host found"); return; } VehiclePoolSyncRequest vehiclePoolSyncRequest = new VehiclePoolSyncRequest(); CSteamID localPlayerId = _client.LocalPlayerId; vehiclePoolSyncRequest.RequesterId = ((object)(CSteamID)(ref localPlayerId)).ToString(); VehiclePoolSyncRequest message = vehiclePoolSyncRequest; _logger.Msg("Requesting pool sync from host"); await _client.SendMessageToPlayerAsync(host.SteamId, (P2PMessage)(object)message); } } private LandVehicle? FindLandVehicleByObjectId(int objectId) { //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) Scene sceneByName = SceneManager.GetSceneByName("Main"); if (!((Scene)(ref sceneByName)).isLoaded) { _logger.Error("Main scene is not loaded"); return null; } GameObject[] rootGameObjects = ((Scene)(ref sceneByName)).GetRootGameObjects(); GameObject[] array = rootGameObjects; foreach (GameObject val in array) { LandVehicle[] componentsInChildren = val.GetComponentsInChildren<LandVehicle>(true); LandVehicle[] array2 = componentsInChildren; foreach (LandVehicle val2 in array2) { if (((NetworkBehaviour)val2).ObjectId == objectId) { _logger.Msg($"Found LandVehicle: ObjectId={objectId}, Name={val2.vehicleName}"); return val2; } } } _logger.Warning($"LandVehicle with ObjectId {objectId} not found in Main scene"); return null; } [IteratorStateMachine(typeof(<ExponentialBackoff>d__34))] private static IEnumerator ExponentialBackoff(Func<bool> predicate, float initialDelay, float finalDelay, float timeout) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ExponentialBackoff>d__34(0) { predicate = predicate, initialDelay = initialDelay, finalDelay = finalDelay, timeout = timeout }; } } public class VehicleAddedMessage : P2PMessage { public override string MessageType => "VehicleAdded"; public int ObjectId { get; set; } public string VehicleGuid { get; set; } public string VehicleName { get; set; } public string VehicleCode { get; set; } public int VehicleColor { get; set; } public override byte[] Serialize() { string s = ((P2PMessage)this).CreateJsonBase($"\"ObjectId\":{ObjectId},\"VehicleGuid\":\"{VehicleGuid}\",\"VehicleName\":\"{VehicleName}\",\"VehicleCode\":\"{VehicleCode}\",\"VehicleColor\":{VehicleColor}"); return Encoding.UTF8.GetBytes(s); } public override void Deserialize(byte[] data) { string @string = Encoding.UTF8.GetString(data); ((P2PMessage)this).ParseJsonBase(@string); ObjectId = int.Parse(((P2PMessage)this).ExtractJsonValue(@string, "ObjectId")); VehicleGuid = ((P2PMessage)this).ExtractJsonValue(@string, "VehicleGuid"); VehicleName = ((P2PMessage)this).ExtractJsonValue(@string, "VehicleName"); VehicleCode = ((P2PMessage)this).ExtractJsonValue(@string, "VehicleCode"); VehicleColor = int.Parse(((P2PMessage)this).ExtractJsonValue(@string, "VehicleColor")); } } public class VehicleCreatedMessage : P2PMessage { public override string MessageType => "VehicleCreated"; public int ObjectId { get; set; } public string VehicleGuid { get; set; } public override byte[] Serialize() { string s = ((P2PMessage)this).CreateJsonBase($"\"ObjectId\":{ObjectId},\"VehicleGuid\":\"{VehicleGuid}\""); return Encoding.UTF8.GetBytes(s); } public override void Deserialize(byte[] data) { string @string = Encoding.UTF8.GetString(data); ((P2PMessage)this).ParseJsonBase(@string); ObjectId = int.Parse(((P2PMessage)this).ExtractJsonValue(@string, "ObjectId")); VehicleGuid = ((P2PMessage)this).ExtractJsonValue(@string, "VehicleGuid"); } } public class VehiclePoolSyncRequest : P2PMessage { public override string MessageType => "VehiclePoolSyncRequest"; public string RequesterId { get; set; } public override byte[] Serialize() { string s = ((P2PMessage)this).CreateJsonBase("\"RequesterId\":\"" + RequesterId + "\""); return Encoding.UTF8.GetBytes(s); } public override void Deserialize(byte[] data) { string @string = Encoding.UTF8.GetString(data); ((P2PMessage)this).ParseJsonBase(@string); RequesterId = ((P2PMessage)this).ExtractJsonValue(@string, "RequesterId"); } } public class VehiclePoolSyncResponse : P2PMessage { [Serializable] public class VehicleData { public int ObjectId { get; set; } public string Guid { get; set; } public string Name { get; set; } public string Code { get; set; } public int Color { get; set; } } public override string MessageType => "VehiclePoolSyncResponse"; public List<VehicleData> Vehicles { get; set; } = new List<VehicleData>(); public override byte[] Serialize() { string text = string.Join(",", Vehicles.Select((VehicleData v) => $"{{\"ObjectId\":{v.ObjectId},\"Guid\":\"{v.Guid}\",\"Name\":\"{v.Name}\",\"Code\":\"{v.Code}\",\"Color\":{v.Color}}}")); string s = ((P2PMessage)this).CreateJsonBase("\"Vehicles\":[" + text + "]"); return Encoding.UTF8.GetBytes(s); } public override void Deserialize(byte[] data) { string @string = Encoding.UTF8.GetString(data); ((P2PMessage)this).ParseJsonBase(@string); int num = @string.IndexOf("\"Vehicles\":[", StringComparison.Ordinal) + 12; int num2 = @string.IndexOf("]", num, StringComparison.Ordinal); string text = @string.Substring(num, num2 - num); Vehicles.Clear(); if (string.IsNullOrWhiteSpace(text)) { return; } string[] array = text.Split(new string[1] { "}," }, StringSplitOptions.None); string[] array2 = array; foreach (string text2 in array2) { string text3 = text2.TrimStart('{').TrimEnd('}') + "}"; if (text3.Contains("ObjectId")) { Vehicles.Add(new VehicleData { ObjectId = int.Parse(((P2PMessage)this).ExtractJsonValue(text3, "ObjectId")), Guid = ((P2PMessage)this).ExtractJsonValue(text3, "Guid"), Name = ((P2PMessage)this).ExtractJsonValue(text3, "Name"), Code = ((P2PMessage)this).ExtractJsonValue(text3, "Code"), Color = int.Parse(((P2PMessage)this).ExtractJsonValue(text3, "Color")) }); } } } } public class VehicleAllocationMessage : P2PMessage { public override string MessageType => "VehicleAllocation"; public string DeliveryId { get; set; } public string VehicleGuid { get; set; } public bool IsAllocated { get; set; } public override byte[] Serialize() { string s = ((P2PMessage)this).CreateJsonBase("\"DeliveryId\":\"" + DeliveryId + "\",\"VehicleGuid\":\"" + VehicleGuid + "\",\"IsAllocated\":" + IsAllocated.ToString().ToLower()); return Encoding.UTF8.GetBytes(s); } public override void Deserialize(byte[] data) { string @string = Encoding.UTF8.GetString(data); ((P2PMessage)this).ParseJsonBase(@string); DeliveryId = ((P2PMessage)this).ExtractJsonValue(@string, "DeliveryId"); VehicleGuid = ((P2PMessage)this).ExtractJsonValue(@string, "VehicleGuid"); IsAllocated = bool.Parse(((P2PMessage)this).ExtractJsonValue(@string, "IsAllocated")); } } public class BaseVehicleAllocationMessage : P2PMessage { public override string MessageType => "BaseVehicleAllocation"; public string ShopName { get; set; } public bool IsAllocated { get; set; } public override byte[] Serialize() { string s = ((P2PMessage)this).CreateJsonBase("\"ShopName\":\"" + ShopName + "\",\"IsAllocated\":" + IsAllocated.ToString().ToLower()); return Encoding.UTF8.GetBytes(s); } public override void Deserialize(byte[] data) { string @string = Encoding.UTF8.GetString(data); ((P2PMessage)this).ParseJsonBase(@string); ShopName = ((P2PMessage)this).ExtractJsonValue(@string, "ShopName"); IsAllocated = bool.Parse(((P2PMessage)this).ExtractJsonValue(@string, "IsAllocated")); } } public static class NetworkConvenienceMethods { private static DeliveryNetworkManager? _networkManager; public static bool HostOrSingleplayer => _networkManager?.HostOrSingleplayer ?? true; public static void InitializeNetworking(DeliveryNetworkManager networkManager) { _networkManager = networkManager; } public static void NotifyVehicleAdded(DeliveryVehicle vehicle) { _networkManager?.BroadcastVehicleAdded(vehicle); } public static void NotifyVehicleCreated(DeliveryVehicle vehicle) { _networkManager?.BroadcastVehicleCreated(vehicle); } public static void NotifyAllocation(string deliveryId, DeliveryVehicle vehicle, bool isAllocated) { _networkManager?.BroadcastVehicleAllocation(deliveryId, vehicle, isAllocated); } public static void NotifyBaseAllocation(string shopName, bool isAllocated) { _networkManager?.BroadcastBaseVehicleAllocation(shopName, isAllocated); } } } namespace MultiDelivery.Helpers { public static class MelonLoggerExtensions { public static void Debug(this Instance logger, string message, bool stacktrace = true) { MelonDebug.Msg(stacktrace ? ("[" + GetCallerInfo() + "] " + message) : message); } private static string GetCallerInfo() { StackTrace stackTrace = new StackTrace(); for (int i = 2; i < stackTrace.FrameCount; i++) { StackFrame frame = stackTrace.GetFrame(i); MethodBase method = frame.GetMethod(); if (!(method?.DeclaringType == null)) { return method.DeclaringType.FullName + "." + method.Name; } } return "unknown"; } } public static class Il2CppListExtensions { public static IEnumerable<T> AsEnumerable<T>(this List<T> list) { return list ?? new List<T>(); } public static object ToNativeList<T>(this List<T> source) { return source ?? new List<T>(); } } public static class Utils { [CompilerGenerated] private sealed class <WaitForCondition>d__6 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Func<bool> condition; public float timeout; public Action onTimeout; public Action onFinish; private float <startTime>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WaitForCondition>d__6(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 (!condition()) { if (!float.IsNaN(timeout) && Time.time - <startTime>5__1 > timeout) { onTimeout?.Invoke(); return false; } <>2__current = null; <>1__state = 1; return true; } onFinish?.Invoke(); 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 <WaitForNetwork>d__5 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public IEnumerator routine; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WaitForNetwork>d__5(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; break; case 1: <>1__state = -1; break; } if (!InstanceFinder.IsServer && !InstanceFinder.IsClient) { <>2__current = null; <>1__state = 1; return true; } MelonCoroutines.Start(routine); 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 <WaitForPlayer>d__4 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public IEnumerator routine; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WaitForPlayer>d__4(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; break; case 1: <>1__state = -1; break; } if ((Object)(object)Player.Local == (Object)null || (Object)(object)((Component)Player.Local).gameObject == (Object)null) { <>2__current = null; <>1__state = 1; return true; } MelonCoroutines.Start(routine); 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 static readonly Instance Logger = new Instance("MultiDelivery-Utils"); public static T? FindObjectByName<T>(string objectName) where T : Object { try { T[] array = Resources.FindObjectsOfTypeAll<T>(); foreach (T val in array) { if (!(((Object)val).name != objectName)) { Logger.Debug("Found " + typeof(T).Name + " '" + objectName + "' directly in loaded objects"); return val; } } return default(T); } catch (Exception ex) { Logger.Error("Error finding " + typeof(T).Name + " '" + objectName + "': " + ex.Message); return default(T); } } public static List<T> GetAllComponentsInChildrenRecursive<T>(GameObject obj) where T : Component { List<T> list = new List<T>(); if ((Object)(object)obj == (Object)null) { return list; } T[] components = obj.GetComponents<T>(); if (components.Length != 0) { list.AddRange(components); } for (int i = 0; i < obj.transform.childCount; i++) { Transform child = obj.transform.GetChild(i); list.AddRange(GetAllComponentsInChildrenRecursive<T>(((Component)child).gameObject)); } return list; } public static bool Is<T>(object obj, out T? result) where T : class { if (obj is T val) { result = val; return true; } result = null; return false; } [IteratorStateMachine(typeof(<WaitForPlayer>d__4))] public static IEnumerator WaitForPlayer(IEnumerator routine) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WaitForPlayer>d__4(0) { routine = routine }; } [IteratorStateMachine(typeof(<WaitForNetwork>d__5))] public static IEnumerator WaitForNetwork(IEnumerator routine) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WaitForNetwork>d__5(0) { routine = routine }; } [IteratorStateMachine(typeof(<WaitForCondition>d__6))] public static IEnumerator WaitForCondition(Func<bool> condition, float timeout = float.NaN, Action? onTimeout = null, Action? onFinish = null) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WaitForCondition>d__6(0) { condition = condition, timeout = timeout, onTimeout = onTimeout, onFinish = onFinish }; } public static string GetHierarchyPath(this Transform transform) { if ((Object)(object)transform == (Object)null) { return "null"; } string text = ((Object)transform).name; Transform parent = transform.parent; while ((Object)(object)parent != (Object)null) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } public static T GetOrAddComponent<T>(this GameObject gameObject) where T : Component { T component = gameObject.GetComponent<T>(); if ((Object)(object)component != (Object)null) { return component; } component = gameObject.AddComponent<T>(); Logger.Debug("Added component " + typeof(T).Name + " to GameObject " + ((Object)gameObject).name); return component; } public static Material? DrawDebugVisuals(this GameObject gameObject, Color? color = null) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) Renderer component = gameObject.GetComponent<Renderer>(); if ((Object)(object)component == (Object)null) { Logger.Error("GameObject " + ((Object)gameObject).name + " has no Renderer component"); return null; } Color valueOrDefault = color.GetValueOrDefault(); if (!color.HasValue) { ((Color)(ref valueOrDefault))..ctor(1f, 0f, 1f, 0.5f); color = valueOrDefault; } Shader val = Shader.Find("Universal Render Pipeline/Lit"); if ((Object)(object)val == (Object)null) { return null; } Material val2 = new Material(val); if (val2.HasProperty("_Surface")) { val2.SetFloat("_Surface", 1f); } Color value = color.Value; if (value.a <= 0f) { value.a = 0.2f; } if (val2.HasProperty("_BaseColor")) { val2.SetColor("_BaseColor", value); } if (val2.HasProperty("_EmissionColor")) { val2.EnableKeyword("_EMISSION"); val2.SetColor("_EmissionColor", new Color(value.r, value.g, value.b) * 1.5f); } val2.SetInt("_ZWrite", 0); val2.renderQueue = 3000; Material material = component.material; component.material = val2; return material; } public static string Capitalize(this string str) { if (str.Length < 1) { throw new ArgumentOutOfRangeException("str"); } return char.ToUpper(str[0]) + str.Substring(1, str.Length - 1); } } } namespace MultiDelivery.Builders { public class DeliveryVehicleBuilder { private Guid _guid; private LandVehicle _landVehicle; public DeliveryVehicleBuilder WithGuid(Guid guid) { _guid = guid; return this; } public DeliveryVehicleBuilder WithGuid(string guid) { _guid = new Guid(guid); return this; } public DeliveryVehicleBuilder WithLandVehicle(LandVehicle landVehicle) { _landVehicle = landVehicle; return this; } public DeliveryVehicleBuilder WithLandVehicle(GameObject landVehicle) { _landVehicle = landVehicle.GetComponent<LandVehicle>(); return this; } public DeliveryVehicle Build() { DeliveryVehicle val = ((Component)_landVehicle).gameObject.AddComponent<DeliveryVehicle>(); val.GUID = _guid.ToString(); _landVehicle.SetGUID(_guid); return val; } } public class LandVehicleBuilder { private string _vehicleName = "CustomVehicle"; private string _vehicleCode = "veeper"; private EVehicleColor _color = (EVehicleColor)16; private Guid _guid = GUIDManager.GenerateUniqueGUID(); private static Transform? _parent; public LandVehicleBuilder WithVehicleName(string vehicleName) { _vehicleName = vehicleName; return this; } public LandVehicleBuilder WithVehicleCode(string vehicleCode) { _vehicleCode = vehicleCode; return this; } public LandVehicleBuilder WithColor(EVehicleColor color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) _color = color; return this; } public LandVehicleBuilder WithGuid(Guid guid) { _guid = guid; return this; } public LandVehicleBuilder WithGuid(string guid) { _guid = new Guid(guid); return this; } public LandVehicleBuilder WithParent(Transform parent) { _parent = parent; return this; } public LandVehicle Build() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_parent == (Object)null) { GameObject val = GameObject.Find("VehiclePool"); if ((Object)(object)val == (Object)null) { val = new GameObject("VehiclePool"); } _parent = val.transform; } Vector3 position = default(Vector3); ((Vector3)(ref position))..ctor(0f, -100f, 0f); Quaternion identity = Quaternion.identity; if (!InstanceFinder.IsServer) { throw new ArgumentException("LandVehicleBuilder can only be used on the server"); } LandVehicle vehiclePrefab = NetworkSingleton<VehicleManager>.Instance.GetVehiclePrefab(_vehicleCode); if ((Object)(object)vehiclePrefab == (Object)null) { throw new ArgumentException("Vehicle prefab with code '" + _vehicleCode + "' not found."); } GameObject val2 = Object.Instantiate<GameObject>(((Component)vehiclePrefab).gameObject, _parent, true); LandVehicle component = val2.GetComponent<LandVehicle>(); component.IsPlayerOwned = false; component.SetVisible(false); component.IsPhysicallySimulated = false; ((Component)component).transform.position = position; ((Component)component).transform.rotation = identity; component.SetGUID(_guid); ((Object)component).name = _vehicleName; ((Object)((Component)component).gameObject).name = _vehicleName; component.vehicleName = _vehicleName; component.SetIsPlayerOwned((NetworkConnection)null, false); component.Rb.isKinematic = false; ((NetworkBehaviour)component).Owner.ClientId = -1; component.ApplyColor(_color); NetworkSingleton<VehicleManager>.Instance.AllVehicles.Add(component); ((NetworkBehaviour)NetworkSingleton<VehicleManager>.Instance).NetworkObject.Spawn(((Component)component).gameObject, (NetworkConnection)null, default(Scene)); return component; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { internal IgnoresAccessChecksToAttribute(string assemblyName) { } } }