Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of SimpleOptimize v0.1.0
SimpleOptimize.dll
Decompiled 2 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using SimpleOptimize.Core; using SimpleOptimize.Features; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("ClientNetworkTransform")] [assembly: IgnoresAccessChecksTo("com.olegknyazev.softmask")] [assembly: IgnoresAccessChecksTo("DissonanceVoip")] [assembly: IgnoresAccessChecksTo("DunGen")] [assembly: IgnoresAccessChecksTo("DunGen.Integration.ASPP")] [assembly: IgnoresAccessChecksTo("DunGen.Integration.UnityNav")] [assembly: IgnoresAccessChecksTo("EasyTextEffects")] [assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")] [assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")] [assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")] [assembly: IgnoresAccessChecksTo("Unity.Burst")] [assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")] [assembly: IgnoresAccessChecksTo("Unity.Collections")] [assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")] [assembly: IgnoresAccessChecksTo("Unity.Jobs")] [assembly: IgnoresAccessChecksTo("Unity.Mathematics")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")] [assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")] [assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Components")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")] [assembly: IgnoresAccessChecksTo("Unity.Services.QoS")] [assembly: IgnoresAccessChecksTo("Unity.Services.Relay")] [assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")] [assembly: IgnoresAccessChecksTo("Unity.Timeline")] [assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.XR.CoreUtils")] [assembly: IgnoresAccessChecksTo("Unity.XR.Management")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.ConformanceAutomation")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MetaQuestSupport")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MockRuntime")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.OculusQuestSupport")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.RuntimeDebugger")] [assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.SpatialTracking")] [assembly: IgnoresAccessChecksTo("UnityEngine.UI")] [assembly: IgnoresAccessChecksTo("UnityEngine.XR.LegacyInputHelpers")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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 SimpleOptimize { internal static class ChatUtil { internal static void Send(string message, bool broadcast = false) { try { HUDManager instance = HUDManager.Instance; if (!((Object)(object)instance == (Object)null)) { string text = "<color=#7dc47a>Optimize</color>: <color=#e8e86a>" + message + "</color>"; if (broadcast) { instance.AddTextMessageServerRpc(text); } else { instance.AddChatMessage(text, "", -1, false); } } } catch (Exception arg) { Plugin.Logger.LogError((object)$"[ChatUtil.Send] {arg}"); } } } internal static class CommandRouter { internal static bool IsSenderTheLocalPlayer(int playerId) { try { if (playerId < 0) { return true; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null) { return false; } return playerId == (int)val.playerClientId || playerId == (int)val.actualClientId; } catch (Exception arg) { Plugin.Logger.LogError((object)$"[CommandRouter.IsSenderTheLocalPlayer] {arg}"); return false; } } internal static bool Route(string raw) { try { if (string.IsNullOrWhiteSpace(raw)) { return false; } string[] array = raw.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); switch (array[0].ToLowerInvariant()) { case "optimize": case "opt": { string text2 = ((array.Length >= 2) ? array[1].ToLowerInvariant() : ""); string text3 = ((array.Length >= 3) ? array[2].ToLowerInvariant() : ""); switch (text2) { case "": { float num2 = Time.smoothDeltaTime * 1000f; ChatUtil.Send($"Sleeping {ItemSleeper.SleepingCount} item(s) · {RenderOptimizer.DeshadowedCount} de-shadowed · {RenderOptimizer.HiddenCount} culled · " + $"frame {num2:0.0}ms (~{((num2 > 0.01f) ? (1000f / num2) : 0f):0} FPS). " + "sleep=" + (ModConfig.SleepShipItems.Value ? "on" : "off") + " shadows=" + (ModConfig.DisableShipItemShadows.Value ? "on" : "off") + " snap=" + (ModConfig.SnapAboardItems.Value ? "on" : "off") + " cull=" + (ModConfig.CullDistantShipItems.Value ? "on" : "off") + " save-cap=" + ((ShipCapacityFix.CurrentCap > 0) ? ShipCapacityFix.CurrentCap.ToString() : "?")); return true; } case "sleep": if (text3 == "on" || text3 == "off") { ModConfig.SleepShipItems.Value = text3 == "on"; ChatUtil.Send("Item sleeping " + ((text3 == "on") ? "ON" : "OFF") + "."); } else { ChatUtil.Send("Usage: /opt sleep on|off"); } return true; case "snap": if (text3 == "on" || text3 == "off") { ModConfig.SnapAboardItems.Value = text3 == "on"; ChatUtil.Send("Instant settle aboard " + ((text3 == "on") ? "ON" : "OFF") + "."); } else { ChatUtil.Send("Usage: /opt snap on|off"); } return true; case "paint": case "spray": switch (text3) { case "": ChatUtil.Send(SprayColor.StatusFragment()); ChatUtil.Send("Usage: /opt spray <index> · /opt spray #RRGGBB · /opt spray off"); return true; case "off": case "vanilla": ModConfig.SprayColorMode.Value = "off"; ChatUtil.Send($"Spray colour back to vanilla (seeded) — {SuiteHandshake.PushSpray()} can(s) refreshed. New cans only; already-sprayed decals keep their colour."); return true; default: { if (int.TryParse(text3, out var result)) { int paletteSize = SprayColor.PaletteSize; if (paletteSize > 0 && (result < 0 || result >= paletteSize)) { ChatUtil.Send($"Palette index must be 0-{paletteSize - 1} ({paletteSize} colours on this prefab)."); return true; } ModConfig.SprayColorIndex.Value = result; ModConfig.SprayColorMode.Value = "palette"; ChatUtil.Send($"Spray colour: palette #{result} — {SuiteHandshake.PushSpray()} can(s) refreshed."); return true; } if (SprayColor.TryParseColor(text3, out var _)) { ModConfig.SprayColorHex.Value = (text3.StartsWith("#") ? text3 : ("#" + text3)); ModConfig.SprayColorMode.Value = "custom"; int num = SuiteHandshake.PushSpray(); ChatUtil.Send($"Spray colour: {ModConfig.SprayColorHex.Value} — {num} can(s) refreshed (tint via {SprayColor.LastTintProperty})."); if (SprayColor.LastTintProperty == "none") { ChatUtil.Send("⚠ That material exposes no known colour property — try a palette index instead."); } return true; } ChatUtil.Send("Usage: /opt spray <index> · /opt spray #RRGGBB · /opt spray off"); return true; } } case "cargo": case "dropship": switch (text3) { case "on": case "off": ModConfig.FastDropship.Value = text3 == "on"; ChatUtil.Send("Fast cargo dropship " + ((text3 == "on") ? "ON" : "OFF") + " — " + FastDropship.StatusFragment()); return true; case "wait": case "hold": { string text4 = ((array.Length >= 4) ? array[3].ToLowerInvariant() : ""); if (text4 == "on" || text4 == "off") { ModConfig.DropshipWaitForOpen.Value = text4 == "on"; ChatUtil.Send((text4 == "on") ? "Dropship will WAIT until opened before leaving." : "Dropship leaves on the timer even if unopened — vanilla takes the items AND the credits if you miss it."); } else { ChatUtil.Send("Wait-until-opened is " + (ModConfig.DropshipWaitForOpen.Value ? "ON" : "off") + ". Usage: /opt dropship wait on|off"); } return true; } case "speed": case "s": { string s = ((array.Length >= 4) ? array[3] : ""); if (int.TryParse(s, out var result2) && result2 >= 1 && result2 <= 4) { ModConfig.FastDropshipSpeed.Value = result2; ChatUtil.Send($"Dropship speed {result2} — {FastDropship.Describe(result2)}" + (ModConfig.FastDropship.Value ? "" : " (feature is OFF — /opt dropship on)")); } else { ChatUtil.Send($"Usage: /opt dropship speed {1}-{4}"); ChatUtil.Send(FastDropship.SpeedTable()); } return true; } default: ChatUtil.Send(FastDropship.StatusFragment() ?? ""); ChatUtil.Send("Speeds: " + FastDropship.SpeedTable() + " · /opt dropship speed <#> · /opt dropship on|off"); return true; } case "transit": if (text3 == "on" || text3 == "off") { ModConfig.FastCompanyTransit.Value = text3 == "on"; FastCompanyTransit.SyncAnimatorSpeed(); ChatUtil.Send("Fast transit " + ((text3 == "on") ? "ON" : "OFF") + " — " + SuiteHandshake.StatusFragment()); } else { ChatUtil.Send("Fast transit is " + (ModConfig.FastCompanyTransit.Value ? "ON" : "off") + " " + string.Format("(x{0:0.#}, {1}) · ", ModConfig.FastTransitSpeed.Value, ModConfig.FastTransitCompanyOnly.Value ? "Company only" : "all moons") + SuiteHandshake.StatusFragment() + " · latched: " + FastCompanyTransit.LatchState); } return true; case "cull": if (text3 == "on" || text3 == "off") { ModConfig.CullDistantShipItems.Value = text3 == "on"; ChatUtil.Send(string.Format("Distance culling {0} (beyond {1:0}m).", (text3 == "on") ? "ON" : "OFF", ModConfig.CullDistance.Value)); } else { ChatUtil.Send("Usage: /opt cull on|off"); } return true; case "yeet": if (text3 == "on" || text3 == "off") { ModConfig.FixCruiserYeet.Value = text3 == "on"; ChatUtil.Send("Cruiser yeet fix " + ((text3 == "on") ? "ON" : "OFF") + "."); } else { ChatUtil.Send("Cruiser yeet fix is " + (ModConfig.FixCruiserYeet.Value ? "ON" : "off") + ". Usage: /opt yeet on|off"); } return true; case "shadows": if (text3 == "on" || text3 == "off") { ModConfig.DisableShipItemShadows.Value = text3 == "on"; ChatUtil.Send("Shadow killing " + ((text3 == "on") ? "ON" : "OFF") + "."); } else { ChatUtil.Send("Usage: /opt shadows on|off"); } return true; default: ChatUtil.Send("Usage: /opt [sleep on|off | shadows on|off]"); return true; } } case "help": { string text = ((array.Length >= 2) ? array[1].ToLowerInvariant() : ""); if (text == "") { ChatUtil.Send("SimpleOptimize — /help optimize"); return true; } if (text != "optimize" && text != "opt" && text != "simpleoptimize") { return false; } ChatUtil.Send("Ship-item optimizer (your machine only): sleeping settled items + killing their shadows."); ChatUtil.Send("/opt = status (counts + FPS) · /opt sleep on|off · /opt shadows on|off — items wake instantly when grabbed"); ChatUtil.Send("Also fixes the vanilla 250-item save cap (items past it despawn on reload) — host-side, automatic."); return true; } default: return false; } } catch (Exception arg) { Plugin.Logger.LogError((object)$"[CommandRouter.Route] {arg}"); ChatUtil.Send("Command failed — see BepInEx log."); return true; } } } internal static class ModConfig { internal static ConfigEntry<string> CommandPrefix { get; private set; } internal static ConfigEntry<bool> SleepShipItems { get; private set; } internal static ConfigEntry<bool> DisableShipItemShadows { get; private set; } internal static ConfigEntry<int> ShipItemCapacity { get; private set; } internal static ConfigEntry<bool> FixSpiderWebSlow { get; private set; } internal static ConfigEntry<bool> FixStuckInteract { get; private set; } internal static ConfigEntry<bool> FixCruiserYeet { get; private set; } internal static ConfigEntry<bool> GrabBeforeStart { get; private set; } internal static ConfigEntry<bool> FixCadaverKillLag { get; private set; } internal static ConfigEntry<bool> MuteThrowRpcSpam { get; private set; } internal static ConfigEntry<bool> SnapAboardItems { get; private set; } internal static ConfigEntry<bool> CullDistantShipItems { get; private set; } internal static ConfigEntry<float> CullDistance { get; private set; } internal static ConfigEntry<string> SprayColorMode { get; private set; } internal static ConfigEntry<int> SprayColorIndex { get; private set; } internal static ConfigEntry<string> SprayColorHex { get; private set; } internal static ConfigEntry<bool> SprayAcceptHostColor { get; private set; } internal static ConfigEntry<bool> FastDropship { get; private set; } internal static ConfigEntry<float> FastDropshipSpeed { get; private set; } internal static ConfigEntry<bool> DropshipWaitForOpen { get; private set; } internal static ConfigEntry<bool> FastCompanyTransit { get; private set; } internal static ConfigEntry<bool> FastTransitCompanyOnly { get; private set; } internal static ConfigEntry<float> FastTransitSpeed { get; private set; } internal static void Init(ConfigFile file) { CommandPrefix = file.Bind<string>("General", "CommandPrefix", "/", "Prefix for chat commands (e.g. /opt)."); SleepShipItems = file.Bind<bool>("Optimizer", "SleepShipItems", true, "Skip per-frame Update() for items resting on the ship (not held, settled). They wake instantly when grabbed or moved. Toggle in-game: /opt sleep on|off."); DisableShipItemShadows = file.Bind<bool>("Optimizer", "DisableShipItemShadows", true, "Turn off shadow casting for items resting on the ship (restored when picked up or off the ship). Toggle in-game: /opt shadows on|off."); ShipItemCapacity = file.Bind<int>("Optimizer", "ShipItemCapacity", 9999, "Vanilla only SAVES the first 250 ship items (StartOfRound.maxShipItemCapacity) — the rest silently despawn on the next load. This raises the cap (0 = leave vanilla). Matters on the host, who writes the save."); FixSpiderWebSlow = file.Bind<bool>("Fixes", "FixSpiderWebSlow", true, "Fix the vanilla bug where a spider web broken/removed while you're in it leaves you permanently slowed (RemoveWeb uses the wrong cleanup factor and double-cleans via OnDestroy). Also self-heals already-corrupted hindered state."); FixStuckInteract = file.Bind<bool>("Fixes", "FixStuckInteract", true, "Fix the vanilla 'interact glitch' (can't interact or scroll-swap until relog): the throwingObject flag is only reset by a server RPC round trip; if that's lost it sticks forever. Watchdog clears it after 2s."); FixCruiserYeet = file.Bind<bool>("Fixes", "FixCruiserYeet", true, "Stop the cruiser being launched by physics depenetration when a player capsule ends up inside it (door-exit teleports, TZP-drunk movement). Overlapping players briefly ghost through the truck instead — vanilla's own seated-player collision toggle."); GrabBeforeStart = file.Bind<bool>("Fixes", "GrabBeforeStart", true, "Let you pick up items before the round starts (vanilla blocks grabbing until the lever is pulled). Local to your machine — the grab gate runs on the grabbing player's client."); SnapAboardItems = file.Bind<bool>("Optimizer", "SnapAboardItems", true, "Skip the fall animation for items dropped/moved aboard the ship or cruiser — they settle instantly and start sleeping the same frame (falling items can't sleep). Items dropped outside still fall normally. Toggle: /opt snap on|off."); CullDistantShipItems = file.Bind<bool>("Optimizer", "CullDistantShipItems", true, "Stop rendering aboard items entirely while you're far from them (draw calls are the big hoard cost while farming away from the ship); restored as you approach. Toggle: /opt cull on|off."); CullDistance = file.Bind<float>("Optimizer", "CullDistance", 45f, "Distance (meters) beyond which aboard items stop rendering."); MuteThrowRpcSpam = file.Bind<bool>("Fixes", "MuteThrowRpcSpam", true, "Mute the vanilla 'ThrowObjectClientRpc called for an object...' error spam from desynced client drops (thousands of log lines per session = real frame cost; vanilla already ignores the bad request)."); FixCadaverKillLag = file.Bind<bool>("Fixes", "FixCadaverKillLag", true, "Fix the FPS collapse when killing Cadaver growth plants: vanilla throws an exception per kill (logged twice with stack traces) plus ~5 debug log lines per kill. Swallows the exceptions and mutes exactly those log lines."); SprayColorMode = file.Bind<string>("Spray", "ColorMode", "off", "off | palette | custom. Vanilla rolls a spray can's colour from the map seed, so overriding it is LOCAL to your screen — vanilla friends still see the seeded colour for the same can and the same decals (nothing desyncs). Set with /opt spray."); SprayColorIndex = file.Bind<int>("Spray", "ColorIndex", 0, "Which of the game's own spray materials to use in palette mode (and which slot custom mode tints). Range depends on the prefab — /opt spray reports how many exist."); SprayColorHex = file.Bind<string>("Spray", "ColorHex", "#FF00FF", "Colour for custom mode, e.g. #FF00FF. The decals are HDRP DecalProjector materials, so the shader's colour property varies; every known name is tried and /opt spray reports which one took."); SprayAcceptHostColor = file.Bind<bool>("Spray", "AcceptHostColor", true, "As a client, adopt the host's spray colour so the lobby matches. Set false to keep your own. Has no effect when you ARE the host. Players without SimpleOptimize always see the vanilla seeded colour — the colour never travels in vanilla netcode."); FastDropship = file.Bind<bool>("Dropship", "FastDropship", true, "Speed up the CARGO dropship that delivers items bought at the terminal. Vanilla makes you wait 40s for it to arrive and 30s before it leaves. Host-authoritative, so only the host needs this — vanilla clients see the early arrival with no desync. Toggle: /opt dropship on|off."); FastDropshipSpeed = file.Bind<float>("Dropship", "Speed", 4f, "Speed level 1-4 for the dropship's countdown and landing animation. Set in-game with /opt dropship speed <#>. 1 = vanilla (40s arrive, 30s parked), 2 = 20s/15s, 3 = 13s/10s, 4 = 10s/8s."); DropshipWaitForOpen = file.Bind<bool>("Dropship", "WaitForOpen", true, "Hold the landed dropship until someone opens it, instead of leaving on vanilla's 30s timer. Vanilla takes your items AND your credits if it leaves unopened (\"Items missed! ... delivery fee cannot be refunded\"), and speeding the countdown up made that window too short to reach. Once opened, Speed applies and it leaves quickly. Toggle: /opt dropship wait on|off."); FastCompanyTransit = file.Bind<bool>("Transit", "FastCompanyTransit", false, "Speed up the PLAYER SHIP's landing and takeoff. OFF by default (Round 12) — Josh wanted the cargo dropship, not this; see [Dropship] FastDropship. ONLY engages when every player in the lobby is running SimpleOptimize (or you're solo) — the sequences are local on each machine, so a lone fast client would get control before everyone else. Toggle: /opt transit on|off."); FastTransitCompanyOnly = file.Bind<bool>("Transit", "CompanyOnly", true, "Restrict the speed-up to Gordion (The Company). Other moons keep vanilla pacing so normal runs feel untouched."); FastTransitSpeed = file.Bind<float>("Transit", "Speed", 3f, "Divisor for transit waits and matching animator speed. 3 turns the ~21s landing into ~7s. Higher values risk audio/animation popping, since some sounds run on their own timers."); } } [BepInPlugin("local.simpleoptimize", "SimpleOptimize", "0.1.0")] public class Plugin : BaseUnityPlugin { private readonly Harmony _harmony = new Harmony("local.simpleoptimize"); public static Plugin Instance { get; private set; } internal static ManualLogSource Logger { get; private set; } private void Awake() { Instance = this; Logger = ((BaseUnityPlugin)this).Logger; ModConfig.Init(((BaseUnityPlugin)this).Config); _harmony.PatchAll(); Logger.LogInfo((object)"SimpleOptimize v0.1.0 loaded. Ship-item optimizer armed."); } } public static class PluginInfo { public const string Guid = "local.simpleoptimize"; public const string Name = "SimpleOptimize"; public const string Version = "0.1.0"; } public static class MyPluginInfo { public const string PLUGIN_GUID = "SimpleOptimize"; public const string PLUGIN_NAME = "SimpleOptimize"; public const string PLUGIN_VERSION = "0.1.0"; } } namespace SimpleOptimize.Patches { [HarmonyPatch(typeof(HUDManager), "AddTextToChatOnServer")] internal static class ChatCommandPatch { [HarmonyPrefix] private static bool Prefix(string chatMessage, int playerId) { try { if (string.IsNullOrEmpty(chatMessage)) { return true; } if (!chatMessage.StartsWith(ModConfig.CommandPrefix.Value)) { return true; } if (!CommandRouter.IsSenderTheLocalPlayer(playerId)) { return true; } string raw = chatMessage.Substring(ModConfig.CommandPrefix.Value.Length).Trim(); bool flag = CommandRouter.Route(raw); return !flag; } catch (Exception arg) { Plugin.Logger.LogError((object)$"[ChatCommandPatch] {arg}"); return true; } } } [HarmonyPatch(typeof(ItemDropship), "Update")] internal static class FastDropshipUpdatePatch { [HarmonyPrefix] private static void Prefix(ItemDropship __instance, out float __state) { __state = (((Object)(object)__instance != (Object)null) ? __instance.shipTimer : 0f); } [HarmonyPostfix] private static void Postfix(ItemDropship __instance, float __state) { try { if ((Object)(object)__instance == (Object)null || !FastDropship.Enabled) { return; } FastDropship.SyncAnimator(__instance); NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton == (Object)null) && singleton.IsServer && !(__instance.shipTimer <= __state)) { if (FastDropship.ShouldHold(__instance)) { __instance.shipTimer = __state; } else { __instance.shipTimer += FastDropship.ExtraTime(); } } } catch (Exception arg) { Plugin.Logger.LogError((object)$"[FastDropshipUpdatePatch] {arg}"); } } } [HarmonyPatch] internal static class FastTransitTranspilerPatch { [HarmonyTargetMethods] private static IEnumerable<MethodBase> Targets() { return FastCompanyTransit.TargetMethods(); } [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { return FastCompanyTransit.Transpiler(instructions); } } [HarmonyPatch(typeof(StartOfRound), "Start")] internal static class FastTransitStartPatch { [HarmonyPostfix] private static void Postfix() { try { SuiteHandshake.Reset(); SuiteHandshake.Register(); FastCompanyTransit.SyncAnimatorSpeed(); } catch (Exception arg) { Plugin.Logger.LogError((object)$"[FastTransitStartPatch] {arg}"); } } } [HarmonyPatch(typeof(RoundManager), "FinishGeneratingNewLevelClientRpc")] internal static class FastTransitLandingLatch { [HarmonyPostfix] private static void Postfix() { FastCompanyTransit.Latch("landing"); } } [HarmonyPatch(typeof(StartOfRound), "EndOfGameClientRpc")] internal static class FastTransitDepartureLatch { [HarmonyPostfix] private static void Postfix() { FastCompanyTransit.Latch("departure"); } } [HarmonyPatch(typeof(StartOfRound), "SetShipReadyToLand")] internal static class FastTransitLandPatch { [HarmonyPostfix] private static void Postfix() { FastCompanyTransit.SyncAnimatorSpeed(); } } [HarmonyPatch(typeof(StartOfRound), "ShipLeave")] internal static class FastTransitLeavePatch { [HarmonyPrefix] private static void Prefix() { FastCompanyTransit.SyncAnimatorSpeed(); } } [HarmonyPatch(typeof(SprayPaintItem), "Start")] internal static class SprayColorStartPatch { [HarmonyPostfix] private static void Postfix(SprayPaintItem __instance) { try { SprayColor.Apply(__instance); } catch (Exception arg) { Plugin.Logger.LogError((object)$"[SprayColorStartPatch] {arg}"); } } } [HarmonyPatch(typeof(StartOfRound), "Start")] internal static class StartupPatch { [HarmonyPostfix] private static void Postfix() { try { RenderOptimizer.EnsureRunning(); ((MonoBehaviour)CoroutineRunner.Instance).StartCoroutine(Line()); } catch (Exception arg) { Plugin.Logger.LogError((object)$"[StartupPatch] {arg}"); } } private static IEnumerator Line() { yield return (object)new WaitForSeconds(3f); SuiteAnnounce.MaybeAnnounce("local.simpleoptimize"); } } } namespace SimpleOptimize.Features { internal static class CadaverKillFix { [HarmonyPatch(typeof(CadaverGrowthAI), "RemoveWeedFromTile")] private static class RemoveWeedPatch { [HarmonyFinalizer] private static Exception Finalizer(Exception __exception) { return Swallow(__exception); } } [HarmonyPatch(typeof(CadaverGrowthAI), "DestroyPlantAtPosition")] private static class DestroyPlantPatch { [HarmonyFinalizer] private static Exception Finalizer(Exception __exception) { return Swallow(__exception); } } [HarmonyPatch(typeof(Debug), "Log", new Type[] { typeof(object) })] private static class LogSpamPatch { private static readonly string[] SpamPrefixes = new string[6] { "Got nearby cadaver plant", "Checking nearby cadaver plant", "Destroying: planttype", "planttype:", "moldPositions[", "setting to -1:" }; [HarmonyPrefix] private static bool Prefix(object message) { try { if (!ModConfig.FixCadaverKillLag.Value || !(message is string text)) { return true; } string[] spamPrefixes = SpamPrefixes; foreach (string value in spamPrefixes) { if (text.StartsWith(value, StringComparison.Ordinal)) { return false; } } if (text.Contains("cadaver plants found at pos")) { return false; } return true; } catch { return true; } } } internal static int Swallowed; private static Exception Swallow(Exception __exception) { if (__exception == null || !ModConfig.FixCadaverKillLag.Value) { return __exception; } Swallowed++; if (Swallowed % 100 == 1) { Plugin.Logger.LogWarning((object)$"[CadaverKillFix] Swallowed vanilla plant-kill exception #{Swallowed}: {__exception.GetType().Name}"); } return null; } } [HarmonyPatch(typeof(VehicleController), "Update")] internal static class CruiserYeetFix { private const float TeleportJumpMeters = 3f; private const float TeleportGraceSeconds = 1.5f; private const float DrunkThreshold = 0.2f; private const float ReleaseMargin = 1.5f; private static readonly Dictionary<ulong, Vector3> _lastRelPos = new Dictionary<ulong, Vector3>(); private static readonly Dictionary<ulong, float> _graceUntil = new Dictionary<ulong, float>(); private static readonly HashSet<ulong> _wasDeepInside = new HashSet<ulong>(); private static readonly HashSet<ulong> _ghosted = new HashSet<ulong>(); [HarmonyPostfix] private static void Postfix(VehicleController __instance) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_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_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: 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_014c: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) try { StartOfRound instance = StartOfRound.Instance; if (instance?.allPlayerScripts == null || (Object)(object)__instance.boundsCollider == (Object)null) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; Bounds bounds = ((Collider)__instance.boundsCollider).bounds; Bounds val = bounds; ((Bounds)(ref val)).Expand(1.5f); Transform transform = ((Component)__instance).transform; PlayerControllerB[] allPlayerScripts = instance.allPlayerScripts; foreach (PlayerControllerB val2 in allPlayerScripts) { if ((Object)(object)val2 == (Object)null) { continue; } ulong playerClientId = val2.playerClientId; if (!val2.isPlayerControlled) { Release(__instance, val2, playerClientId); _wasDeepInside.Remove(playerClientId); continue; } Transform val3 = (((Object)(object)val2.overridePhysicsParent != (Object)null) ? val2.overridePhysicsParent : val2.physicsParent); bool flag = val2.inVehicleAnimation || ((Object)(object)val3 != (Object)null && ((Object)(object)val3 == (Object)(object)transform || val3.IsChildOf(transform))); Vector3 val4 = transform.InverseTransformPoint(((Component)val2).transform.position); if (_lastRelPos.TryGetValue(playerClientId, out var value)) { Vector3 val5 = val4 - value; if (((Vector3)(ref val5)).sqrMagnitude > 9f) { _graceUntil[playerClientId] = realtimeSinceStartup + 1.5f; } } _lastRelPos[playerClientId] = val4; Vector3 position = ((Component)val2).transform.position; bool flag2 = ((Bounds)(ref bounds)).Contains(position + Vector3.up * 0.1f) && ((Bounds)(ref bounds)).Contains(position + Vector3.up); if (!ModConfig.FixCruiserYeet.Value || flag) { Release(__instance, val2, playerClientId); _wasDeepInside.Remove(playerClientId); continue; } if (_ghosted.Contains(playerClientId)) { if (!((Bounds)(ref val)).Contains(position + Vector3.up)) { Release(__instance, val2, playerClientId); Plugin.Logger.LogInfo((object)("[CruiserYeetFix] " + val2.playerUsername + " clear of cruiser — collision restored.")); } continue; } float value2; bool flag3 = val2.drunkness > 0.2f || (_graceUntil.TryGetValue(playerClientId, out value2) && realtimeSinceStartup < value2); if (flag2 && !_wasDeepInside.Contains(playerClientId) && flag3) { __instance.SetVehicleCollisionForPlayer(false, val2); _ghosted.Add(playerClientId); Plugin.Logger.LogWarning((object)("[CruiserYeetFix] " + val2.playerUsername + " arrived inside cruiser bounds (" + ((val2.drunkness > 0.2f) ? "TZP" : "teleport") + ") — ghosted to prevent yeet.")); } if (flag2) { _wasDeepInside.Add(playerClientId); } else { _wasDeepInside.Remove(playerClientId); } } } catch (Exception arg) { Plugin.Logger.LogError((object)$"[CruiserYeetFix] {arg}"); } } private static void Release(VehicleController v, PlayerControllerB p, ulong id) { if (_ghosted.Remove(id)) { v.SetVehicleCollisionForPlayer(true, p); } } } [HarmonyPatch(typeof(StartOfRound), "Start")] internal static class EarlyGrabFix { [HarmonyPostfix] private static void Postfix(StartOfRound __instance) { try { if (!ModConfig.GrabBeforeStart.Value || __instance.allItemsList?.itemsList == null) { return; } int num = 0; foreach (Item items in __instance.allItemsList.itemsList) { if (!((Object)(object)items == (Object)null) && !items.canBeGrabbedBeforeGameStart) { items.canBeGrabbedBeforeGameStart = true; num++; } } if (num > 0) { Plugin.Logger.LogInfo((object)$"[EarlyGrabFix] {num} item type(s) made grabbable before game start."); } } catch (Exception arg) { Plugin.Logger.LogError((object)$"[EarlyGrabFix] {arg}"); } } } internal static class FastCompanyTransit { private static readonly string[] TargetCoroutines = new string[4] { "openingDoorsSequence", "EndOfGame", "unloadSceneForAllPlayers", "TravelToLevelEffects" }; private static bool _latchedFast; private static string _latchedWhy = "not latched"; internal static bool LastAppliedFast { get; private set; } internal static string LatchState => (_latchedFast ? "fast" : "normal") + " (" + _latchedWhy + ")"; internal static void Latch(string sequence) { try { string text = StartOfRound.Instance?.currentLevel?.PlanetName ?? "?"; _latchedFast = Active(); _latchedWhy = sequence + " @ " + text; Plugin.Logger.LogInfo((object)("[FastCompanyTransit] latched " + (_latchedFast ? "FAST" : "normal") + " for " + sequence + " on '" + text + "' " + $"(handshake fast={SuiteHandshake.AllPlayersHaveIt}).")); SyncAnimatorSpeed(); } catch (Exception arg) { Plugin.Logger.LogError((object)$"[FastCompanyTransit.Latch] {arg}"); _latchedFast = false; } } internal static bool Active() { try { if (!ModConfig.FastCompanyTransit.Value) { return false; } if (!SuiteHandshake.AllPlayersHaveIt) { return false; } if (!ModConfig.FastTransitCompanyOnly.Value) { return true; } SelectableLevel val = StartOfRound.Instance?.currentLevel; if ((Object)(object)val == (Object)null) { return false; } return val.PlanetName != null && val.PlanetName.Contains("Gordion"); } catch (Exception arg) { Plugin.Logger.LogError((object)$"[FastCompanyTransit.Active] {arg}"); return false; } } internal static float ScaleWait(float seconds) { try { if (!_latchedFast) { return seconds; } float num = Mathf.Max(1f, ModConfig.FastTransitSpeed.Value); return seconds / num; } catch { return seconds; } } internal static void SyncAnimatorSpeed() { try { Animator val = StartOfRound.Instance?.shipAnimator; if (!((Object)(object)val == (Object)null)) { bool latchedFast = _latchedFast; float num = (latchedFast ? Mathf.Max(1f, ModConfig.FastTransitSpeed.Value) : 1f); if (!Mathf.Approximately(val.speed, num)) { val.speed = num; } LastAppliedFast = latchedFast; } } catch (Exception arg) { Plugin.Logger.LogError((object)$"[FastCompanyTransit.SyncAnimatorSpeed] {arg}"); } } internal static IEnumerable<MethodBase> TargetMethods() { List<MethodBase> list = new List<MethodBase>(); string[] targetCoroutines = TargetCoroutines; foreach (string fragment in targetCoroutines) { try { Type type = AccessTools.FirstInner(typeof(StartOfRound), (Func<Type, bool>)((Type t) => t.Name.Contains(fragment))); if (type == null) { Plugin.Logger.LogWarning((object)("[FastCompanyTransit] coroutine '" + fragment + "' not found — skipped.")); continue; } MethodInfo methodInfo = AccessTools.Method(type, "MoveNext", (Type[])null, (Type[])null); if (methodInfo == null) { Plugin.Logger.LogWarning((object)("[FastCompanyTransit] '" + fragment + "' has no MoveNext — skipped.")); } else { list.Add(methodInfo); } } catch (Exception arg) { Plugin.Logger.LogError((object)$"[FastCompanyTransit.TargetMethods:{fragment}] {arg}"); } } return list; } internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { ConstructorInfo ctor = AccessTools.Constructor(typeof(WaitForSeconds), new Type[1] { typeof(float) }, false); MethodInfo scale = AccessTools.Method(typeof(FastCompanyTransit), "ScaleWait", (Type[])null, (Type[])null); int hits = 0; foreach (CodeInstruction ins in instructions) { if (ctor != null && ins.opcode == OpCodes.Newobj && ins.operand as ConstructorInfo == ctor) { hits++; yield return new CodeInstruction(OpCodes.Call, (object)scale); } yield return ins; } Plugin.Logger.LogInfo((object)$"[FastCompanyTransit] scaled {hits} WaitForSeconds call(s)."); } } internal static class FastDropship { private const float VanillaArrive = 40f; private const float VanillaParked = 30f; internal const int MinSpeed = 1; internal const int MaxSpeed = 4; internal static float LastMultiplier { get; private set; } = 1f; internal static bool Enabled { get { if (ModConfig.FastDropship != null) { return ModConfig.FastDropship.Value; } return false; } } internal static float Multiplier => Mathf.Max(1f, ModConfig.FastDropshipSpeed.Value); internal static bool ShouldHold(ItemDropship ship) { try { if ((Object)(object)ship == (Object)null || !ModConfig.DropshipWaitForOpen.Value) { return false; } if (ship.deliveringVehicle) { return false; } return ship.shipLanded && !ship.shipDoorsOpened; } catch { return false; } } internal static float ExtraTime() { float num = (LastMultiplier = Multiplier); return (num - 1f) * Time.deltaTime; } internal static void SyncAnimator(ItemDropship ship) { try { Animator val = ship?.shipAnimator; if (!((Object)(object)val == (Object)null)) { float num = (Enabled ? Multiplier : 1f); if (!Mathf.Approximately(val.speed, num)) { val.speed = num; } } } catch (Exception arg) { Plugin.Logger.LogError((object)$"[FastDropship.SyncAnimator] {arg}"); } } internal static string Describe(float m) { m = Mathf.Max(1f, m); string text = (ModConfig.DropshipWaitForOpen.Value ? ", waits until opened" : ""); if (!(m <= 1f)) { return $"arrive ~{40f / m:0}s{text}, then leaves in ~{30f / m:0}s"; } return "vanilla (40s arrive" + ((text.Length > 0) ? text : ", 30s parked") + ")"; } internal static string SpeedTable() { List<string> list = new List<string>(); for (int i = 1; i <= 4; i++) { list.Add(string.Format("{0}={1}", i, (i <= 1) ? "vanilla" : $"{40f / (float)i:0}s/{30f / (float)i:0}s")); } return string.Join(" · ", list); } internal static string StatusFragment() { if (!Enabled) { return "dropship: off (vanilla 40s arrive, 30s parked)"; } float multiplier = Multiplier; return $"dropship: speed {multiplier:0.#} — {Describe(multiplier)}"; } } [HarmonyPatch(typeof(SandSpiderAI), "RemoveWeb")] internal static class WebSlowFix { [HarmonyPrefix] private static void Prefix(SandSpiderAI __instance, int trapID) { try { if (!ModConfig.FixSpiderWebSlow.Value || __instance.webTraps == null || trapID < 0 || trapID >= __instance.webTraps.Count) { return; } SandSpiderWebTrap val = __instance.webTraps[trapID]; PlayerControllerB val2 = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null) && val.hinderingLocalPlayer) { val.hinderingLocalPlayer = false; val2.isMovementHindered = Mathf.Max(0, val2.isMovementHindered - 1); val2.hinderedMultiplier *= 0.4f; if ((Object)(object)val.currentTrappedPlayer == (Object)(object)val2) { val.currentTrappedPlayer = null; } if ((Object)(object)val.webAudio != (Object)null) { val.webAudio.Stop(); } Plugin.Logger.LogInfo((object)"[HighQuotaFixes] Cleaned up removed web trapping the local player."); } } catch (Exception arg) { Plugin.Logger.LogError((object)$"[WebSlowFix] {arg}"); } } } [HarmonyPatch(typeof(Debug), "LogError", new Type[] { typeof(object) })] internal static class RpcErrorDespam { [HarmonyPrefix] private static bool Prefix(object message) { try { if (!ModConfig.MuteThrowRpcSpam.Value || !(message is string text)) { return true; } return !text.StartsWith("ThrowObjectClientRpc called for an object", StringComparison.Ordinal); } catch { return true; } } } [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] internal static class StuckStateWatchdog { private const float ThrowStuckSeconds = 2f; private static float _throwingSince; [HarmonyPostfix] private static void Postfix(PlayerControllerB __instance) { try { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null || (Object)(object)__instance != (Object)(object)val) { return; } if (ModConfig.FixStuckInteract.Value) { if (!val.throwingObject) { _throwingSince = 0f; } else { float realtimeSinceStartup = Time.realtimeSinceStartup; if (_throwingSince == 0f) { _throwingSince = realtimeSinceStartup; } else if (realtimeSinceStartup - _throwingSince > 2f) { val.throwingObject = false; _throwingSince = 0f; Plugin.Logger.LogWarning((object)$"[HighQuotaFixes] throwingObject stuck >{2f}s — cleared (interact glitch)."); } } } if (ModConfig.FixSpiderWebSlow.Value) { if (val.isMovementHindered < 0) { Plugin.Logger.LogWarning((object)$"[HighQuotaFixes] isMovementHindered was {val.isMovementHindered} — reset to 0."); val.isMovementHindered = 0; } if (val.isMovementHindered == 0 && val.hinderedMultiplier != 1f) { Plugin.Logger.LogWarning((object)$"[HighQuotaFixes] hinderedMultiplier drifted to {val.hinderedMultiplier:0.###} with nothing hindering — reset to 1."); val.hinderedMultiplier = 1f; } } } catch (Exception arg) { Plugin.Logger.LogError((object)$"[StuckStateWatchdog] {arg}"); } } } [HarmonyPatch(typeof(GrabbableObject), "Update")] internal static class ItemSleeper { private static int _sleptThisFrame; private static int _sleptLastFrame; private static int _frame; private static Transform _vehicleRoot; private static float _nextVehicleRefresh; private static int _dropSoundFrame; private static int _dropSoundsThisFrame; internal static int SleepingCount => _sleptLastFrame; [HarmonyPrefix] private static bool Prefix(GrabbableObject __instance) { //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_011d: 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) try { if (!ModConfig.SleepShipItems.Value) { return true; } if (__instance.isHeld || __instance.isPocketed || __instance.isBeingUsed) { return true; } bool flag = __instance.isInShipRoom || __instance.isInElevator; if (!flag) { float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup >= _nextVehicleRefresh) { _nextVehicleRefresh = realtimeSinceStartup + 5f; VehicleController val = Object.FindObjectOfType<VehicleController>(); _vehicleRoot = (((Object)(object)val != (Object)null) ? ((Component)val).transform : null); } flag = (Object)(object)_vehicleRoot != (Object)null && ((Component)__instance).transform.IsChildOf(_vehicleRoot); } if (!__instance.reachedFloorTarget || !__instance.hasHitGround) { if (!flag || !ModConfig.SnapAboardItems.Value) { return true; } ((Component)__instance).transform.localPosition = __instance.targetFloorPosition; if ((Object)(object)__instance.itemProperties != (Object)null) { ((Component)__instance).transform.rotation = Quaternion.Euler(__instance.itemProperties.restingRotation.x, (__instance.floorYRot == -1) ? ((Component)__instance).transform.eulerAngles.y : ((float)__instance.floorYRot), __instance.itemProperties.restingRotation.z); } __instance.reachedFloorTarget = true; __instance.hasHitGround = true; __instance.fallTime = 1f; int frameCount = Time.frameCount; if (frameCount != _dropSoundFrame) { _dropSoundFrame = frameCount; _dropSoundsThisFrame = 0; } if (_dropSoundsThisFrame < 3) { _dropSoundsThisFrame++; __instance.PlayDropSFX(); __instance.OnHitGround(); } } else if (!flag) { return true; } int frameCount2 = Time.frameCount; if (frameCount2 != _frame) { _sleptLastFrame = _sleptThisFrame; _sleptThisFrame = 0; _frame = frameCount2; } _sleptThisFrame++; return false; } catch (Exception arg) { Plugin.Logger.LogError((object)$"[ItemSleeper] {arg}"); return true; } } } internal static class RenderOptimizer { private const float SweepInterval = 2f; private static bool _running; private static readonly Dictionary<Renderer, ShadowCastingMode> _originals = new Dictionary<Renderer, ShadowCastingMode>(); private static readonly Dictionary<GrabbableObject, Renderer[]> _itemRenderers = new Dictionary<GrabbableObject, Renderer[]>(); private static readonly HashSet<Renderer> _hidden = new HashSet<Renderer>(); internal static int DeshadowedCount => _originals.Count; internal static int HiddenCount => _hidden.Count; internal static void EnsureRunning() { if (!_running) { _running = true; ((MonoBehaviour)CoroutineRunner.Instance).StartCoroutine(SweepLoop()); } } internal static void SweepNow() { try { Sweep(); } catch (Exception arg) { Plugin.Logger.LogError((object)$"[RenderOptimizer.SweepNow] {arg}"); } } private static IEnumerator SweepLoop() { WaitForSeconds wait = new WaitForSeconds(2f); while (true) { yield return wait; try { Sweep(); } catch (Exception arg) { Plugin.Logger.LogError((object)$"[RenderOptimizer] {arg}"); } } } private static void Sweep() { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) bool value = ModConfig.DisableShipItemShadows.Value; bool flag = ModConfig.CullDistantShipItems.Value; if (!value && !flag) { RestoreAll(); return; } float num = ModConfig.CullDistance.Value * ModConfig.CullDistance.Value; object obj; if (!((Object)(object)StartOfRound.Instance?.audioListener != (Object)null)) { GameNetworkManager instance = GameNetworkManager.Instance; if (instance == null) { obj = null; } else { PlayerControllerB localPlayerController = instance.localPlayerController; obj = ((localPlayerController != null) ? ((Component)localPlayerController).transform : null); } } else { obj = ((Component)StartOfRound.Instance.audioListener).transform; } Transform val = (Transform)obj; Vector3 val2 = (((Object)(object)val != (Object)null) ? val.position : Vector3.zero); if ((Object)(object)val == (Object)null) { flag = false; } VehicleController val3 = Object.FindObjectOfType<VehicleController>(); Transform val4 = (((Object)(object)val3 != (Object)null) ? ((Component)val3).transform : null); HashSet<Renderer> hashSet = new HashSet<Renderer>(); GrabbableObject[] array = Object.FindObjectsByType<GrabbableObject>((FindObjectsSortMode)0); GrabbableObject[] array2 = array; foreach (GrabbableObject val5 in array2) { if ((Object)(object)val5 == (Object)null || val5.isHeld || val5.isPocketed || (!val5.isInShipRoom && !val5.isInElevator && (!((Object)(object)val4 != (Object)null) || !((Component)val5).transform.IsChildOf(val4)))) { continue; } if (!_itemRenderers.TryGetValue(val5, out var value2)) { value2 = (_itemRenderers[val5] = ((Component)val5).GetComponentsInChildren<Renderer>()); } int num2; if (flag) { Vector3 val6 = ((Component)val5).transform.position - val2; num2 = ((((Vector3)(ref val6)).sqrMagnitude > num) ? 1 : 0); } else { num2 = 0; } bool flag2 = (byte)num2 != 0; Renderer[] array3 = value2; foreach (Renderer val7 in array3) { if ((Object)(object)val7 == (Object)null) { continue; } if (value) { hashSet.Add(val7); if (!_originals.ContainsKey(val7) && (int)val7.shadowCastingMode != 0) { _originals[val7] = val7.shadowCastingMode; val7.shadowCastingMode = (ShadowCastingMode)0; } } if (flag2 && val7.enabled) { val7.enabled = false; _hidden.Add(val7); } else if (!flag2 && _hidden.Remove(val7)) { val7.enabled = true; } } } if (_itemRenderers.Count > 0) { List<GrabbableObject> list = new List<GrabbableObject>(); foreach (KeyValuePair<GrabbableObject, Renderer[]> itemRenderer in _itemRenderers) { if ((Object)(object)itemRenderer.Key == (Object)null) { list.Add(itemRenderer.Key); } } foreach (GrabbableObject item in list) { _itemRenderers.Remove(item); } } List<Renderer> list2 = new List<Renderer>(); foreach (KeyValuePair<Renderer, ShadowCastingMode> original in _originals) { if ((Object)(object)original.Key == (Object)null || !hashSet.Contains(original.Key)) { list2.Add(original.Key); } } foreach (Renderer item2 in list2) { if ((Object)(object)item2 != (Object)null) { item2.shadowCastingMode = _originals[item2]; } _originals.Remove(item2); } if ((flag || _hidden.Count <= 0) && _hidden.Count <= 0) { return; } _hidden.RemoveWhere((Renderer r) => (Object)(object)r == (Object)null); if (flag) { return; } foreach (Renderer item3 in _hidden) { item3.enabled = true; } _hidden.Clear(); } private static void RestoreAll() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (_originals.Count > 0) { foreach (KeyValuePair<Renderer, ShadowCastingMode> original in _originals) { if ((Object)(object)original.Key != (Object)null) { original.Key.shadowCastingMode = original.Value; } } _originals.Clear(); } if (_hidden.Count <= 0) { return; } foreach (Renderer item in _hidden) { if ((Object)(object)item != (Object)null) { item.enabled = true; } } _hidden.Clear(); } } [HarmonyPatch(typeof(StartOfRound), "Awake")] internal static class ShipCapacityFix { internal static int CurrentCap = -1; [HarmonyPostfix] private static void Postfix(StartOfRound __instance) { try { int value = ModConfig.ShipItemCapacity.Value; if (value > 0 && __instance.maxShipItemCapacity < value) { Plugin.Logger.LogInfo((object)$"[ShipCapacityFix] maxShipItemCapacity {__instance.maxShipItemCapacity} -> {value}"); __instance.maxShipItemCapacity = value; } CurrentCap = __instance.maxShipItemCapacity; } catch (Exception arg) { Plugin.Logger.LogError((object)$"[ShipCapacityFix] {arg}"); } } } internal static class SprayColor { internal enum Mode { Off, Palette, Custom } private static readonly string[] TintProperties = new string[6] { "_BaseColor", "_Color", "_UnlitColor", "_EmissiveColor", "_DecalColor", "_TintColor" }; internal static int PaletteSize { get; private set; } = -1; internal static string LastTintProperty { get; private set; } = "?"; internal static Mode CurrentMode { get { string text = ModConfig.SprayColorMode.Value?.ToLowerInvariant(); if (text == "palette") { return Mode.Palette; } if (text == "custom") { return Mode.Custom; } return Mode.Off; } } private static string Tint(Material mat, Color c) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) string text = null; string[] tintProperties = TintProperties; foreach (string text2 in tintProperties) { if (!((Object)(object)mat == (Object)null) && mat.HasProperty(text2)) { mat.SetColor(text2, c); if (text == null) { text = text2; } } } return text; } internal static bool TryParseColor(string s, out Color c) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) c = Color.white; if (string.IsNullOrWhiteSpace(s)) { return false; } string text = s.Trim(); if (!text.StartsWith("#")) { text = "#" + text; } return ColorUtility.TryParseHtmlString(text, ref c); } internal static void Apply(SprayPaintItem item) { //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown //IL_00e0: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)item == (Object)null || item.isWeedKillerSprayBottle) { return; } Material[] sprayCanMats = item.sprayCanMats; if (sprayCanMats == null || sprayCanMats.Length == 0) { return; } PaletteSize = sprayCanMats.Length; Mode currentMode = CurrentMode; if (currentMode == Mode.Off) { return; } int num = Mathf.Clamp(ModConfig.SprayColorIndex.Value, 0, sprayCanMats.Length - 1); if (currentMode == Mode.Custom && TryParseColor(ModConfig.SprayColorHex.Value, out var c)) { Material[] array = (Material[])sprayCanMats.Clone(); Material val = new Material(array[num]); LastTintProperty = Tint(val, c) ?? "none"; array[num] = val; item.sprayCanMats = array; if (item.particleMats != null && num < item.particleMats.Length) { Material[] array2 = (Material[])item.particleMats.Clone(); Material val2 = new Material(array2[num]); Tint(val2, c); array2[num] = val2; item.particleMats = array2; } } item.sprayCanMatsIndex = num; SetParticleMaterials(item, num); } catch (Exception arg) { Plugin.Logger.LogError((object)$"[SprayColor.Apply] {arg}"); } } private static void SetParticleMaterials(SprayPaintItem item, int idx) { try { if (item.particleMats != null && idx < item.particleMats.Length) { Material material = item.particleMats[idx]; Renderer val = (((Object)(object)item.sprayParticle != (Object)null) ? ((Component)item.sprayParticle).GetComponent<Renderer>() : null); if ((Object)(object)val != (Object)null) { val.material = material; } Renderer val2 = (((Object)(object)item.sprayCanNeedsShakingParticle != (Object)null) ? ((Component)item.sprayCanNeedsShakingParticle).GetComponent<Renderer>() : null); if ((Object)(object)val2 != (Object)null) { val2.material = material; } } } catch (Exception arg) { Plugin.Logger.LogError((object)$"[SprayColor.SetParticleMaterials] {arg}"); } } internal static int ReapplyAll() { int num = 0; SprayPaintItem[] array = Object.FindObjectsByType<SprayPaintItem>((FindObjectsSortMode)0); foreach (SprayPaintItem item in array) { Apply(item); num++; } return num; } internal static string StatusFragment() { string text = ((PaletteSize > 0) ? $"{PaletteSize} colours (0-{PaletteSize - 1})" : "palette unknown until a can spawns"); return CurrentMode switch { Mode.Palette => $"spray: palette #{ModConfig.SprayColorIndex.Value} · {text}", Mode.Custom => "spray: custom " + ModConfig.SprayColorHex.Value + " (via " + LastTintProperty + ") · " + text, _ => "spray: vanilla (seeded per save) · " + text, }; } } [HarmonyPatch(typeof(PlayerControllerB), "TeleportPlayer")] internal static class TeleportSweep { [HarmonyPostfix] private static void Postfix(PlayerControllerB __instance) { try { if ((Object)(object)__instance == (Object)(object)GameNetworkManager.Instance?.localPlayerController) { RenderOptimizer.SweepNow(); } } catch (Exception arg) { Plugin.Logger.LogError((object)$"[TeleportSweep] {arg}"); } } } } namespace SimpleOptimize.Core { internal sealed class CoroutineRunner : MonoBehaviour { private static CoroutineRunner _instance; internal static CoroutineRunner Instance { get { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown if ((Object)(object)_instance == (Object)null) { GameObject val = new GameObject("SimpleOptimize.CoroutineRunner"); ((Object)val).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)val); _instance = val.AddComponent<CoroutineRunner>(); } return _instance; } } } internal static class SuiteAnnounce { private static readonly (string Guid, string Name)[] Suite = new(string, string)[5] { ("local.simplesell", "SimpleSell"), ("local.simpleweather", "SimpleWeather"), ("local.simpleblackbox", "SimpleBlackBox"), ("local.simpleoptimize", "SimpleOptimize"), ("local.simplebuy", "SimpleBuy") }; internal static void MaybeAnnounce(string myGuid) { try { List<(string, string)> list = Suite.Where(((string Guid, string Name) s) => Chainloader.PluginInfos.ContainsKey(s.Guid)).ToList(); if (list.Count == 0 || list[0].Item1 != myGuid) { return; } if (list.Count == Suite.Length) { ChatUtil.Send($"Simple Suite by Chonk_Zilla: {list.Count}/{Suite.Length} plugins loaded — /help"); return; } string arg = string.Join(", ", from s in Suite where !Chainloader.PluginInfos.ContainsKey(s.Guid) select s.Name); ChatUtil.Send($"Simple Suite by Chonk_Zilla: {list.Count}/{Suite.Length} plugins loaded (missing: {arg}) — /help"); } catch (Exception arg2) { Plugin.Logger.LogError((object)$"[SuiteAnnounce] {arg2}"); } } } internal static class SuiteHandshake { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnHello; public static Action<ulong> <1>__OnClientChanged; public static HandleNamedMessageDelegate <2>__OnVerdict; public static HandleNamedMessageDelegate <3>__OnSpray; } internal const string HelloMsg = "SimpleSuite.Hello"; internal const string VerdictMsg = "SimpleSuite.Verdict"; internal const string SprayMsg = "SimpleSuite.Spray"; private static readonly HashSet<ulong> _haveIt = new HashSet<ulong>(); internal static bool AllPlayersHaveIt { get; private set; } private static bool IsConnected(NetworkManager nm, ulong id) { foreach (ulong connectedClientsId in nm.ConnectedClientsIds) { if (connectedClientsId == id) { return true; } } return false; } internal static void Reset() { _haveIt.Clear(); AllPlayersHaveIt = false; } internal static void Register() { //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown try { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null) { return; } CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; if (customMessagingManager == null) { return; } if (singleton.IsHost) { object obj = <>O.<0>__OnHello; if (obj == null) { HandleNamedMessageDelegate val = OnHello; <>O.<0>__OnHello = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("SimpleSuite.Hello", (HandleNamedMessageDelegate)obj); singleton.OnClientConnectedCallback += OnClientChanged; singleton.OnClientDisconnectCallback += OnClientChanged; _haveIt.Add(singleton.LocalClientId); Recompute(); return; } object obj2 = <>O.<2>__OnVerdict; if (obj2 == null) { HandleNamedMessageDelegate val2 = OnVerdict; <>O.<2>__OnVerdict = val2; obj2 = (object)val2; } customMessagingManager.RegisterNamedMessageHandler("SimpleSuite.Verdict", (HandleNamedMessageDelegate)obj2); object obj3 = <>O.<3>__OnSpray; if (obj3 == null) { HandleNamedMessageDelegate val3 = OnSpray; <>O.<3>__OnSpray = val3; obj3 = (object)val3; } customMessagingManager.RegisterNamedMessageHandler("SimpleSuite.Spray", (HandleNamedMessageDelegate)obj3); SendHello(); } catch (Exception arg) { Plugin.Logger.LogError((object)$"[SuiteHandshake.Register] {arg}"); } } private unsafe static void SendHello() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) try { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || singleton.IsHost) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(1, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteByteSafe((byte)1); singleton.CustomMessagingManager.SendNamedMessage("SimpleSuite.Hello", 0uL, val, (NetworkDelivery)2); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } catch (Exception arg) { Plugin.Logger.LogError((object)$"[SuiteHandshake.SendHello] {arg}"); } } private static void OnHello(ulong sender, FastBufferReader reader) { try { _haveIt.Add(sender); Plugin.Logger.LogInfo((object)$"[Handshake] client {sender} has the suite ({_haveIt.Count} known)."); Recompute(); BroadcastSpray(); } catch (Exception arg) { Plugin.Logger.LogError((object)$"[SuiteHandshake.OnHello] {arg}"); } } private static void OnVerdict(ulong sender, FastBufferReader reader) { try { byte b = default(byte); ((FastBufferReader)(ref reader)).ReadByteSafe(ref b); AllPlayersHaveIt = b != 0; Plugin.Logger.LogInfo((object)("[Handshake] host says fast mode " + (AllPlayersHaveIt ? "ON" : "OFF") + ".")); } catch (Exception arg) { Plugin.Logger.LogError((object)$"[SuiteHandshake.OnVerdict] {arg}"); } } private static void OnClientChanged(ulong _) { Recompute(); } private static void Recompute() { try { NetworkManager nm = NetworkManager.Singleton; if ((Object)(object)nm == (Object)null || !nm.IsHost) { return; } _haveIt.RemoveWhere((ulong id) => id != nm.LocalClientId && !IsConnected(nm, id)); bool flag = true; foreach (ulong connectedClientsId in nm.ConnectedClientsIds) { if (!_haveIt.Contains(connectedClientsId)) { flag = false; break; } } if (flag != AllPlayersHaveIt) { Plugin.Logger.LogInfo((object)("[Handshake] fast mode " + (flag ? "ON" : "OFF") + " " + $"({_haveIt.Count}/{nm.ConnectedClientsIds.Count} players have it).")); } AllPlayersHaveIt = flag; Broadcast(flag); } catch (Exception arg) { Plugin.Logger.LogError((object)$"[SuiteHandshake.Recompute] {arg}"); } } private unsafe static void Broadcast(bool on) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) try { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsHost || singleton.ConnectedClientsIds.Count == 0) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(1, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteByteSafe(on ? ((byte)1) : ((byte)0)); singleton.CustomMessagingManager.SendNamedMessageToAll("SimpleSuite.Verdict", val, (NetworkDelivery)2); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } catch (Exception arg) { Plugin.Logger.LogError((object)$"[SuiteHandshake.Broadcast] {arg}"); } } internal static int PushSpray() { int result = SprayColor.ReapplyAll(); BroadcastSpray(); return result; } internal unsafe static void BroadcastSpray() { //IL_006f: 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_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: 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) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) try { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsHost || singleton.ConnectedClientsIds.Count == 0) { return; } string text = ModConfig.SprayColorMode.Value?.ToLowerInvariant(); byte b = (byte)((text == "palette") ? 1 : ((text == "custom") ? 2 : 0)); byte b2 = b; Color c = Color.white; SprayColor.TryParseColor(ModConfig.SprayColorHex.Value, out c); FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(8, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteByteSafe(b2); int value = ModConfig.SprayColorIndex.Value; ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref value, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteByteSafe((byte)(c.r * 255f)); ((FastBufferWriter)(ref val)).WriteByteSafe((byte)(c.g * 255f)); ((FastBufferWriter)(ref val)).WriteByteSafe((byte)(c.b * 255f)); singleton.CustomMessagingManager.SendNamedMessageToAll("SimpleSuite.Spray", val, (NetworkDelivery)2); Plugin.Logger.LogInfo((object)$"[Handshake] pushed spray colour (mode={b2}) to {singleton.ConnectedClientsIds.Count} client(s)."); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } catch (Exception arg) { Plugin.Logger.LogError((object)$"[SuiteHandshake.BroadcastSpray] {arg}"); } } private static void OnSpray(ulong sender, FastBufferReader reader) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) try { if (ModConfig.SprayAcceptHostColor.Value) { byte b = default(byte); ((FastBufferReader)(ref reader)).ReadByteSafe(ref b); int value = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref value, default(ForPrimitives)); byte b2 = default(byte); ((FastBufferReader)(ref reader)).ReadByteSafe(ref b2); byte b3 = default(byte); ((FastBufferReader)(ref reader)).ReadByteSafe(ref b3); byte b4 = default(byte); ((FastBufferReader)(ref reader)).ReadByteSafe(ref b4); ModConfig.SprayColorMode.Value = b switch { 2 => "custom", 1 => "palette", _ => "off", }; ModConfig.SprayColorIndex.Value = value; ModConfig.SprayColorHex.Value = $"#{b2:X2}{b3:X2}{b4:X2}"; int num = SprayColor.ReapplyAll(); Plugin.Logger.LogInfo((object)("[Handshake] host set spray colour (" + ModConfig.SprayColorMode.Value + " " + $"{ModConfig.SprayColorHex.Value}) — {num} can(s) refreshed.")); } } catch (Exception arg) { Plugin.Logger.LogError((object)$"[SuiteHandshake.OnSpray] {arg}"); } } internal static string StatusFragment() { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null) { return "handshake: no session"; } if (!singleton.IsHost) { return "handshake: client, fast=" + (AllPlayersHaveIt ? "on" : "off"); } return string.Format("handshake: {0}/{1} have it, fast={2}", _haveIt.Count, singleton.ConnectedClientsIds.Count, AllPlayersHaveIt ? "on" : "off"); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }