using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ConditionalConfigSync; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("Allifreyr")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("2.1.4.0")] [assembly: AssemblyInformationalVersion("2.1.4")] [assembly: AssemblyProduct("Forever Build 2")] [assembly: AssemblyTitle("ForeverBuild2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.1.4.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 ForeverBuild { internal static class Stability { internal static bool ShouldModify(WearNTear wear) { if (!PluginConfig.IsActive || (Object)(object)wear == (Object)null) { return false; } if ((Object)(object)((Component)wear).GetComponent() != (Object)null || (Object)(object)((Component)wear).GetComponent() != (Object)null) { return false; } Piece val = (((Object)(object)wear.m_piece != (Object)null) ? wear.m_piece : ((Component)wear).GetComponent()); if ((Object)(object)val != (Object)null) { return val.IsPlacedByPlayer(); } return false; } internal static void ApplyVanilla(MaterialType material, out float maxSupport, out float minSupport, out float horizontalLoss, out float verticalLoss) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected I4, but got Unknown switch ((int)material) { case 0: maxSupport = 100f; minSupport = 10f; verticalLoss = 0.125f; horizontalLoss = 0.2f; break; case 3: maxSupport = 140f; minSupport = 10f; verticalLoss = 0.1f; horizontalLoss = 1f / 6f; break; case 1: maxSupport = 1000f; minSupport = 100f; verticalLoss = 0.125f; horizontalLoss = 1f; break; case 2: maxSupport = 1500f; minSupport = 20f; verticalLoss = 1f / 13f; horizontalLoss = 1f / 13f; break; case 4: maxSupport = 1500f; minSupport = 100f; verticalLoss = 0.125f; horizontalLoss = 0.5f; break; case 5: maxSupport = 2000f; minSupport = 100f; verticalLoss = 0.1f; horizontalLoss = 1f / 3f; break; case 6: maxSupport = 5000f; minSupport = 100f; verticalLoss = 1f / 15f; horizontalLoss = 0.25f; break; case 7: maxSupport = 1000f; minSupport = 100f; verticalLoss = 0.125f; horizontalLoss = 1f / 3f; break; case 8: maxSupport = 200f; minSupport = 10f; verticalLoss = 1f / 13f; horizontalLoss = 0.2f; break; default: maxSupport = 0f; minSupport = 0f; verticalLoss = 0f; horizontalLoss = 0f; break; } } } [HarmonyPatch(typeof(WearNTear), "GetMaterialProperties")] internal static class WearNTearGetMaterialPropertiesPatch { private static int _lastLoggedId; private static float _lastLoggedTime; private static bool Prefix(WearNTear __instance, ref float maxSupport, ref float minSupport, ref float horizontalLoss, ref float verticalLoss) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (!Stability.ShouldModify(__instance)) { return true; } Stability.ApplyVanilla(__instance.m_materialType, out maxSupport, out minSupport, out horizontalLoss, out verticalLoss); if (PluginConfig.IsInfinite) { horizontalLoss = 0f; verticalLoss = 0f; LogOnce(__instance, "infinite (loss 0)"); return false; } float effectiveMultiplier = PluginConfig.EffectiveMultiplier; horizontalLoss /= effectiveMultiplier; verticalLoss /= effectiveMultiplier; LogOnce(__instance, "x" + effectiveMultiplier + " loss"); return false; } private static void LogOnce(WearNTear wear, string how) { if (!PluginConfig.ExtraLogging.Value) { return; } int instanceID = ((Object)wear).GetInstanceID(); if (instanceID != _lastLoggedId || !(Time.time - _lastLoggedTime < 2f)) { _lastLoggedId = instanceID; _lastLoggedTime = Time.time; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("Adjusted support on " + ((Object)wear).name + " (" + how + ")")); } } } } [HarmonyPatch(typeof(WearNTear), "HaveSupport")] internal static class WearNTearHaveSupportPatch { private static void Postfix(WearNTear __instance, ref bool __result) { if (PluginConfig.IsInfinite && Stability.ShouldModify(__instance)) { __result = true; } } } [BepInPlugin("Allifreyr.ForeverBuild2", "Forever Build 2", "2.1.4")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInIncompatibility("lime.plugins.foreverbuild")] [BepInIncompatibility("Allifreyr.ForeverBuild")] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "Allifreyr.ForeverBuild2"; public const string PluginName = "Forever Build 2"; public const string PluginVersion = "2.1.4"; internal static Plugin Instance { get; private set; } internal static ManualLogSource Log { get; private set; } internal static Harmony Harmony { get; private set; } private void Awake() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; Game.isModded = true; PluginConfig.Bind(((BaseUnityPlugin)this).Config); Harmony = new Harmony("Allifreyr.ForeverBuild2"); Harmony.PatchAll(Assembly.GetExecutingAssembly()); Log.LogInfo((object)string.Format("{0} {1} loaded. Mode={2}, multiplier={3}", "Forever Build 2", "2.1.4", PluginConfig.Mode.Value, PluginConfig.SupportMultiplier.Value)); } private void OnDestroy() { Harmony harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } Instance = null; } } public enum StabilityMode { Vanilla, Multiplier, Infinite } internal static class PluginConfig { internal static readonly ConfigSync ConfigSync = new ConfigSync("Allifreyr.ForeverBuild2") { DisplayName = "Forever Build 2", CurrentVersion = "2.1.4", MinimumRequiredVersion = "2.1.4", ModRequired = true }; internal static ConfigEntry LockConfiguration { get; private set; } internal static ConfigEntry ModEnabled { get; private set; } internal static ConfigEntry Mode { get; private set; } internal static ConfigEntry SupportMultiplier { get; private set; } internal static ConfigEntry ExtraLogging { get; private set; } internal static bool IsActive { get { if (ModEnabled.Value) { return Mode.Value != StabilityMode.Vanilla; } return false; } } internal static bool IsInfinite { get { if (ModEnabled.Value) { return Mode.Value == StabilityMode.Infinite; } return false; } } internal static float EffectiveMultiplier { get { float value = SupportMultiplier.Value; if (!(value < 1f)) { return value; } return 1f; } } internal static void Bind(ConfigFile config) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown LockConfiguration = config.Bind("1 - General", "Lock Configuration", true, "If on, only the server/host (and server admins) can change synced settings. [Synced with Server]"); ((ConditionalConfigSync)ConfigSync).AddLockingConfigEntry(LockConfiguration); ModEnabled = BindServer(config, "1 - General", "Enable", defaultValue: true, "Master switch. Off leaves vanilla stability untouched. [Synced with Server]"); Mode = BindServer(config, "2 - Stability", "Mode", StabilityMode.Infinite, "Vanilla: unchanged game math. Multiplier: support loss is divided by Support Multiplier (still needs a path to ground). Infinite: no support loss and pieces never collapse from stability, including mid-air. [Synced with Server]"); SupportMultiplier = BindServer(config, "2 - Stability", "Support Multiplier", 2f, new ConfigDescription("Used when Mode is Multiplier. 2 is about twice vanilla reach, 3 about three times, and so on. Minimum 1 (vanilla-equivalent). Does not allow floating pieces. [Synced with Server]", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 100f), Array.Empty())); ExtraLogging = BindClient(config, "3 - Debug", "Extra Logging", defaultValue: false, "Local only. Writes a line when Forever Build 2 changes a piece's support math."); } private static ConfigEntry BindServer(ConfigFile config, string section, string key, T defaultValue, string description) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown return BindServer(config, section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty())); } private static ConfigEntry BindServer(ConfigFile config, string section, string key, T defaultValue, ConfigDescription description) { ConfigEntry val = config.Bind(section, key, defaultValue, description); ((ConditionalConfigSync)ConfigSync).AddConfigEntry(val, (ConfigSyncMode)0); return val; } private static ConfigEntry BindClient(ConfigFile config, string section, string key, T defaultValue, string description) { ConfigEntry val = config.Bind(section, key, defaultValue, description); ((ConditionalConfigSync)ConfigSync).AddConfigEntry(val, (ConfigSyncMode)2); return val; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }