using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using 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.GameConsole.Commands; using MultiDelivery.GameConsole.Commands.Help; using MultiDelivery.GameConsole.Commands.Pool; using MultiDelivery.GameConsole.Commands.Quest; using MultiDelivery.GameConsole.Core; using MultiDelivery.Helpers; using MultiDelivery.Network; using MultiDelivery.Persistence; using MultiDelivery.Pool; using MultiDelivery.Quest; using S1API.Console; 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; using ScheduleOne.UI.Phone.Delivery; using ScheduleOne.UI.Shop; using ScheduleOne.Vehicles; using ScheduleOne.Vehicles.Modification; using ScheduleOne.Weather; using Semver; using SteamNetworkLib; using SteamNetworkLib.Core; using SteamNetworkLib.Events; using SteamNetworkLib.Models; using Steamworks; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; [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.3", "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.3.0")] [assembly: AssemblyInformationalVersion("1.0.3+b82546d5ccdc8a5a55abd97c5cbab4403884cb3e")] [assembly: AssemblyProduct("MultiDelivery-Mono")] [assembly: AssemblyTitle("MultiDelivery-Mono")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.3.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 P; [CompilerGenerated] [DebuggerBrowsable(DebuggerBrowsableState.Never)] private LogLevel? P; public Logger(string categoryName, LogLevel? forceLevel = null) { P = categoryName; 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 = 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(P) ? "MultiDelivery" : ("MultiDelivery." + P)); string text3 = "[" + text2 + "] " + text; switch (level) { case LogLevel.NetworkTrace: if (MultiDelivery.NetworkLogging.Value) { Melon.Logger.Msg(text3); } break; case LogLevel.Debug: MelonDebug.Msg(text3); break; case LogLevel.Info: Melon.Logger.Msg(text3); break; case LogLevel.Warn: Melon.Logger.Warning(text3); break; case LogLevel.Error: Melon.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.3"; } public class MultiDelivery : MelonMod { [CompilerGenerated] private sealed class d__7 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public MultiDelivery <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__7(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(); } } 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 NetworkLogging = Category.CreateEntry("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 override void OnInitializeMelon() { Logger.Msg("MultiDelivery initialized"); DependenciesChecker.PrintMissing(); MelonCoroutines.Start(InitializeNetworkManager()); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { QuestSetupManager.OnSceneWasLoaded(buildIndex, sceneName); if (!(sceneName != "Menu")) { PoolManager.Instance.Pool.Clear(); PoolManager.Instance.Allocations.Clear(); PoolManager.Instance.BaseVehicleAllocationsForShop.Clear(); } } [IteratorStateMachine(typeof(d__7))] private IEnumerator InitializeNetworkManager() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__7(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"); } } } namespace MultiDelivery.Quest { public class DropoffQuest : Quest { [CompilerGenerated] private sealed class d__21 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public DropoffQuest <>4__this; private NPC 5__1; private int 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__21(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 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; 5__2 = 0; break; case 1: { <>1__state = -1; int num = 5__2 + 1; 5__2 = num; break; } } if (5__2 < 3 && PoolManager.Instance.Pool.Count <= <>4__this._startingCapacity) { <>2__current = (object)new WaitForSeconds(3f); <>1__state = 1; return true; } 5__1 = NPC.Get(); if (5__1 != null) { if (PoolManager.Instance.Pool.Count <= <>4__this._startingCapacity) { 5__1.SendTextMessage("Something went wrong... Vehicle got in a car crash :(", (Response[])null, 1f, true); } else { 5__1.SendTextMessage($"Vehicle added, you now can order {PoolManager.Instance.Pool.Count} more " + "deliver" + ((PoolManager.Instance.Pool.Count > 1) ? "ies" : "y") + " from stores.", (Response[])null, 1f, true); 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 => IconLoader.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(d__21))] private IEnumerator NotifyCompletion() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new 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(); if (jeremy == null) { Logger.Warning("Jeremy Wilkinson not found"); return; } jeremy.Dialogue.BuildAndRegisterContainer("DeliveryExpansion", (Action)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)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)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 (" + MoneyManager.FormatAmount(GetVehiclePrice(), false, false) + "). Want to pick one up?", (Action)delegate(ChoiceList ch) { ch.Add("PURCHASE", "I'll take it. (" + MoneyManager.FormatAmount(GetVehiclePrice(), false, false) + ")", "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)null); c.AddNode("NOT_ENOUGH", "You don't have enough money to buy it. Come back later.", (Action)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)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)null); c.AddNode("DECLINED", "No worries, just let me know if you change your mind!", (Action)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(); if ((Object)(object)component != (Object)null) { Dealership dealership = component.Dealership; if ((Object)(object)dealership != (Object)null) { dealership.SpawnVehicle("veeper"); return; } } NetworkSingleton.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"); } internal 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((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.Instance.GetVehiclePrefab("veeper"); return (vehiclePrefab != null) ? vehiclePrefab.VehiclePrice : 5000f; } } public class QuestSetupManager { [CompilerGenerated] private sealed class d__6 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__6(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)(() => 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 += 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"; internal const string QuestStartMessage = "Your properties are getting busy. Want to handle more than one delivery at a time? I've got an idea. Stop by the dealership."; private static FullRank RequiredRank = new FullRank((Rank)5, 1); private static readonly Logger Logger = new Logger("QuestSetupManager"); public static void OnSceneWasLoaded(int buildIndex, string sceneName) { if (!(sceneName == "Main")) { if (sceneName == "Menu") { Player.LocalPlayerSpawned -= WirePlayerEvent; LevelManager.OnXPChanged -= SendMessageIfRequiredRank; } } else { Player.LocalPlayerSpawned += WirePlayerEvent; } } private static void WirePlayerEvent(Player _) { Logger.Debug("Player loaded event called"); MelonCoroutines.Start(WireOnXpChangedDelayed()); } [IteratorStateMachine(typeof(d__6))] private static IEnumerator WireOnXpChangedDelayed() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__6(0); } private static 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(); 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; } } } } [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(); if ((Object)(object)_detector == (Object)null) { _detector = ((Component)this).gameObject.AddComponent(); } } 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_0102: Unknown result type (might be due to invalid IL or missing references) LandVehicle vehicle2 = vehicle; _logger.Debug($"Adding vehicle to pool: {vehicle2.GUID}"); DeliveryVehicle val = ((Component)vehicle2).GetComponent(); if ((Object)(object)val == (Object)null) { Guid gUID = vehicle2.GUID; val = new DeliveryVehicleBuilder().WithLandVehicle(vehicle2).WithGuid(gUID).Build(); } vehicle2.IsPlayerOwned = false; vehicle2.SetIsPlayerOwned((NetworkConnection)null, false); vehicle2.SetVisible(false); vehicle2.IsPhysicallySimulated = false; IEnumerable source = from lv in NetworkSingleton.Instance.PlayerOwnedVehicles.AsEnumerable() where lv.GUID.ToString() != vehicle2.GUID.ToString() select lv; NetworkSingleton.Instance.PlayerOwnedVehicles = source.ToList(); ((Component)vehicle2).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(); if ((Object)(object)val3 == (Object)null) { val3 = ((Component)this).gameObject.AddComponent(); } ((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(); 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(); 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.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(DeliveryShop))] internal static class CapacityText { private static readonly Logger Logger = new Logger("CapacityText"); private static ConditionalWeakTable _capacityTexts = new ConditionalWeakTable(); [HarmonyPatch("Initialize")] [HarmonyPostfix] private static void AddCapacityTextPostfix(DeliveryShop __instance) { Logger.Debug("Adding capacity text for " + ((Object)__instance).name); if (_capacityTexts.TryGetValue(__instance, out Text _)) { return; } Text deliveryTimeLabel = __instance.DeliveryTimeLabel; GameObject val = ((deliveryTimeLabel != null) ? ((Component)((Component)deliveryTimeLabel).transform.parent).gameObject : null); Logger.Debug($"Adding capacity text: {deliveryTimeLabel}, templatego: {val}"); if (val == null) { return; } GameObject val2 = Object.Instantiate(val); val2.transform.SetParent(val.transform.parent, false); val2.transform.SetSiblingIndex(val.transform.GetSiblingIndex()); Text component = ((Component)val2.transform.Find("Label")).GetComponent(); component.text = "Free vehicles"; Text component2 = ((Component)val2.transform.Find("Time")).GetComponent(); component2.text = "1/1"; _capacityTexts.Add(__instance, component2); List list = val.transform.parent.FindAllTransforms("Spacer"); if (list.Count > 0) { Transform val3 = list[list.Count - 1]; if ((Object)(object)val3 != (Object)null) { ((Component)val3).gameObject.SetActive(false); } } } [HarmonyPatch("FixedUpdate")] [HarmonyPostfix] private static void UpdateCapacityTextPostfix(DeliveryShop __instance) { if (__instance.IsOpen && ((App)(object)PlayerSingleton.Instance).isOpen && _capacityTexts.TryGetValue(__instance, out Text value)) { var (num, num2) = GetVehiclesForShop(__instance); value.text = $"{num}/{num2}"; } } private static (int available, int total) GetVehiclesForShop(DeliveryShop shop) { string matchingShopInterfaceName = shop.MatchingShopInterfaceName; PoolManager instance = PoolManager.Instance; int item = 1 + instance.Pool.Count; int num = 0; if (!(instance.BaseVehicleAllocationsForShop.TryGetValue(matchingShopInterfaceName, out var value) && value)) { num++; } int num2 = Math.Min(instance.Allocations.Count, instance.Pool.Count); int num3 = instance.Pool.Count - num2; num += num3; return (num, item); } } [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.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.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(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 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)PoolManager.Instance.Pool).FirstOrDefault((Func)((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(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.Instance.SendDelivery(val); } } if (data.DeliveryHistory != null) { DeliveryReceipt[] deliveryHistory = data.DeliveryHistory; foreach (DeliveryReceipt val2 in deliveryHistory) { NetworkSingleton.Instance._deliveryHistory.Add(val2); } } if (data.DisplayedDeliveryHistory != null) { DeliveryReceipt[] displayedDeliveryHistory = data.DisplayedDeliveryHistory; foreach (DeliveryReceipt val3 in displayedDeliveryHistory) { NetworkSingleton.Instance._displayedDeliveryHistory.Add(val3); } } } } public class PoolManager { private static readonly Logger Logger = new Logger("PoolManager"); public static PoolManager Instance { get; } = new PoolManager(); public HashSet Pool { get; } = new HashSet(); internal Dictionary Allocations { get; } = new Dictionary(); internal Dictionary BaseVehicleAllocationsForShop { get; } = new Dictionary(); 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)Pool).FirstOrDefault((Func)((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 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() == (Object)null) { return false; } __instance.Vehicle = ((Component)__instance).GetComponent(); __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 d__13 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public LandVehicle vehicle; public EVehicleColor color; public VehicleSave <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__13(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 _dtos = new List(); 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); } } internal void RemoveVehicle(DeliveryVehicle vehicle) { DeliveryVehicle vehicle2 = vehicle; _dtos.RemoveAll((VehicleSaveDto dto) => dto.Guid.ToString() == vehicle2.GUID.ToString()); } 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.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(d__13))] 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 d__13(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 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 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 <>9__3; internal bool b__2() { return message.Vehicles.All((VehiclePoolSyncResponse.VehicleData v) => (Object)(object)<>4__this.FindLandVehicleByObjectId(v.ObjectId) != (Object)null); } internal bool 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 <>9__3; internal bool b__2() { return (Object)(object)((IEnumerable)PoolManager.Instance.Pool).FirstOrDefault((Func)((DeliveryVehicle v) => v.GUID == message.VehicleGuid)) != (Object)null; } internal bool b__3(DeliveryVehicle v) { return v.GUID == message.VehicleGuid; } internal bool b__4(DeliveryVehicle v) { return v.GUID == message.VehicleGuid; } } [CompilerGenerated] private sealed class d__34 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Func predicate; public float initialDelay; public float finalDelay; public float timeout; private float 5__1; private float 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public 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; 5__1 = initialDelay; 5__2 = 0f; break; case 1: <>1__state = -1; 5__2 += 5__1; 5__1 = Mathf.Min(5__1 * 2f, finalDelay); break; } if (!predicate() && 5__2 < timeout) { <>2__current = (object)new WaitForSeconds(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((Action)OnVehicleAdded); _client.RegisterMessageHandler((Action)OnVehicleCreated); _client.RegisterMessageHandler((Action)OnPoolSyncRequest); _client.RegisterMessageHandler((Action)OnPoolSyncResponse); _client.RegisterMessageHandler((Action)OnVehicleAllocation); _client.RegisterMessageHandler((Action)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.<g__ProcessMessage|0>d))] IEnumerator ProcessMessage() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <>c__DisplayClass22_0.<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.<g__ProcessMessage|0>d))] IEnumerator ProcessMessage() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <>c__DisplayClass23_0.<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.<g__ProcessMessage|0>d))] IEnumerator ProcessMessage() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <>c__DisplayClass25_0.<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.<g__ProcessMessage|0>d))] IEnumerator ProcessMessage() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <>c__DisplayClass26_0.<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 members = _client.GetLobbyMembers(); MemberInfo host = ((IEnumerable)members).FirstOrDefault((Func)((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(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(d__34))] private static IEnumerator ExponentialBackoff(Func predicate, float initialDelay, float finalDelay, float timeout) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new 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 Vehicles { get; set; } = new List(); 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 DependenciesChecker { private static readonly Logger Logger = new Logger("DependenciesChecker"); private static readonly List Dependencies = new List(2) { new Dependency { Name = "S1API (Forked)", AssemblyName = "S1API", MinVersion = new SemVersion(3, 0, 1, "", ""), IsRequired = true }, new Dependency { Name = "SteamNetworkLib", AssemblyName = "SteamNetworkLib", MinVersion = new SemVersion(1, 2, 1, "", ""), IsRequired = false } }; private static bool IsPresent(Dependency dependency) { Dependency dependency2 = dependency; Assembly foundInDomain = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly assembly) => assembly.GetName().Name == dependency2.AssemblyName); if (foundInDomain == null) { return false; } MelonMod val = ((IEnumerable)MelonTypeBase.RegisteredMelons).FirstOrDefault((Func)((MelonMod m) => ((MelonBase)m).MelonAssembly.Assembly == foundInDomain)); if (val == null) { Logger.Debug(foundInDomain.GetName().Name + " wasn't found in RegisteredMelons, cannot verify version. Assuming present."); return true; } SemVersion semanticVersion = ((MelonBase)val).Info.SemanticVersion; if (semanticVersion == (SemVersion)null) { Logger.Debug($"{foundInDomain.GetName().Name}'s version {semanticVersion} is not SemVer. Assuming present."); return true; } return semanticVersion >= dependency2.MinVersion; } private static List GetMissing() { return Dependencies.Where((Dependency dependency) => !IsPresent(dependency)).ToList(); } public static void PrintMissing() { List missing = GetMissing(); if (!missing.Any()) { return; } foreach (Dependency item in missing) { if (item.IsRequired) { Logger.Error($"Critical:\nRequired dependency {item.Name} is missing or outdated (min version {item.MinVersion}). Mod will not function correctly without it."); } else { Logger.Warn($"Optional dependency {item.Name} is missing or outdated (min version {item.MinVersion})."); } } } } public record Dependency { public string Name { get; set; } public string AssemblyName { get; set; } public SemVersion MinVersion { get; set; } public bool IsRequired { get; set; } } public class IconLoader { private static Sprite _questIconSprite; public static Sprite QuestIconSprite => GetIcon(ref _questIconSprite, "MultiDelivery.assets.quest_icon.png"); 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; } } 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 AsEnumerable(this List list) { return list ?? new List(); } public static object ToNativeList(this List source) { return source ?? new List(); } } public static class Utils { [CompilerGenerated] private sealed class d__7 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Func condition; public float timeout; public Action onTimeout; public Action onFinish; private float 5__1; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__7(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; 5__1 = Time.time; break; case 1: <>1__state = -1; break; } if (!condition()) { if (!float.IsNaN(timeout) && Time.time - 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 d__6 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public IEnumerator routine; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public 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; 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 d__5 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public IEnumerator routine; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public 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 ((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(string objectName) where T : Object { try { T[] array = Resources.FindObjectsOfTypeAll(); 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 GetAllComponentsInChildrenRecursive(GameObject obj) where T : Component { List list = new List(); if ((Object)(object)obj == (Object)null) { return list; } T[] components = obj.GetComponents(); 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(((Component)child).gameObject)); } return list; } public static List FindAllTransforms(this Transform transform, string name) { List list = new List(); for (int i = 0; i < transform.childCount; i++) { Transform child = transform.GetChild(i); if (((Object)child).name == name) { list.Add(child); } } return list; } public static bool Is(object obj, out T? result) where T : class { if (obj is T val) { result = val; return true; } result = null; return false; } [IteratorStateMachine(typeof(d__5))] public static IEnumerator WaitForPlayer(IEnumerator routine) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__5(0) { routine = routine }; } [IteratorStateMachine(typeof(d__6))] public static IEnumerator WaitForNetwork(IEnumerator routine) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__6(0) { routine = routine }; } [IteratorStateMachine(typeof(d__7))] public static IEnumerator WaitForCondition(Func condition, float timeout = float.NaN, Action? onTimeout = null, Action? onFinish = null) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__7(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(this GameObject gameObject) where T : Component { T component = gameObject.GetComponent(); if ((Object)(object)component != (Object)null) { return component; } component = gameObject.AddComponent(); 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(); 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); } } } namespace MultiDelivery.GameConsole { public class RootCommand : BaseConsoleCommand { private readonly RootNode _rootNode; public override string CommandWord => "multidelivery"; public override string CommandDescription => "Root command for MultiDelivery mod. Use subcommands for specific actions. Output is presented in MelonLoader console window."; public override string ExampleUsage => "multidelivery help"; public RootCommand() { _rootNode = new RootNode(); } public override void ExecuteCommand(List args) { _rootNode.Execute(new CommandContext(((BaseConsoleCommand)this).CommandWord, args)); } } } namespace MultiDelivery.GameConsole.Core { public class CommandContext { private readonly Instance _logger; public IReadOnlyList Args { get; } public string Path { get; } public CommandContext(string path, IReadOnlyList args) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown Path = path; Args = args; _logger = new Instance("MultiDelivery.Console." + Path); } public CommandContext CreateChild(string childName, IReadOnlyList args) { return new CommandContext(Path + "." + childName, args); } public void Reply(string message) { _logger.Msg(message); } public void Error(string message) { _logger.Error(message); } } public abstract class CompositeCommand : ICommandNode { private readonly Dictionary _children = new Dictionary(); public abstract string Name { get; } public abstract string Description { get; } protected void Register(ICommandNode command) { _children[command.Name] = command; } public virtual void Execute(CommandContext context) { if (context.Args.Count == 0) { PrintHelp(context); return; } string text = context.Args[0]; if (!_children.TryGetValue(text, out ICommandNode value)) { context.Error("Unknown subcommand: " + text); return; } List args = context.Args.Skip(1).ToList(); CommandContext context2 = context.CreateChild(value.Name, args); value.Execute(context2); } protected void PrintHelp(CommandContext context) { context.Reply(Name + " commands:"); foreach (ICommandNode value in _children.Values) { context.Reply("- " + value.Name + ": " + value.Description); } } public IEnumerable GetChildren() { return _children.Values; } } public interface ICommandNode { string Name { get; } string Description { get; } void Execute(CommandContext context); } } namespace MultiDelivery.GameConsole.Commands { public class RootNode : CompositeCommand { public override string Name => "root"; public override string Description => "Root command node"; public RootNode() { Register(new HelpCommand(this)); Register(new QuestCommand()); Register(new PoolCommand()); } } } namespace MultiDelivery.GameConsole.Commands.Quest { public class QuestCommand : CompositeCommand { public override string Name => "quest"; public override string Description => "Quest-related commands."; public QuestCommand() { Register(new QuestForceCommand()); Register(new QuestStartCommand()); } } public class QuestForceCommand : ICommandNode { public string Name => "force"; public string Description => "Forces the quest to register regardless of Rank"; public void Execute(CommandContext context) { NPC val = NPC.Get(); 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(); context.Reply("Quest force executed."); } } } public class QuestStartCommand : ICommandNode { public string Name => "start"; public string Description => "Starts a quest."; public void Execute(CommandContext context) { DropoffQuestDialogue.OnAcceptQuest(); context.Reply("Quest started."); } } } namespace MultiDelivery.GameConsole.Commands.Pool { public class PoolAddCommand : ICommandNode { public string Name => "add"; public string Description => "Adds to the pool."; public void Execute(CommandContext context) { if (context.Args.Count == 0) { context.Error("Missing number."); return; } if (!int.TryParse(context.Args[0], out var result) || result < 1) { context.Error("Invalid number."); return; } for (int i = 0; i < result; i++) { CreatePoolVehicle(); } context.Reply($"Added {result} to pool."); } internal static void CreatePoolVehicle() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) LandVehicle newLandVehicle = NetworkSingleton.Instance.SpawnAndReturnVehicle("veeper", Vector3.zero, Quaternion.identity, false); DeliveryVehicle val = ((Component)newLandVehicle).GetComponent(); if ((Object)(object)val == (Object)null) { Guid gUID = newLandVehicle.GUID; val = new DeliveryVehicleBuilder().WithLandVehicle(newLandVehicle).WithGuid(gUID).Build(); } newLandVehicle.IsPlayerOwned = false; newLandVehicle.SetIsPlayerOwned((NetworkConnection)null, false); newLandVehicle.SetVisible(false); newLandVehicle.IsPhysicallySimulated = false; IEnumerable source = from lv in NetworkSingleton.Instance.PlayerOwnedVehicles.AsEnumerable() where lv.GUID.ToString() != newLandVehicle.GUID.ToString() select lv; NetworkSingleton.Instance.PlayerOwnedVehicles = source.ToList(); ((Component)newLandVehicle).transform.position = new Vector3(0f, -100f, 0f); PoolManager.Instance.AddToSaveData(val); PoolManager.Instance.AddToPool(val); } } public class PoolCommand : CompositeCommand { public override string Name => "pool"; public override string Description => "Pool management."; public PoolCommand() { Register(new PoolAddCommand()); Register(new PoolSetCommand()); Register(new PoolGetCommand()); } } public class PoolGetCommand : ICommandNode { public string Name => "get"; public string Description => "Gets the number of vehicles in the pool."; public void Execute(CommandContext context) { int count = PoolManager.Instance.Pool.Count; int count2 = PoolManager.Instance.Allocations.Count; context.Reply($"Pool has {count} vehicles in it, {count2} of which are allocated."); } } public class PoolSetCommand : ICommandNode { public string Name => "set"; public string Description => "Sets the pool value. Downsizing the pool is not networked."; public void Execute(CommandContext context) { if (context.Args.Count == 0) { context.Error("Missing number."); return; } if (!int.TryParse(context.Args[0], out var result) || result < 0) { context.Error("Invalid number."); return; } int num = result - PoolManager.Instance.Pool.Count; if (num > 0) { for (int i = 0; i < num; i++) { PoolAddCommand.CreatePoolVehicle(); } } else { for (int j = 0; j < -num; j++) { DeliveryVehicle vehicle = PoolManager.Instance.Pool.LastOrDefault(); if ((Object)(object)vehicle == (Object)null) { context.Error("Last pool vehicle not found. Downsizing the pool unavailable"); return; } PoolManager.Instance.Pool.Remove(vehicle); List list = (from x in PoolManager.Instance.Allocations where (Object)(object)x.Value == (Object)(object)vehicle select x.Key).ToList(); foreach (string item in list) { PoolManager.Instance.Allocations.Remove(item); } VehicleSave.Instance.RemoveVehicle(vehicle); } } context.Reply($"Pool set to {result}."); } } } namespace MultiDelivery.GameConsole.Commands.Help { public class HelpCommand : ICommandNode { private readonly CompositeCommand _root; public string Name => "help"; public string Description => "Displays available commands."; public HelpCommand(CompositeCommand root) { _root = root; } public void Execute(CommandContext context) { foreach (ICommandNode child in _root.GetChildren()) { context.Reply(child.Name + " - " + child.Description); } } } } 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(); return this; } public DeliveryVehicle Build() { DeliveryVehicle val = ((Component)_landVehicle).gameObject.AddComponent(); 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.Instance.GetVehiclePrefab(_vehicleCode); if ((Object)(object)vehiclePrefab == (Object)null) { throw new ArgumentException("Vehicle prefab with code '" + _vehicleCode + "' not found."); } GameObject val2 = Object.Instantiate(((Component)vehiclePrefab).gameObject, _parent, true); LandVehicle component = val2.GetComponent(); 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.Instance.AllVehicles.Add(component); ((NetworkBehaviour)NetworkSingleton.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) { } } }