Please disclose if your mod was created primarily 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 FiresGhettoNetworking v1.1.6
VAGhettoNetworking.dll
Decompiled a month agousing System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("VAGhettoNetworking")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("VAGhettoNetworking")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("f234bd11-429c-45e2-b280-1fb9121d050d")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace FiresGhettoNetworkMod { [BepInPlugin("com.Fire.FiresGhettoNetworkMod", "FiresGhettoNetworkMod", "1.1.6")] public class FiresGhettoNetworkMod : BaseUnityPlugin { [HarmonyPatch] public static class WackyDatabaseCompatibilityPatch { public static void Init(Harmony harmony) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown Type type = Type.GetType("wackydatabase.Util.Functions, WackysDatabase"); if (type == null) { LoggerOptions.LogInfo("WackyDatabase not detected — skipping compatibility patch."); return; } MethodInfo method = type.GetMethod("SnapshotItem", BindingFlags.Static | BindingFlags.Public); if (method == null) { LoggerOptions.LogWarning("WackyDatabase detected but SnapshotItem method not found — patch skipped."); return; } harmony.Patch((MethodBase)method, new HarmonyMethod(typeof(WackyDatabaseCompatibilityPatch), "SnapshotItem_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); LoggerOptions.LogInfo("WackyDatabase compatibility patch applied — will skip snapshots for invalid/broken clones."); } [HarmonyPrefix] public static bool SnapshotItem_Prefix(ref ItemDrop item) { if ((Object)(object)item == (Object)null) { LoggerOptions.LogWarning("WDB: Skipping snapshot for null ItemDrop (likely broken clone)."); return false; } if ((Object)(object)((Component)item).gameObject == (Object)null) { LoggerOptions.LogWarning("WDB: Skipping snapshot for " + ((Object)item).name + " — gameObject is null (missing prefab from removed mod)."); return false; } bool flag = ((Component)item).GetComponentsInChildren<Renderer>(true).Length != 0; bool flag2 = ((Component)item).GetComponentsInChildren<MeshFilter>(true).Length != 0; if (!flag && !flag2) { LoggerOptions.LogWarning("WDB: Skipping snapshot for " + ((Object)item).name + " — no renderers or meshes (broken model)."); return false; } return true; } } [CompilerGenerated] private sealed class <RegisterDummyRpcWhenReady>d__35 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public FiresGhettoNetworkMod <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RegisterDummyRpcWhenReady>d__35(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 (ZRoutedRpc.instance == null) { <>2__current = null; <>1__state = 1; return true; } if (_dummyRpcRegistered) { ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)"Dummy ForceUpdateZDO RPC already registered — skipping."); return false; } ZRoutedRpc.instance.Register("ForceUpdateZDO", (Action<long>)delegate { }); _dummyRpcRegistered = true; ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)"Dummy ForceUpdateZDO RPC registered."); 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(); } } public const string PluginGUID = "com.Fire.FiresGhettoNetworkMod"; public const string PluginName = "FiresGhettoNetworkMod"; public const string PluginVersion = "1.1.6"; public static ConfigEntry<LogLevel> ConfigLogLevel; public static ConfigEntry<bool> ConfigEnableCompression; public static ConfigEntry<UpdateRateOptions> ConfigUpdateRate; public static ConfigEntry<SendRateMinOptions> ConfigSendRateMin; public static ConfigEntry<SendRateMaxOptions> ConfigSendRateMax; public static ConfigEntry<QueueSizeOptions> ConfigQueueSize; public static ConfigEntry<ForceCrossplayOptions> ConfigForceCrossplay; public static ConfigEntry<int> ConfigPlayerLimit; public static ConfigEntry<bool> ConfigEnableShipFixes; public static ConfigEntry<bool> ConfigEnableServerSideShipSimulation; public static ConfigEntry<int> ConfigExtendedZoneRadius; public static ConfigEntry<bool> ConfigEnableZDOThrottling; public static ConfigEntry<float> ConfigZDOThrottleDistance; public static ConfigEntry<bool> ConfigEnableAILOD; public static ConfigEntry<float> ConfigAILODNearDistance; public static ConfigEntry<float> ConfigAILODFarDistance; public static ConfigEntry<float> ConfigAILODThrottleFactor; public static ConfigEntry<int> ConfigZoneLoadBatchSize; public static ConfigEntry<int> ConfigZPackageReceiveBufferSize; public static ConfigEntry<bool> ConfigEnableServerAuthority; private static bool _dummyRpcRegistered; private bool _delayedInitDone = false; internal static Harmony Harmony { get; private set; } private void Awake() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown Harmony = new Harmony("com.Fire.FiresGhettoNetworkMod"); BindConfigs(); try { ((BaseUnityPlugin)this).Config.Save(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to save config file immediately: " + ex.Message)); } LoggerOptions.Init(((BaseUnityPlugin)this).Logger); ServerClientUtils.Detect(((BaseUnityPlugin)this).Logger); bool isDedicatedServerDetected = ServerClientUtils.IsDedicatedServerDetected; if (isDedicatedServerDetected) { LoggerOptions.LogInfo("Running on DEDICATED SERVER — enabling all server-side features."); } else { LoggerOptions.LogInfo("Running on CLIENT or SINGLE-PLAYER/LISTEN SERVER — only minimal client-safe features will be applied."); } SafeInvokeInit("FiresGhettoNetworkMod.CompressionGroup", "InitConfig", new object[1] { ((BaseUnityPlugin)this).Config }); SafeInvokeInit("FiresGhettoNetworkMod.NetworkingRatesGroup", "Init", new object[1] { ((BaseUnityPlugin)this).Config }); SafeInvokeInit("FiresGhettoNetworkMod.DedicatedServerGroup", "Init", new object[1] { ((BaseUnityPlugin)this).Config }); Harmony.PatchAll(typeof(CompressionGroup)); Harmony.PatchAll(typeof(NetworkingRatesGroup)); Harmony.PatchAll(typeof(DedicatedServerGroup)); WackyDatabaseCompatibilityPatch.Init(Harmony); if (isDedicatedServerDetected && ConfigEnableServerAuthority.Value) { PlayerPositionSyncPatches.Init(((BaseUnityPlugin)this).Config); Harmony.PatchAll(typeof(PlayerPositionSyncPatches)); Harmony.PatchAll(typeof(ShipFixesGroup)); Harmony.PatchAll(typeof(ZDOMemoryManager)); Harmony.PatchAll(typeof(ServerAuthorityPatches)); Harmony.PatchAll(typeof(MonsterAIPatches)); Harmony.PatchAll(typeof(ZDOThrottlingPatches)); Harmony.PatchAll(typeof(AILODPatches)); LoggerOptions.LogInfo("All server-side features and authority patches enabled."); } else if (!isDedicatedServerDetected) { LoggerOptions.LogInfo("Server-side features skipped — not running on a dedicated server."); } else { LoggerOptions.LogInfo("Server-side features disabled via ConfigEnableServerAuthority = false."); } ((MonoBehaviour)this).StartCoroutine(RegisterDummyRpcWhenReady()); ((BaseUnityPlugin)this).Logger.LogInfo((object)"FiresGhettoNetworkMod v1.1.6 loaded."); } private void TryPatchAll(Type type) { if (type == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"Tried to patch a null type!"); } else { Harmony.PatchAll(type); } } private void SafeInvokeInit(string typeName, string methodName, object[] args) { try { Type type = Type.GetType(typeName); if (type == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Type " + typeName + " not found; skipping " + methodName + ".")); return; } MethodInfo method = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Method " + methodName + " not found on " + typeName + ".")); } else { method.Invoke(null, args); } } catch (TypeLoadException arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"TypeLoadException while invoking {typeName}.{methodName}: {arg}"); } catch (Exception arg2) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Exception while invoking {typeName}.{methodName}: {arg2}"); } } private void BindConfigs() { //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected O, but got Unknown //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Expected O, but got Unknown //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Expected O, but got Unknown //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Expected O, but got Unknown //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Expected O, but got Unknown //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Expected O, but got Unknown //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Expected O, but got Unknown //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Expected O, but got Unknown ConfigLogLevel = ((BaseUnityPlugin)this).Config.Bind<LogLevel>("General", "Log Level", LogLevel.Message, "Controls verbosity in BepInEx log."); ConfigEnableCompression = ((BaseUnityPlugin)this).Config.Bind<bool>("Networking", "Enable Compression", true, "Enable ZSTD network compression (highly recommended)."); ConfigUpdateRate = ((BaseUnityPlugin)this).Config.Bind<UpdateRateOptions>("Networking", "Update Rate", UpdateRateOptions._100, "Server update frequency. Lower = less bandwidth."); ConfigSendRateMin = ((BaseUnityPlugin)this).Config.Bind<SendRateMinOptions>("Networking.Steamworks", "Send Rate Min", SendRateMinOptions._256KB, "Minimum send rate Steam will attempt."); ConfigSendRateMax = ((BaseUnityPlugin)this).Config.Bind<SendRateMaxOptions>("Networking.Steamworks", "Send Rate Max", SendRateMaxOptions._1024KB, "Maximum send rate Steam will attempt."); ConfigQueueSize = ((BaseUnityPlugin)this).Config.Bind<QueueSizeOptions>("Networking", "Queue Size", QueueSizeOptions._32KB, "Send queue size. Higher helps high-player servers."); ConfigForceCrossplay = ((BaseUnityPlugin)this).Config.Bind<ForceCrossplayOptions>("Dedicated Server", "Force Crossplay", ForceCrossplayOptions.steamworks, "Requires restart.\nsteamworks = Force crossplay DISABLED (Steam friends only)\nplayfab = Force crossplay ENABLED (PlayFab matchmaking)\nvanilla = Respect command-line -crossplay flag (default Valheim behavior)"); ConfigPlayerLimit = ((BaseUnityPlugin)this).Config.Bind<int>("Dedicated Server", "Player Limit", 10, new ConfigDescription("Max players on dedicated server. Requires restart.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 127), Array.Empty<object>())); ConfigEnableShipFixes = ((BaseUnityPlugin)this).Config.Bind<bool>("Ship Fixes", "Enable Universal Ship Fixes", true, "Apply permanent autopilot + jitter fixes to ALL ships."); ConfigEnableServerSideShipSimulation = ((BaseUnityPlugin)this).Config.Bind<bool>("Ship Fixes", "Server-Side Ship Simulation", true, "Server authoritatively simulates ship physics."); ConfigEnableServerAuthority = ((BaseUnityPlugin)this).Config.Bind<bool>("Server Authority", "Enable Server-Side Simulation", true, new ConfigDescription("Makes the server fully authoritative over zones, ZDO ownership, monster AI, events, etc. (does NOT override your existing ship fixes).\n\nWARNING: THIS IS A SERVER-ONLY FEATURE!\nEnabling this on a CLIENT will cause INFINITE LOADING SCREEN.\nThe mod automatically disables it on clients regardless of this setting.", (AcceptableValueBase)null, Array.Empty<object>())); ConfigExtendedZoneRadius = ((BaseUnityPlugin)this).Config.Bind<int>("Server Authority", "Extended Zone Radius", 1, new ConfigDescription("Additional zone layers the server pre-loads around players for smoother zone transitions.\n0 = vanilla (no extra pre-load)\n1 = +1 layer (recommended, ~7x7 zones total)\n2 = +2 layers (~9x9 zones)\n3 = +3 layers (~11x11 zones)\n\nHigher values reduce stutter when crossing zone borders but increase server CPU/RAM usage.\nSERVER-ONLY — clients ignore this setting.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 3), Array.Empty<object>())); ConfigEnableZDOThrottling = ((BaseUnityPlugin)this).Config.Bind<bool>("Server Authority", "Enable ZDO Throttling", true, "Reduce update frequency for distant ZDOs (creatures/structures far away) to save bandwidth.\nSERVER-ONLY — no effect on client."); ConfigZDOThrottleDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Server Authority", "ZDO Throttle Distance", 500f, new ConfigDescription("Distance (meters) beyond which ZDOs are throttled (lower update rate).\n0 = disable throttling.\nRecommended: 400-600m.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1000f), Array.Empty<object>())); ConfigEnableAILOD = ((BaseUnityPlugin)this).Config.Bind<bool>("Server Authority", "Enable AI LOD Throttling", true, "Reduce FixedUpdate frequency for distant AI (saves server CPU).\nNearby AI stays full speed for smooth combat.\nSERVER-ONLY — no effect on client."); ConfigAILODNearDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Server Authority", "AI LOD Near Distance", 100f, new ConfigDescription("Full-speed AI within this range (meters).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(50f, 200f), Array.Empty<object>())); ConfigAILODFarDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Server Authority", "AI LOD Far Distance", 300f, new ConfigDescription("Beyond this distance, AI is throttled (meters).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(200f, 600f), Array.Empty<object>())); ConfigAILODThrottleFactor = ((BaseUnityPlugin)this).Config.Bind<float>("Server Authority", "AI LOD Throttle Factor", 0.5f, new ConfigDescription("Update multiplier for throttled AI (0.5 = half speed, 0.25 = quarter). Lower = more savings.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 0.75f), Array.Empty<object>())); ZDOMemoryManager.ConfigMaxZDOs = ((BaseUnityPlugin)this).Config.Bind<int>("Advanced", "Max Active ZDOs", 500000, new ConfigDescription("If the number of active ZDOs exceeds this value, the mod will force cleanup of orphan non-persistent ZDOs and run garbage collection.\nSet to 0 to disable. Useful on very long-running servers with high entity counts.\nDefault: 500000 (vanilla rarely goes above ~200k).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1000000), Array.Empty<object>())); ConfigEntryBase[] array = (ConfigEntryBase[])(object)new ConfigEntryBase[19] { (ConfigEntryBase)ConfigLogLevel, (ConfigEntryBase)ConfigEnableCompression, (ConfigEntryBase)ConfigUpdateRate, (ConfigEntryBase)ConfigSendRateMin, (ConfigEntryBase)ConfigSendRateMax, (ConfigEntryBase)ConfigQueueSize, (ConfigEntryBase)ConfigForceCrossplay, (ConfigEntryBase)ConfigPlayerLimit, (ConfigEntryBase)ConfigEnableShipFixes, (ConfigEntryBase)ConfigEnableServerSideShipSimulation, (ConfigEntryBase)ConfigEnableServerAuthority, (ConfigEntryBase)ConfigExtendedZoneRadius, (ConfigEntryBase)ConfigEnableZDOThrottling, (ConfigEntryBase)ConfigZDOThrottleDistance, (ConfigEntryBase)ConfigEnableAILOD, (ConfigEntryBase)ConfigAILODNearDistance, (ConfigEntryBase)ConfigAILODFarDistance, (ConfigEntryBase)ConfigAILODThrottleFactor, (ConfigEntryBase)ZDOMemoryManager.ConfigMaxZDOs }; ConfigEntryBase[] array2 = array; foreach (ConfigEntryBase val in array2) { Type type = ((object)val).GetType(); EventInfo @event = type.GetEvent("SettingChanged"); if (@event != null) { EventHandler handler = delegate(object sender, EventArgs __) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown string text = (((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) ? "SERVER" : "CLIENT"); ConfigEntryBase val2 = (ConfigEntryBase)sender; LoggerOptions.LogInfo($"[{text}] Config changed: {val2.Definition.Section} → {val2.Definition.Key} = {val2.BoxedValue}"); }; @event.AddEventHandler(val, handler); } } if ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer()) { ConfigEnableServerAuthority.Value = false; } } private void Start() { ((MonoBehaviour)this).StartCoroutine(RegisterDummyRpcWhenReady()); } [IteratorStateMachine(typeof(<RegisterDummyRpcWhenReady>d__35))] private IEnumerator RegisterDummyRpcWhenReady() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <RegisterDummyRpcWhenReady>d__35(0) { <>4__this = this }; } } public enum LogLevel { [Description("Errors/Warnings only")] Warning, [Description("Errors/Warnings/Messages [default]")] Message, [Description("Everything including Info")] Info } public enum UpdateRateOptions { [Description("100% - 20 updates/sec [default]")] _100, [Description("75% - 15 updates/sec")] _75, [Description("50% - 10 updates/sec")] _50 } public enum SendRateMinOptions { [Description("1024 KB/s | 8 Mbit/s")] _1024KB, [Description("768 KB/s | 6 Mbit/s")] _768KB, [Description("512 KB/s | 4 Mbit/s")] _512KB, [Description("256 KB/s | 2 Mbit/s [default]")] _256KB, [Description("150 KB/s | 1.2 Mbit/s [vanilla]")] _150KB } public enum SendRateMaxOptions { [Description("1024 KB/s | 8 Mbit/s [default]")] _1024KB, [Description("768 KB/s | 6 Mbit/s")] _768KB, [Description("512 KB/s | 4 Mbit/s")] _512KB, [Description("256 KB/s | 2 Mbit/s")] _256KB, [Description("150 KB/s | 1.2 Mbit/s [vanilla]")] _150KB } public enum QueueSizeOptions { [Description("80 KB")] _80KB, [Description("64 KB")] _64KB, [Description("48 KB")] _48KB, [Description("32 KB [default]")] _32KB, [Description("Vanilla (~10 KB)")] _vanilla } public enum ForceCrossplayOptions { [Description("Vanilla behaviour - respect -crossplay flag [default]")] vanilla, [Description("Force crossplay ENABLED (use PlayFab backend)")] playfab, [Description("Force crossplay DISABLED (use Steamworks backend)")] steamworks } [HarmonyPatch] public static class AILODPatches { [HarmonyPatch(typeof(Character), "CustomFixedUpdate")] [HarmonyPrefix] public static bool CustomFixedUpdate_Prefix(Character __instance, float dt) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsDedicated() || !FiresGhettoNetworkMod.ConfigEnableAILOD.Value) { return true; } if (!__instance.IsPlayer()) { Tameable component = ((Component)__instance).GetComponent<Tameable>(); if (component == null || !((Object)(object)component != (Object)null) || !component.IsTamed()) { float num = float.MaxValue; foreach (Player allPlayer in Player.GetAllPlayers()) { if ((Object)(object)allPlayer != (Object)null) { float num2 = Vector3.Distance(((Component)__instance).transform.position, ((Component)allPlayer).transform.position); if (num2 < num) { num = num2; } } } if (num <= FiresGhettoNetworkMod.ConfigAILODNearDistance.Value) { return true; } if (num > FiresGhettoNetworkMod.ConfigAILODFarDistance.Value) { int hashCode = ((object)__instance).GetHashCode(); float num3 = 1f / FiresGhettoNetworkMod.ConfigAILODThrottleFactor.Value; if ((Time.time + (float)hashCode * 0.001f) % num3 > dt) { return false; } } return true; } } return true; } } [HarmonyPatch] public static class CompressionGroup { internal static class CompressionStatus { public class SocketStatus { public int version = 0; public bool compressionEnabled = false; public bool sendingCompressed = false; public bool receivingCompressed = false; } private const int COMPRESSION_VERSION = 6; public static readonly SocketStatus ourStatus = new SocketStatus { version = 6, compressionEnabled = false }; private static readonly Dictionary<ISocket, SocketStatus> peerStatus = new Dictionary<ISocket, SocketStatus>(); public static void AddPeer(ISocket socket) { if (socket != null) { if (peerStatus.ContainsKey(socket)) { peerStatus.Remove(socket); } peerStatus[socket] = new SocketStatus(); LoggerOptions.LogMessage("Compression: New peer connected " + socket.GetEndPointString()); } } public static void RemovePeer(ISocket socket) { peerStatus.Remove(socket); } public static SocketStatus GetStatus(ISocket socket) { SocketStatus value; return peerStatus.TryGetValue(socket, out value) ? value : null; } public static bool IsCompatible(ISocket socket) { SocketStatus status = GetStatus(socket); return status != null && status.version == ourStatus.version; } public static bool GetSendCompressionStarted(ISocket socket) { return GetStatus(socket)?.sendingCompressed ?? false; } public static bool GetReceiveCompressionStarted(ISocket socket) { return GetStatus(socket)?.receivingCompressed ?? false; } public static void SetSendCompressionStarted(ISocket socket, bool started) { GetStatus(socket).sendingCompressed = started; } public static void SetReceiveCompressionStarted(ISocket socket, bool started) { GetStatus(socket).receivingCompressed = started; } } private static string ZSTD_DICT_RESOURCE_NAME = "FiresGhettoNetworkMod.dict.small"; private static int ZSTD_LEVEL = 1; private static object compressor; private static object decompressor; public static ConfigEntry<bool> ConfigCompressionEnabled; private const string RPC_COMPRESSION_VERSION = "FiresGhetto.CompressionVersion"; private const string RPC_COMPRESSION_ENABLED = "FiresGhetto.CompressionEnabled"; private const string RPC_COMPRESSION_STARTED = "FiresGhetto.CompressedStarted"; public static void InitConfig(ConfigFile config) { ConfigCompressionEnabled = FiresGhettoNetworkMod.ConfigEnableCompression; ConfigCompressionEnabled.SettingChanged += delegate { SetCompressionEnabledFromConfig(); }; CompressionStatus.ourStatus.compressionEnabled = ConfigCompressionEnabled?.Value ?? false; } public static void InitCompressor() { try { Type type = Type.GetType("ZstdSharp.Compressor, ZstdSharp"); Type type2 = Type.GetType("ZstdSharp.Decompressor, ZstdSharp"); if (type == null || type2 == null) { LoggerOptions.LogWarning("ZstdSharp assembly not found - compression disabled."); return; } Assembly executingAssembly = Assembly.GetExecutingAssembly(); byte[] array; using (Stream stream = executingAssembly.GetManifestResourceStream(ZSTD_DICT_RESOURCE_NAME)) { if (stream == null) { LoggerOptions.LogError("Compression dictionary resource not found. Compression disabled."); return; } array = new byte[stream.Length]; stream.Read(array, 0, array.Length); } compressor = Activator.CreateInstance(type, ZSTD_LEVEL); type.GetMethod("LoadDictionary")?.Invoke(compressor, new object[1] { array }); decompressor = Activator.CreateInstance(type2); type2.GetMethod("LoadDictionary")?.Invoke(decompressor, new object[1] { array }); LoggerOptions.LogInfo("ZSTD compression dictionary loaded successfully."); } catch (Exception arg) { LoggerOptions.LogError($"Failed to initialize compressor: {arg}"); } } private static void SetCompressionEnabledFromConfig() { bool value = ConfigCompressionEnabled.Value; CompressionStatus.ourStatus.compressionEnabled = value; LoggerOptions.LogMessage("Network compression: " + (value ? "Enabled" : "Disabled")); SendCompressionEnabledStatusToAll(); } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] [HarmonyPostfix] private static void OnNewConnection(ZNetPeer peer) { if (compressor != null) { CompressionStatus.AddPeer(peer.m_socket); RegisterRPCs(peer); SendCompressionVersion(peer); } } [HarmonyPatch(typeof(ZNet), "Disconnect")] [HarmonyPostfix] private static void OnDisconnect(ZNetPeer peer) { CompressionStatus.RemovePeer(peer.m_socket); } private static void RegisterRPCs(ZNetPeer peer) { peer.m_rpc.Register<int>("FiresGhetto.CompressionVersion", (Action<ZRpc, int>)RPC_CompressionVersion); peer.m_rpc.Register<bool>("FiresGhetto.CompressionEnabled", (Action<ZRpc, bool>)RPC_CompressionEnabled); peer.m_rpc.Register<bool>("FiresGhetto.CompressedStarted", (Action<ZRpc, bool>)RPC_CompressionStarted); } private static void SendCompressionVersion(ZNetPeer peer) { peer.m_rpc.Invoke("FiresGhetto.CompressionVersion", new object[1] { CompressionStatus.ourStatus.version }); } private static void RPC_CompressionVersion(ZRpc rpc, int version) { ZNetPeer val = FindPeerByRpc(rpc); if (val != null) { CompressionStatus.SocketStatus status = CompressionStatus.GetStatus(val.m_socket); if (status != null) { status.version = version; } if (version == CompressionStatus.ourStatus.version) { LoggerOptions.LogMessage("Compression compatible with " + GetPeerName(val)); } else { LoggerOptions.LogWarning($"Compression version mismatch with {GetPeerName(val)} (them: {version}, us: {CompressionStatus.ourStatus.version})"); } if (CompressionStatus.IsCompatible(val.m_socket)) { SendCompressionEnabledStatus(val); } } } private static void SendCompressionEnabledStatusToAll() { if ((Object)(object)ZNet.instance == (Object)null) { return; } foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (CompressionStatus.IsCompatible(peer.m_socket)) { SendCompressionEnabledStatus(peer); } } } private static void SendCompressionEnabledStatus(ZNetPeer peer) { peer.m_rpc.Invoke("FiresGhetto.CompressionEnabled", new object[1] { CompressionStatus.ourStatus.compressionEnabled }); bool started = CompressionStatus.ourStatus.compressionEnabled && (CompressionStatus.GetStatus(peer.m_socket)?.compressionEnabled ?? false); SendCompressionStarted(peer, started); } private static void RPC_CompressionEnabled(ZRpc rpc, bool enabled) { ZNetPeer val = FindPeerByRpc(rpc); if (val != null) { CompressionStatus.SocketStatus status = CompressionStatus.GetStatus(val.m_socket); if (status != null) { status.compressionEnabled = enabled; } bool started = CompressionStatus.ourStatus.compressionEnabled && enabled; SendCompressionStarted(val, started); } } private static void SendCompressionStarted(ZNetPeer peer, bool started) { CompressionStatus.SocketStatus status = CompressionStatus.GetStatus(peer.m_socket); if (status != null && status.sendingCompressed != started) { peer.m_rpc.Invoke("FiresGhetto.CompressedStarted", new object[1] { started }); Flush(peer); status.sendingCompressed = started; LoggerOptions.LogMessage("Compression " + (started ? "started" : "stopped") + " with " + GetPeerName(peer)); } } private static void Flush(ZNetPeer peer) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_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_0009: 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_0010: Invalid comparison between Unknown and I4 OnlineBackendType onlineBackend = ZNet.m_onlineBackend; OnlineBackendType val = onlineBackend; if ((int)val != 0) { if ((int)val == 1) { } } else { peer.m_socket.Flush(); } } private static void RPC_CompressionStarted(ZRpc rpc, bool started) { ZNetPeer val = FindPeerByRpc(rpc); if (val != null) { CompressionStatus.SocketStatus status = CompressionStatus.GetStatus(val.m_socket); if (status != null) { status.receivingCompressed = started; } LoggerOptions.LogMessage("Receiving " + (started ? "compressed" : "uncompressed") + " data from " + GetPeerName(val)); } } internal static byte[] Compress(byte[] data) { if (compressor == null) { return data; } Type type = compressor.GetType(); MethodInfo methodInfo = type.GetMethod("Wrap", new Type[1] { typeof(byte[]) }) ?? type.GetMethod("Wrap"); object obj = methodInfo.Invoke(compressor, new object[1] { data }); if (obj is byte[] result) { return result; } MethodInfo methodInfo2 = obj?.GetType().GetMethod("ToArray", Type.EmptyTypes); if (methodInfo2 != null) { return (byte[])methodInfo2.Invoke(obj, null); } return data; } internal static byte[] Decompress(byte[] data) { if (decompressor == null) { throw new Exception("Decompressor not initialized"); } Type type = decompressor.GetType(); MethodInfo methodInfo = type.GetMethod("Unwrap", new Type[1] { typeof(byte[]) }) ?? type.GetMethod("Unwrap"); object obj = methodInfo.Invoke(decompressor, new object[1] { data }); if (obj is byte[] result) { return result; } MethodInfo methodInfo2 = obj?.GetType().GetMethod("ToArray", Type.EmptyTypes); if (methodInfo2 != null) { return (byte[])methodInfo2.Invoke(obj, null); } throw new Exception("Failed to decompress data"); } [HarmonyPatch(typeof(ZSteamSocket), "SendQueuedPackages")] [HarmonyPrefix] private static bool Steam_SendCompressed(ref Queue<byte[]> ___m_sendQueue, ZSteamSocket __instance) { if (compressor == null || !CompressionStatus.GetSendCompressionStarted((ISocket)(object)__instance)) { return true; } ___m_sendQueue = new Queue<byte[]>(___m_sendQueue.Select((byte[] p) => Compress(p))); return true; } [HarmonyPatch(typeof(ZSteamSocket), "Recv")] [HarmonyPostfix] private static void Steam_RecvCompressed(ref ZPackage __result, ZSteamSocket __instance) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown if (__result == null || decompressor == null) { return; } CompressionStatus.SocketStatus status = CompressionStatus.GetStatus((ISocket)(object)__instance); if (status == null || !status.receivingCompressed) { return; } try { __result = new ZPackage(Decompress(__result.GetArray())); } catch { LoggerOptions.LogWarning("Failed to decompress incoming Steamworks package - falling back to uncompressed"); status.receivingCompressed = false; } } private static ZNetPeer FindPeerByRpc(ZRpc rpc) { try { if (rpc == null || ZRoutedRpc.instance == null) { return null; } return ((List<ZNetPeer>)AccessTools.Field(typeof(ZRoutedRpc), "m_peers").GetValue(ZRoutedRpc.instance))?.FirstOrDefault((Func<ZNetPeer, bool>)((ZNetPeer p) => p.m_rpc == rpc)); } catch { return null; } } private static string GetPeerName(ZNetPeer peer) { if (peer == null) { return "unknown"; } try { if (peer.m_socket != null) { return peer.m_socket.GetEndPointString(); } } catch { } return peer.m_uid.ToString(); } } [HarmonyPatch] public static class DedicatedServerGroup { private static bool isDedicatedDetected; public static void Init(ConfigFile config) { LoggerOptions.LogInfo("Dedicated server features initialized."); isDedicatedDetected = ServerClientUtils.IsDedicatedServerDetected; if (isDedicatedDetected) { LoggerOptions.LogInfo("Running as dedicated server (ServerClientUtils)."); } else { LoggerOptions.LogInfo("Running as client/listen-server (ServerClientUtils)."); } } [HarmonyPatch(typeof(FejdStartup), "ParseServerArguments")] [HarmonyPostfix] private static void ApplyForceCrossplay() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) if (isDedicatedDetected) { switch (FiresGhettoNetworkMod.ConfigForceCrossplay.Value) { case ForceCrossplayOptions.playfab: ZNet.m_onlineBackend = (OnlineBackendType)1; LoggerOptions.LogInfo("Forcing crossplay ENABLED (PlayFab backend)."); break; case ForceCrossplayOptions.steamworks: ZNet.m_onlineBackend = (OnlineBackendType)0; LoggerOptions.LogInfo("Forcing crossplay DISABLED (Steamworks backend)."); break; default: LoggerOptions.LogInfo("Crossplay mode: vanilla (respecting command line)."); break; } } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> OverridePlayerLimit(IEnumerable<CodeInstruction> instructions) { //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Invalid comparison between Unknown and I4 //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Expected O, but got Unknown if (!isDedicatedDetected) { return instructions; } List<CodeInstruction> list = new List<CodeInstruction>(instructions); bool flag = false; for (int i = 0; i < list.Count; i++) { if (!(list[i].opcode == OpCodes.Call) || !(list[i].operand is MethodInfo methodInfo) || !(methodInfo.Name == "GetNrOfPlayers")) { continue; } for (int j = i + 1; j < list.Count; j++) { if (list[j].opcode == OpCodes.Ldc_I4_S || list[j].opcode == OpCodes.Ldc_I4 || list[j].opcode == OpCodes.Ldc_I4_0 || list[j].opcode == OpCodes.Ldc_I4_1 || list[j].opcode == OpCodes.Ldc_I4_2 || list[j].opcode == OpCodes.Ldc_I4_3 || list[j].opcode == OpCodes.Ldc_I4_4 || list[j].opcode == OpCodes.Ldc_I4_5 || list[j].opcode == OpCodes.Ldc_I4_6 || list[j].opcode == OpCodes.Ldc_I4_7 || list[j].opcode == OpCodes.Ldc_I4_8) { int num = FiresGhettoNetworkMod.ConfigPlayerLimit.Value; if ((int)ZNet.m_onlineBackend == 1) { num++; LoggerOptions.LogInfo("Applied +1 player limit for PlayFab backend."); } LoggerOptions.LogInfo($"Overriding player limit constant → {num}"); list[j] = new CodeInstruction(OpCodes.Ldc_I4, (object)num); flag = true; break; } } if (flag) { break; } } if (!flag) { LoggerOptions.LogWarning("Player limit constant not found in ZNet.RPC_PeerInfo. Patch skipped – possible game update or conflicting mod."); } return list; } } public static class LoggerOptions { private static ManualLogSource logger; public static void Init(ManualLogSource source) { logger = source; } public static void LogError(object data) { logger.LogError(data); } public static void LogWarning(object data) { logger.LogWarning(data); } public static void LogMessage(object data) { if (FiresGhettoNetworkMod.ConfigLogLevel != null && FiresGhettoNetworkMod.ConfigLogLevel.Value >= LogLevel.Message) { logger.LogMessage(data); } } public static void LogInfo(object data) { if (FiresGhettoNetworkMod.ConfigLogLevel != null && FiresGhettoNetworkMod.ConfigLogLevel.Value >= LogLevel.Info) { logger.LogInfo(data); } } } [HarmonyPatch] public static class MonsterAIPatches { private static readonly int PlayerPrefabHash = StringExtensionMethods.GetStableHashCode("Player"); private static readonly List<Player> s_tempPlayers = new List<Player>(); [HarmonyPatch(typeof(SpawnSystem), "UpdateSpawning")] [HarmonyPrefix] private static bool UpdateSpawning_Prefix(SpawnSystem __instance, ZNetView ___m_nview, List<SpawnSystemList> ___m_spawnLists) { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsDedicated()) { return true; } if ((Object)(object)___m_nview == (Object)null || !___m_nview.IsValid() || !___m_nview.IsOwner()) { return false; } s_tempPlayers.Clear(); GetPlayersInZone(__instance, s_tempPlayers); if (s_tempPlayers.Count == 0) { return false; } DateTime time = ZNet.instance.GetTime(); foreach (SpawnSystemList ___m_spawnList in ___m_spawnLists) { if (___m_spawnList?.m_spawners != null) { Traverse.Create((object)__instance).Method("UpdateSpawnList", new object[3] { ___m_spawnList.m_spawners, time, false }).GetValue(); } } if ((Object)(object)RandEventSystem.instance != (Object)null) { List<SpawnData> currentSpawners = RandEventSystem.instance.GetCurrentSpawners(); if (currentSpawners != null) { Traverse.Create((object)__instance).Method("UpdateSpawnList", new object[3] { currentSpawners, time, true }).GetValue(); } } return false; } private static void GetPlayersInZone(SpawnSystem spawnSystem, List<Player> players) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) foreach (Player allPlayer in Player.GetAllPlayers()) { if ((Object)(object)allPlayer != (Object)null && InsideZone(spawnSystem, ((Component)allPlayer).transform.position)) { players.Add(allPlayer); } } } private static bool InsideZone(SpawnSystem spawnSystem, Vector3 point, float extra = 0f) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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_001b: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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_004b: Unknown result type (might be due to invalid IL or missing references) float num = 32f + extra; Vector3 position = ((Component)spawnSystem).transform.position; return point.x >= position.x - num && point.x <= position.x + num && point.z >= position.z - num && point.z <= position.z + num; } [HarmonyPatch(typeof(RandEventSystem), "FixedUpdate")] [HarmonyPrefix] private static bool RandEventSystem_FixedUpdate_Prefix(RandEventSystem __instance) { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsDedicated()) { return true; } List<Player> allPlayers = Player.GetAllPlayers(); if (allPlayers == null || allPlayers.Count == 0) { return false; } return true; } public static Player GetNearestPlayer(Vector3 position) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) Player result = null; float num = float.MaxValue; foreach (Player allPlayer in Player.GetAllPlayers()) { if ((Object)(object)allPlayer != (Object)null) { float num2 = Vector3.Distance(position, ((Component)allPlayer).transform.position); if (num2 < num) { num = num2; result = allPlayer; } } } return result; } public static bool IsAnyPlayerInActiveArea(Vector3 position) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZoneSystem.instance == (Object)null) { return false; } Vector2i zone = ZoneSystem.GetZone(position); int activeArea = ZoneSystem.instance.m_activeArea; foreach (Player allPlayer in Player.GetAllPlayers()) { if ((Object)(object)allPlayer != (Object)null) { Vector2i zone2 = ZoneSystem.GetZone(((Component)allPlayer).transform.position); if (ZNetScene.InActiveArea(zone, zone2, activeArea)) { return true; } } } return false; } public static Player GetClosestPlayerInRange(Vector3 position, float maxDistance) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) Player result = null; float num = maxDistance; foreach (Player allPlayer in Player.GetAllPlayers()) { if ((Object)(object)allPlayer != (Object)null && !((Character)allPlayer).IsDead()) { float num2 = Vector3.Distance(position, ((Component)allPlayer).transform.position); if (num2 < num) { num = num2; result = allPlayer; } } } return result; } public static bool IsPlayerZDO(ZDO zdo) { return zdo != null && zdo.GetPrefab() == PlayerPrefabHash; } } [HarmonyPatch] public static class NetworkingRatesGroup { public static void Init(ConfigFile config) { FiresGhettoNetworkMod.ConfigUpdateRate.SettingChanged += delegate { ApplyUpdateRate(); }; FiresGhettoNetworkMod.ConfigSendRateMin.SettingChanged += delegate { ApplySendRates(); }; FiresGhettoNetworkMod.ConfigSendRateMax.SettingChanged += delegate { ApplySendRates(); }; FiresGhettoNetworkMod.ConfigQueueSize.SettingChanged += delegate { LoggerOptions.LogInfo("Queue size changed - restart recommended."); }; ApplyUpdateRate(); ApplySendRates(); } private static void ApplyUpdateRate() { LoggerOptions.LogMessage($"Update rate set to {FiresGhettoNetworkMod.ConfigUpdateRate.Value}"); } public static void ApplySendRates() { if (!((Object)(object)ZNet.instance == (Object)null)) { int sendRateValue = GetSendRateValue(FiresGhettoNetworkMod.ConfigSendRateMin.Value); int sendRateValue2 = GetSendRateValue(FiresGhettoNetworkMod.ConfigSendRateMax.Value); SetSteamConfig("k_ESteamNetworkingConfig_SendRateMin", sendRateValue); SetSteamConfig("k_ESteamNetworkingConfig_SendRateMax", sendRateValue2); LoggerOptions.LogMessage($"Steam send rates applied: Min {sendRateValue / 1024} KB/s, Max {sendRateValue2 / 1024} KB/s"); } } private static int GetSendRateValue(object option) { string text = option.ToString(); if (1 == 0) { } int result = text switch { "_1024KB" => 1048576, "_768KB" => 786432, "_512KB" => 524288, "_256KB" => 262144, _ => 153600, }; if (1 == 0) { } return result; } [HarmonyPatch(typeof(ZDOMan), "SendZDOToPeers2")] [HarmonyPrefix] private static void AdjustUpdateInterval(ref float dt) { switch (FiresGhettoNetworkMod.ConfigUpdateRate.Value) { case UpdateRateOptions._75: dt *= 0.75f; break; case UpdateRateOptions._50: dt *= 0.5f; break; } } [HarmonyPatch(typeof(ZNet), "Start")] [HarmonyPostfix] private static void EnsureRatesOnStart() { ApplySendRates(); } private static void SetSteamConfig(string enumMemberName, int value) { IntPtr intPtr = IntPtr.Zero; try { IEnumerable<Type> source = AppDomain.CurrentDomain.GetAssemblies().SelectMany(delegate(Assembly a) { try { return a.GetTypes(); } catch { return Array.Empty<Type>(); } }); Type type = source.FirstOrDefault((Type t) => t.FullName == "Steamworks.ESteamNetworkingConfigValue"); Type type2 = source.FirstOrDefault((Type t) => t.FullName == "Steamworks.ESteamNetworkingConfigScope"); Type type3 = source.FirstOrDefault((Type t) => t.FullName == "Steamworks.ESteamNetworkingConfigDataType"); if (type == null || type2 == null || type3 == null) { LoggerOptions.LogWarning("Steamworks.NET types not found - send rate config skipped."); return; } object obj = Enum.Parse(type, enumMemberName); object obj2 = Enum.Parse(type2, "k_ESteamNetworkingConfig_Global"); object obj3 = Enum.Parse(type3, "k_ESteamNetworkingConfig_Int32"); intPtr = Marshal.AllocHGlobal(4); Marshal.WriteInt32(intPtr, value); Type type4 = ((Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsDedicated()) ? source.FirstOrDefault((Type t) => t.FullName == "Steamworks.SteamGameServerNetworkingUtils") : source.FirstOrDefault((Type t) => t.FullName == "Steamworks.SteamNetworkingUtils")); if (type4 == null) { LoggerOptions.LogWarning("Steamworks utils type not found - send rate config skipped."); return; } MethodInfo method = type4.GetMethod("SetConfigValue", BindingFlags.Static | BindingFlags.Public); if (method == null) { LoggerOptions.LogWarning("SetConfigValue method not found - send rate config skipped."); return; } method.Invoke(null, new object[5] { obj, obj2, IntPtr.Zero, obj3, intPtr }); } catch (Exception ex) { LoggerOptions.LogWarning("Failed to set Steam config " + enumMemberName + ": " + ex.Message); } finally { if (intPtr != IntPtr.Zero) { Marshal.FreeHGlobal(intPtr); } } } [HarmonyPatch(typeof(ZSteamSocket), "RegisterGlobalCallbacks")] [HarmonyPostfix] private static void ApplySendRatesOnConnect() { ApplySendRates(); } [HarmonyPatch(typeof(ZDOMan), "SendZDOs")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> SendZDOs_QueueLimitTranspiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); int num = 0; int configuredQueueLimit = GetConfiguredQueueLimit(); for (int i = 0; i < list.Count; i++) { if ((!(list[i].opcode == OpCodes.Ldc_I4) && !(list[i].opcode == OpCodes.Ldc_I4_S)) || !(list[i].operand is int num2) || num2 < 10240) { continue; } bool flag = false; for (int j = Math.Max(0, i - 15); j < Math.Min(list.Count, i + 15); j++) { if (list[j].opcode == OpCodes.Callvirt && list[j].operand is MethodInfo methodInfo && methodInfo.Name == "GetSendQueueSize") { flag = true; break; } } if (flag) { LoggerOptions.LogInfo($"Overriding ZDOMan.SendZDOs queue limit #{num + 1}: original {num2} → {configuredQueueLimit} bytes"); list[i].opcode = OpCodes.Ldc_I4; list[i].operand = configuredQueueLimit; num++; } } if (num == 0) { LoggerOptions.LogWarning("No queue limit constants found in ZDOMan.SendZDOs — queue size config not applied (game update may have changed IL)."); } else { LoggerOptions.LogInfo($"Successfully patched {num} queue limit constant(s)."); } return list.AsEnumerable(); } private static int GetConfiguredQueueLimit() { QueueSizeOptions value = FiresGhettoNetworkMod.ConfigQueueSize.Value; if (1 == 0) { } int result = value switch { QueueSizeOptions._80KB => 81920, QueueSizeOptions._64KB => 65536, QueueSizeOptions._48KB => 49152, QueueSizeOptions._32KB => 32768, _ => 10240, }; if (1 == 0) { } return result; } } [HarmonyPatch] public static class PlayerPositionSyncPatches { private class PlayerPredictionData { public Vector3 lastPos; public Quaternion lastRot; public Vector3 velocity; public float lastUpdateTime; public bool hasData = false; } public static ConfigEntry<bool> ConfigEnablePlayerPositionBoost; public static ConfigEntry<float> ConfigPlayerPositionUpdateMultiplier; public static ConfigEntry<bool> ConfigEnableClientInterpolation; public static ConfigEntry<bool> ConfigEnablePlayerPrediction; private static Dictionary<long, PlayerPredictionData> predictionData = new Dictionary<long, PlayerPredictionData>(); public static void Init(ConfigFile config) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown ConfigEnablePlayerPositionBoost = config.Bind<bool>("Player Sync", "Enable High-Frequency Position Updates", true, "Boosts server send rate for player positions to reduce floaty movement/desync between players."); ConfigPlayerPositionUpdateMultiplier = config.Bind<float>("Player Sync", "Position Update Multiplier", 2.5f, new ConfigDescription("Multiplier for player position sync priority (1.0 = vanilla, 2.5 = recommended). Higher = smoother on mixed PCs.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>())); ConfigEnableClientInterpolation = config.Bind<bool>("Player Sync", "Enable Client-Side Interpolation", true, "Smooths received player positions on clients to eliminate jitter on high-ping/low-end PCs."); ConfigEnablePlayerPrediction = config.Bind<bool>("Player Sync", "Enable Client-Side Prediction", true, "Predicts other players' movement between network updates for ultra-smooth feel (especially in combat on high ping).\nCLIENT-ONLY — no server impact."); } [HarmonyPatch(typeof(ZDOMan), "ServerSortSendZDOS")] [HarmonyPrefix] public static void ServerSortSendZDOS_Prefix(List<ZDO> objects, Vector3 refPos) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (!ConfigEnablePlayerPositionBoost.Value || !ZNet.instance.IsServer()) { return; } float value = ConfigPlayerPositionUpdateMultiplier.Value; foreach (ZDO @object in objects) { @object.m_tempSortValue = Vector3.Distance(@object.GetPosition(), refPos); if (IsPlayerZDO(@object)) { @object.m_tempSortValue -= 150f * value; } } } private static bool IsPlayerZDO(ZDO zdo) { if (zdo == null) { return false; } return zdo.GetString(StringExtensionMethods.GetStableHashCode("playerName"), "").Length > 0; } [HarmonyPatch(typeof(ZNetView), "Deserialize")] [HarmonyPostfix] public static void Deserialize_Postfix(ZNetView __instance, ZPackage pkg) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Invalid comparison between Unknown and I4 //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_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_00cd: 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_013e: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0147: 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_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: 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_0136: Unknown result type (might be due to invalid IL or missing references) if ((!ConfigEnableClientInterpolation.Value && !ConfigEnablePlayerPrediction.Value) || (Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer() || (int)ZNet.GetConnectionStatus() != 2) { return; } ZDO val = ((__instance != null) ? __instance.GetZDO() : null); if (val == null || !IsPlayerZDO(val)) { return; } long owner = val.GetOwner(); if (owner == ZNet.GetUID()) { return; } Vector3 position = val.GetPosition(); Quaternion rotation = val.GetRotation(); if (!predictionData.TryGetValue(owner, out var value)) { value = new PlayerPredictionData { lastPos = position, lastRot = rotation, lastUpdateTime = Time.time, hasData = true }; predictionData[owner] = value; return; } float num = Time.time - value.lastUpdateTime; if (num > 0f && value.hasData) { value.velocity = (position - value.lastPos) / num; } value.lastPos = position; value.lastRot = rotation; value.lastUpdateTime = Time.time; value.hasData = true; } [HarmonyPatch(typeof(Player), "LateUpdate")] [HarmonyPostfix] public static void Player_LateUpdate_Postfix(Player __instance) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Invalid comparison between Unknown and I4 //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: 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_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0189: 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) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer || (Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer() || (int)ZNet.GetConnectionStatus() != 2) { return; } ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return; } ZDO zDO = component.GetZDO(); if (zDO == null || !IsPlayerZDO(zDO)) { return; } long owner = zDO.GetOwner(); if (predictionData.TryGetValue(owner, out var value) && value.hasData) { if (ConfigEnablePlayerPrediction.Value) { float num = Time.deltaTime * 1.5f; Vector3 val = value.lastPos + value.velocity * num; ((Component)__instance).transform.position = Vector3.Lerp(((Component)__instance).transform.position, val, 0.8f); } if (ConfigEnableClientInterpolation.Value) { float num2 = Time.deltaTime * 12f; num2 = Mathf.Clamp01(num2); Vector3 val2 = value.lastPos + value.velocity * Time.deltaTime * 0.5f; ((Component)__instance).transform.position = Vector3.Lerp(((Component)__instance).transform.position, val2, num2); ((Component)__instance).transform.rotation = Quaternion.Slerp(((Component)__instance).transform.rotation, value.lastRot, num2); } } } } [HarmonyPatch] public static class ServerAuthorityPatches { private static readonly int DefaultActiveArea = 3; private static readonly int DefaultDistantArea = 5; [HarmonyPatch(typeof(ZoneSystem), "IsActiveAreaLoaded")] [HarmonyPriority(800)] [HarmonyPrefix] public static bool IsActiveAreaLoaded_TeleportFix(ref bool __result) { if ((Object)(object)Player.m_localPlayer != (Object)null && ((Character)Player.m_localPlayer).IsTeleporting()) { __result = true; return false; } return true; } [HarmonyPatch(typeof(ZNetScene), "CreateDestroyObjects")] [HarmonyPrefix] public static bool CreateDestroyObjects_Prefix(ZNetScene __instance) { //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsDedicated() || ZNet.instance.GetConnectedPeers().Count == 0) { return true; } int value = FiresGhettoNetworkMod.ConfigExtendedZoneRadius.Value; int num = (ZoneSystem.instance?.m_activeArea ?? DefaultActiveArea) + value; int num2 = (ZoneSystem.instance?.m_activeDistantArea ?? DefaultDistantArea) + value; List<ZDO> list = new List<ZDO>(); List<ZDO> list2 = new List<ZDO>(); foreach (ZNetPeer connectedPeer in ZNet.instance.GetConnectedPeers()) { if (connectedPeer.IsReady()) { Vector3 refPos = connectedPeer.GetRefPos(); Vector2i zone = ZoneSystem.GetZone(refPos); ZDOMan.instance.FindSectorObjects(zone, num, num2, list, list2); } } List<ZDO> list3 = list.Distinct().ToList(); List<ZDO> list4 = list2.Distinct().ToList(); Traverse val = Traverse.Create((object)__instance); val.Method("CreateObjects", new object[2] { list3, list4 }).GetValue(); val.Method("RemoveObjects", new object[2] { list3, list4 }).GetValue(); return false; } [HarmonyPatch(typeof(ZoneSystem), "IsActiveAreaLoaded")] [HarmonyPrefix] public static bool IsActiveAreaLoaded_Prefix(ref bool __result, ZoneSystem __instance) { //IL_00c9: 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_00d3: 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_013d: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsDedicated() || ZNet.instance.GetPeers().Count == 0) { return true; } int value = FiresGhettoNetworkMod.ConfigExtendedZoneRadius.Value; int num = __instance.m_activeArea + value; object value2 = Traverse.Create((object)__instance).Field("m_zones").GetValue(); if (value2 == null) { return true; } if (!(value2 is IDictionary dictionary)) { return true; } foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (!peer.IsReady()) { continue; } Vector2i zone = ZoneSystem.GetZone(peer.GetRefPos()); for (int i = zone.y - num; i <= zone.y + num; i++) { for (int j = zone.x - num; j <= zone.x + num; j++) { if (!dictionary.Contains((object)new Vector2i(j, i))) { __result = false; return false; } } } } __result = true; return false; } [HarmonyPatch(typeof(ZoneSystem), "Update")] [HarmonyPostfix] public static void ZoneSystem_Update_Postfix(ZoneSystem __instance) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsDedicated() || ZNet.instance.GetPeers().Count == 0) { return; } Traverse val = Traverse.Create((object)__instance); foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer.IsReady()) { val.Method("CreateLocalZones", new object[1] { peer.GetRefPos() }).GetValue(); } } } private static bool IsPlayerZDO(ZDO zdo) { int prefab = zdo.GetPrefab(); return prefab == StringExtensionMethods.GetStableHashCode("Player"); } private static bool IsPeerConnected(ZDOMan zdoMan, long uid) { if (uid == ZDOMan.GetSessionID()) { return true; } foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer.m_uid == uid) { return true; } } return false; } [HarmonyPatch(typeof(ZNetScene), "OutsideActiveArea", new Type[] { typeof(Vector3) })] [HarmonyPrefix] public static bool OutsideActiveArea_Prefix(ref bool __result, Vector3 point) { //IL_0086: 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_008e: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsDedicated() || ZNet.instance.GetPeers().Count == 0) { return true; } int value = FiresGhettoNetworkMod.ConfigExtendedZoneRadius.Value; int num = (ZoneSystem.instance?.m_activeArea ?? DefaultActiveArea) + value; __result = true; foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer.IsReady() && !ZNetScene.OutsideActiveArea(point, ZoneSystem.GetZone(peer.GetRefPos()), num)) { __result = false; break; } } return false; } [HarmonyPatch(typeof(Tameable), "Awake")] [HarmonyPrefix] public static bool Tameable_Awake_Prefix() { return (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsDedicated(); } [HarmonyPatch(typeof(Tameable), "Update")] [HarmonyPrefix] public static bool Tameable_Update_Prefix() { return (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsDedicated(); } [HarmonyPatch(typeof(Tameable), "SetText")] [HarmonyPrefix] public static bool Tameable_SetText_Prefix() { return (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsDedicated(); } [HarmonyPatch(typeof(AudioMan), "Update")] [HarmonyPrefix] public static bool AudioMan_Update_Prefix() { ZNet instance = ZNet.instance; return instance == null || !instance.IsDedicated(); } } public static class ServerClientUtils { private static ManualLogSource _earlyLogger; public static bool IsDedicatedServerDetected { get; private set; } public static void Detect(ManualLogSource logger = null) { //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Invalid comparison between Unknown and I4 _earlyLogger = logger; IsDedicatedServerDetected = false; try { string path = Process.GetCurrentProcess().MainModule?.FileName ?? ""; string text = Path.GetFileNameWithoutExtension(path).ToLowerInvariant(); string text2 = Path.GetDirectoryName(path)?.ToLowerInvariant() ?? ""; Log("Executable name: " + text); Log("Executable directory: " + text2); if (text.Contains("server")) { IsDedicatedServerDetected = true; Log("Detected dedicated server via executable name containing 'server'."); return; } if (text2.Contains("server") || text2.Contains("dedicated")) { IsDedicatedServerDetected = true; Log("Detected dedicated server via directory path containing 'server' or 'dedicated'."); return; } Log($"Application.isBatchMode = {Application.isBatchMode}"); if (Application.isBatchMode) { IsDedicatedServerDetected = true; Log("Detected dedicated server via Application.isBatchMode."); return; } string[] commandLineArgs = Environment.GetCommandLineArgs(); string[] array = commandLineArgs; foreach (string text3 in array) { string text4 = text3.ToLowerInvariant(); if (text4 == "-batchmode" || text4 == "-nographics" || text4.Contains("dedicated")) { IsDedicatedServerDetected = true; Log("Detected dedicated server via command line argument: " + text3); return; } } if ((int)SystemInfo.graphicsDeviceType == 4) { IsDedicatedServerDetected = true; Log("Detected dedicated server via null graphics device (headless mode)."); return; } Type type = AccessTools.TypeByName("ZNet") ?? Type.GetType("ZNet, Assembly-CSharp"); if (type == null) { Log("ZNet type not found; assuming client/listen-server."); return; } MethodInfo method = type.GetMethod("IsDedicated", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { object obj = method.Invoke(null, null); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { IsDedicatedServerDetected = true; Log("Detected dedicated server via ZNet.IsDedicated()."); return; } } MethodInfo method2 = type.GetMethod("IsServer", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (method2 != null) { object obj2 = method2.Invoke(null, null); bool flag2 = default(bool); int num2; if (obj2 is bool) { flag2 = (bool)obj2; num2 = 1; } else { num2 = 0; } if (((uint)num2 & (flag2 ? 1u : 0u)) != 0) { IsDedicatedServerDetected = true; Log("Detected dedicated server via ZNet.IsServer()."); return; } } object obj3 = (type.GetField("m_instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(null); if (obj3 != null) { PropertyInfo property = type.GetProperty("IsServer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { object value = property.GetValue(obj3); bool flag3 = default(bool); int num3; if (value is bool) { flag3 = (bool)value; num3 = 1; } else { num3 = 0; } if (((uint)num3 & (flag3 ? 1u : 0u)) != 0) { IsDedicatedServerDetected = true; Log("Detected dedicated server via ZNet.instance.IsServer."); return; } } MethodInfo method3 = type.GetMethod("IsDedicated", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method3 != null) { object obj4 = method3.Invoke(obj3, null); bool flag4 = default(bool); int num4; if (obj4 is bool) { flag4 = (bool)obj4; num4 = 1; } else { num4 = 0; } if (((uint)num4 & (flag4 ? 1u : 0u)) != 0) { IsDedicatedServerDetected = true; Log("Detected dedicated server via ZNet.instance.IsDedicated."); return; } } } Log("No dedicated-server indicator found; assuming client/listen-server."); } catch (Exception ex) { LogWarn("Server detection failed: " + ex.Message); IsDedicatedServerDetected = false; } } private static void Log(string message) { ManualLogSource earlyLogger = _earlyLogger; if (earlyLogger != null) { earlyLogger.LogInfo((object)message); } } private static void LogWarn(string message) { ManualLogSource earlyLogger = _earlyLogger; if (earlyLogger != null) { earlyLogger.LogWarning((object)message); } } public static bool IsRunningOnDedicatedServer() { if (IsDedicatedServerDetected) { return true; } if ((Object)(object)ZNet.instance != (Object)null) { return ZNet.instance.IsDedicated(); } return false; } } [HarmonyPatch] public static class ShipFixesGroup { [HarmonyPatch(typeof(Player), "TryPlacePiece")] public static class Player_TryPlacePiece_Patch { public static void Postfix(Player __instance, Piece piece, bool __result) { if (!__result || (Object)(object)piece == (Object)null) { return; } ShipControlls component = ((Component)piece).GetComponent<ShipControlls>(); if ((Object)(object)component != (Object)null) { ((Behaviour)component).enabled = true; Debug.Log((object)("FiresGhettoNetworkMod: Enabled ShipControlls on placed ship: " + ((Object)piece).name)); } string cleanName = ((Object)piece).name.Replace("(Clone)", "").Trim(); if (ShipPrefabNames.Any((string name) => cleanName.StartsWith(name))) { ZNetView component2 = ((Component)piece).GetComponent<ZNetView>(); if ((Object)(object)component2 != (Object)null && component2.GetZDO() != null) { component2.GetZDO().Set(ZDOVars.s_user, -1L); Debug.Log((object)("FiresGhettoNetworkMod: " + cleanName + " placed — PERMANENT AUTOPILOT ENABLED")); } } } } [HarmonyPatch(typeof(ShipControlls), "RPC_RequestControl")] [HarmonyPatch(typeof(ShipControlls), "RPC_ReleaseControl")] public static class ShipControlls_BlockUserWrite_Patch { private static bool Prefix(ShipControlls __instance) { return true; } private static void Postfix(ShipControlls __instance) { if (!FiresGhettoNetworkMod.ConfigEnableShipFixes.Value || (Object)(object)__instance?.m_ship == (Object)null) { return; } string cleanName = ((Object)__instance.m_ship).name.Replace("(Clone)", "").Trim(); if (!ShipPrefabNames.Any((string n) => cleanName.StartsWith(n))) { return; } ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid()) { long @long = component.GetZDO().GetLong(ZDOVars.s_user, 0L); if (@long != -1) { component.GetZDO().Set(ZDOVars.s_user, -1L); component.InvokeRPC("ForceUpdateZDO", Array.Empty<object>()); LoggerOptions.LogInfo("Reverted user on ship " + cleanName + " to -1 to preserve dummy physics."); } } } } [HarmonyPatch(typeof(ShipControlls), "HaveValidUser")] public static class ShipControlls_DummyPhysics_Patch { private static bool Prefix(ShipControlls __instance, ref bool __result) { if ((Object)(object)__instance.m_ship == (Object)null) { return true; } string cleanName = ((Object)__instance.m_ship).name.Replace("(Clone)", "").Trim(); if (!ShipPrefabNames.Any((string n) => cleanName.StartsWith(n))) { return true; } ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return true; } long @long = component.GetZDO().GetLong(ZDOVars.s_user, 0L); if (@long == -1) { __result = true; return false; } return true; } } public static readonly List<string> ShipPrefabNames = new List<string> { "Vandrarskapp01", "VAPrototype", "VAPrototype1", "VAPinnacle", "VAPinnacle1", "VAPinnacle2", "RowBoat", "VikingShip_Ashlands", "VikingShip", "Raft", "Karve", "Trailership" }; } [HarmonyPatch] public static class ZDOMemoryManager { public static ConfigEntry<int> ConfigMaxZDOs; private static float startupTimer; private static bool startupComplete; private static bool warningShown; private const float STARTUP_GRACE_PERIOD = 600f; public static void Init(ConfigFile config) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown ConfigMaxZDOs = config.Bind<int>("Advanced", "Max Active ZDOs", 10000000, new ConfigDescription("Force ZDO cleanup if active ZDOs exceed this after startup (0 = disabled).\nStartup grace period (10 min) prevents spam during world load.\nThis feature is CLIENT-ONLY and will not run on dedicated servers.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 2000000), Array.Empty<object>())); } [HarmonyPatch(typeof(ZDOMan), "Update")] [HarmonyPostfix] private static void CleanupIfTooBig(ZDOMan __instance, float dt) { if ((Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer()) || ConfigMaxZDOs.Value <= 0) { return; } if (!startupComplete) { startupTimer += dt; if (startupTimer >= 600f) { startupComplete = true; LoggerOptions.LogInfo("ZDO cleanup grace period ended — normal monitoring enabled."); } return; } FieldInfo fieldInfo = AccessTools.Field(typeof(ZDOMan), "m_objectsByID"); if (fieldInfo == null) { return; } Dictionary<ZDOID, ZDO> dictionary = (Dictionary<ZDOID, ZDO>)fieldInfo.GetValue(__instance); if (dictionary != null && dictionary.Count > ConfigMaxZDOs.Value) { if (!warningShown) { LoggerOptions.LogWarning($"ZDO pool too big ({dictionary.Count} > {ConfigMaxZDOs.Value}) — forcing cleanup..."); LoggerOptions.LogWarning("You have been Exploring a LOT. You should log out to free up RAM."); warningShown = true; } int count = dictionary.Count; AccessTools.Method(typeof(ZDOMan), "RemoveOrphanNonPersistentZDOS", (Type[])null, (Type[])null).Invoke(__instance, null); GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); dictionary = (Dictionary<ZDOID, ZDO>)fieldInfo.GetValue(__instance); LoggerOptions.LogInfo($"Cleanup complete: {count} → {dictionary?.Count ?? 0} ZDOs"); } } } [HarmonyPatch] public static class ZDOThrottlingPatches { private const float DISTANT_PENALTY = 500f; [HarmonyPatch(typeof(ZDOMan), "ServerSortSendZDOS")] [HarmonyPostfix] public static void ServerSortSendZDOS_Postfix(List<ZDO> objects, Vector3 refPos) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Invalid comparison between Unknown and I4 //IL_0092: 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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsDedicated() || !FiresGhettoNetworkMod.ConfigEnableZDOThrottling.Value) { return; } float value = FiresGhettoNetworkMod.ConfigZDOThrottleDistance.Value; if (value <= 0f) { return; } float num = value * value; bool flag = false; foreach (ZDO @object in objects) { if ((int)@object.Type != 1) { Vector3 position = @object.GetPosition(); float num2 = (position.x - refPos.x) * (position.x - refPos.x) + (position.z - refPos.z) * (position.z - refPos.z); if (num2 > num) { @object.m_tempSortValue += 500f; flag = true; } } } if (!flag) { return; } objects.Sort(delegate(ZDO x, ZDO y) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 if ((int)x.Type == 1 && (int)y.Type != 1) { return -1; } return ((int)y.Type == 1 && (int)x.Type != 1) ? 1 : x.m_tempSortValue.CompareTo(y.m_tempSortValue); }); } [HarmonyPatch(typeof(ZDOMan), "SendZDOToPeers2")] [HarmonyPrefix] public static void ThrottleDistantZDOs(ref float dt) { } } }