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 BuildTweaks v1.0.1
BuildTweaks.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; 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: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("BuildTweaks")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("BuildTweaks")] [assembly: AssemblyTitle("BuildTweaks")] [assembly: AssemblyVersion("1.0.0.0")] [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 BuildTweaks { [BepInPlugin("local.buildtweaks", "Build Tweaks", "1.0.0")] public class BuildTweaksPlugin : BaseUnityPlugin { private class SyncData { public bool allowToggle; public bool extIgnoreCollision; public float extRange; public bool forceValid; } private class OrigExt { public float dist; } private static BuildTweaksPlugin I; private const string RpcName = "LocalBuildTweaks_Cfg"; private const int ProtocolVersion = 3; private ConfigEntry<KeyboardShortcut> toggleKey; private ConfigEntry<bool> cfgAllowToggle; private ConfigEntry<bool> cfgExtIgnoreCollision; private ConfigEntry<float> cfgExtRange; private ConfigEntry<bool> cfgForceValid; private ConfigEntry<bool> cfgDebug; private static SyncData fromServer; private bool collisionOff; private volatile bool reloadFlag; private float nextReload; private static readonly Dictionary<StationExtension, OrigExt> Orig = new Dictionary<StationExtension, OrigExt>(); private static readonly FieldInfo FDist = AccessTools.Field(typeof(StationExtension), "m_maxStationDistance"); private static readonly FieldInfo FStatus = AccessTools.Field(typeof(Player), "m_placementStatus"); private static readonly FieldInfo FGhost = AccessTools.Field(typeof(Player), "m_placementGhost"); private static readonly MethodInfo MSetGhostValid = AccessTools.Method(typeof(Player), "SetPlacementGhostValid", (Type[])null, (Type[])null); private static readonly MethodInfo MTestClip = AccessTools.Method(typeof(Player), "TestGhostClipping", (Type[])null, (Type[])null); private static bool inRawClipTest; private static string lastDebug = ""; private static bool EffAllowToggle => (fromServer != null) ? fromServer.allowToggle : I.cfgAllowToggle.Value; private static bool EffExtIgnoreCollision => (fromServer != null) ? fromServer.extIgnoreCollision : I.cfgExtIgnoreCollision.Value; private static float EffExtRange => (fromServer != null) ? fromServer.extRange : I.cfgExtRange.Value; private static bool EffForceValid => (fromServer != null) ? fromServer.forceValid : I.cfgForceValid.Value; private void Awake() { //IL_0022: 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_00b1: Expected O, but got Unknown //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Expected O, but got Unknown I = this; toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "ToggleBuildCollision", new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>()), "Кнопка включения и выключения коллизии построек (только у вас, не синхронизируется)"); cfgAllowToggle = ((BaseUnityPlugin)this).Config.Bind<bool>("Synced", "AllowCollisionToggle", true, "[Синхр.] Разрешить игрокам отключать коллизию построек по кнопке"); cfgExtIgnoreCollision = ((BaseUnityPlugin)this).Config.Bind<bool>("Synced", "ExtensionsIgnoreCollision", true, "[Синхр.] Убрать ограничение «нужно больше места» для улучшений крафт-станций: их можно ставить вплотную и внахлёст друг с другом и с другими постройками"); cfgExtRange = ((BaseUnityPlugin)this).Config.Bind<float>("Synced", "ExtensionRange", 0f, new ConfigDescription("[Синхр.] Максимальное расстояние (м) от крафт-станции до её улучшений. 0 = как в оригинале (обычно 5)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); cfgForceValid = ((BaseUnityPlugin)this).Config.Bind<bool>("Synced", "ForceValidWhenCollisionOff", true, "[Синхр.] Пока коллизия отключена кнопкой, любая установка, которую игра считает недопустимой, становится допустимой. Варды, зоны запрета строительства и привязка улучшений к станции продолжают работать"); cfgDebug = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogPlacementStatus", true, "Писать в лог BepInEx статус установки заблокированных построек, пока коллизия выключена, а также для улучшений станций (только у вас)"); ((BaseUnityPlugin)this).Config.SettingChanged += delegate { ApplyAllExtensions(); Broadcast(); }; WatchConfigFile(); Harmony h = new Harmony("local.buildtweaks"); TryPatch(h, typeof(Player), "TestGhostClipping", "ClipPrefix", prefix: true); TryPatch(h, typeof(Player), "UpdatePlacementGhost", "PlacementPostfix", prefix: false); TryPatch(h, typeof(StationExtension), "Awake", "ExtAwakePostfix", prefix: false); TryPatch(h, typeof(ZNet), "OnNewConnection", "NewConnPostfix", prefix: false); TryPatch(h, typeof(ZNet), "RPC_PeerInfo", "PeerInfoPostfix", prefix: false); TryPatch(h, typeof(ZNet), "OnDestroy", "NetDestroyPostfix", prefix: false); } private static void TryPatch(Harmony h, Type t, string method, string patch, bool prefix) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(t, method, (Type[])null, (Type[])null); if (methodInfo == null) { ((BaseUnityPlugin)I).Logger.LogWarning((object)("Method " + t.Name + "." + method + " not found - patch skipped")); return; } HarmonyMethod val = new HarmonyMethod(typeof(BuildTweaksPlugin).GetMethod(patch, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)); try { if (prefix) { h.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { h.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } catch (Exception ex) { ((BaseUnityPlugin)I).Logger.LogWarning((object)("Patch " + t.Name + "." + method + " failed: " + ex.Message)); } } private void WatchConfigFile() { try { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Path.GetDirectoryName(((BaseUnityPlugin)this).Config.ConfigFilePath), Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath)); fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite; fileSystemWatcher.Changed += delegate { reloadFlag = true; }; fileSystemWatcher.EnableRaisingEvents = true; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Config watcher not started: " + ex.Message)); } } private void Update() { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) if (reloadFlag && Time.unscaledTime >= nextReload) { reloadFlag = false; nextReload = Time.unscaledTime + 1f; try { ((BaseUnityPlugin)this).Config.Reload(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)ex.Message); } } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { collisionOff = false; } else { if (Typing()) { return; } KeyboardShortcut value = toggleKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { if (!EffAllowToggle) { ((Character)localPlayer).Message((MessageType)2, "Build collision toggle is disabled by the server", 0, (Sprite)null, false); return; } collisionOff = !collisionOff; ((Character)localPlayer).Message((MessageType)2, collisionOff ? "Build collision: OFF" : "Build collision: ON", 0, (Sprite)null, false); } } } private static bool Typing() { if ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus()) { return true; } if (Console.IsVisible()) { return true; } if (Menu.IsVisible()) { return true; } return false; } private static bool WantSkip(GameObject ghost) { if ((Object)(object)I == (Object)null) { return false; } if (I.collisionOff && EffAllowToggle) { return true; } return EffExtIgnoreCollision && (Object)(object)ghost != (Object)null && (Object)(object)ghost.GetComponent<StationExtension>() != (Object)null; } private static void DebugLog(string msg) { if (!((Object)(object)I == (Object)null) && I.cfgDebug.Value && !(msg == lastDebug)) { lastDebug = msg; ((BaseUnityPlugin)I).Logger.LogInfo((object)("[placement] " + msg)); } } private static bool ClipPrefix(GameObject __0, ref bool __result) { if (inRawClipTest) { return true; } if (WantSkip(__0)) { __result = false; return false; } return true; } private static void PlacementPostfix(Player __instance) { if ((Object)(object)I == (Object)null || FStatus == null || FGhost == null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } object? value = FGhost.GetValue(__instance); GameObject val = (GameObject)((value is GameObject) ? value : null); if ((Object)(object)val == (Object)null || !val.activeSelf || !WantSkip(val)) { return; } string name = Enum.GetName(FStatus.FieldType, FStatus.GetValue(__instance)); if (name == null || name == "Valid") { return; } bool flag = I.collisionOff && EffAllowToggle; bool flag2 = false; if (name == "MoreSpace") { flag2 = true; } else if (name == "Invalid") { if (flag && EffForceValid) { flag2 = true; } else if (MTestClip != null) { inRawClipTest = true; try { flag2 = (bool)MTestClip.Invoke(__instance, new object[2] { val, 0.2f }); } catch { } finally { inRawClipTest = false; } } } DebugLog(((Object)val).name + ": " + name + (flag2 ? " -> forced valid" : " (kept)")); if (flag2) { FStatus.SetValue(__instance, Enum.Parse(FStatus.FieldType, "Valid")); if (MSetGhostValid != null) { MSetGhostValid.Invoke(__instance, new object[1] { true }); } } } private static void ExtAwakePostfix(StationExtension __instance) { ApplyOne(__instance); } private static void ApplyOne(StationExtension e) { if ((Object)(object)e == (Object)null) { return; } if (!Orig.TryGetValue(e, out var value)) { value = new OrigExt(); if (FDist != null) { value.dist = (float)FDist.GetValue(e); } Orig[e] = value; } if (FDist != null) { float effExtRange = EffExtRange; FDist.SetValue(e, (effExtRange > 0f) ? effExtRange : value.dist); } } private static void ApplyAllExtensions() { foreach (StationExtension item in Orig.Keys.Where((StationExtension k) => (Object)(object)k == (Object)null).ToList()) { Orig.Remove(item); } StationExtension[] array = Object.FindObjectsByType<StationExtension>((FindObjectsSortMode)0); foreach (StationExtension e in array) { ApplyOne(e); } } private static bool IsServer() { return (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer(); } private static ZPackage MakePackage() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(3); val.Write(I.cfgAllowToggle.Value); val.Write(I.cfgExtIgnoreCollision.Value); val.Write(I.cfgExtRange.Value); val.Write(I.cfgForceValid.Value); return val; } private static void NewConnPostfix(ZNetPeer __0) { if (__0 != null && __0.m_rpc != null) { __0.m_rpc.Register<ZPackage>("LocalBuildTweaks_Cfg", (Action<ZRpc, ZPackage>)RPC_Receive); } } private static void PeerInfoPostfix(ZRpc __0) { if (!IsServer() || __0 == null) { return; } try { __0.Invoke("LocalBuildTweaks_Cfg", new object[1] { MakePackage() }); } catch (Exception ex) { ((BaseUnityPlugin)I).Logger.LogWarning((object)("Config send failed: " + ex.Message)); } } private static void Broadcast() { if (!IsServer()) { return; } try { List<ZNetPeer> value = Traverse.Create((object)ZNet.instance).Field("m_peers").GetValue<List<ZNetPeer>>(); if (value == null) { return; } foreach (ZNetPeer item in value) { try { if (item.m_rpc != null) { item.m_rpc.Invoke("LocalBuildTweaks_Cfg", new object[1] { MakePackage() }); } } catch { } } } catch (Exception ex) { ((BaseUnityPlugin)I).Logger.LogWarning((object)("Broadcast failed: " + ex.Message)); } } private static void RPC_Receive(ZRpc rpc, ZPackage pkg) { if (IsServer()) { return; } try { int num = pkg.ReadInt(); if (num != 3) { ((BaseUnityPlugin)I).Logger.LogWarning((object)"Server BuildTweaks version differs - using local config"); return; } fromServer = new SyncData { allowToggle = pkg.ReadBool(), extIgnoreCollision = pkg.ReadBool(), extRange = pkg.ReadSingle(), forceValid = pkg.ReadBool() }; ((BaseUnityPlugin)I).Logger.LogInfo((object)"Received config from server"); ApplyAllExtensions(); } catch (Exception ex) { ((BaseUnityPlugin)I).Logger.LogWarning((object)("Config receive failed: " + ex.Message)); } } private static void NetDestroyPostfix() { fromServer = null; } } }