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 AllTheBones v1.0.0
AllTheBones.dll
Decompiled 4 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using AllTheBones.Configuration; using AllTheBones.Items; using AllTheBones.Patches; using AllTheBones.Systems; using AllTheBones.Utils; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Extensions; using Jotunn.Managers; using Jotunn.Utils; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("JotunnModStub")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("JotunnModStub")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("0.1.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = "")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.0")] namespace AllTheBones { [BepInPlugin("com.ggr.AllTheBones", "AllTheBones", "0.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [SynchronizationMode(/*Could not decode attribute arguments.*/)] internal class AllTheBones : BaseUnityPlugin { public const string PluginGUID = "com.ggr.AllTheBones"; public const string PluginName = "AllTheBones"; public const string PluginVersion = "0.1.0"; public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization(); private void Awake() { Logger.LogInfo((object)"All The Bones has landed"); ModConfig.Init(((BaseUnityPlugin)this).Config); Diagnostics.Enabled = ModConfig.Diagnostics.Value; AddLocalizations(); ApplyPatches(); PrefabManager.OnVanillaPrefabsAvailable += AddItems; } private void ApplyPatches() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown Harmony harmony = new Harmony("com.ggr.AllTheBones"); ApplyPatch(harmony, ModConfig.UseItemPatch, typeof(UseItemPatches)); ApplyPatch(harmony, ModConfig.PlantGrowthPatch, typeof(PlantGrowthPatches)); ApplyPatch(harmony, ModConfig.PlantGrowthPatch, typeof(PlantAwakePatches)); ApplyPatch(harmony, ModConfig.StabilityBoostPatch, typeof(StabilityBoostPatch)); ApplyPatch(harmony, ModConfig.WeatherImmunityPatch, typeof(WeatherImmunityPatch)); if (Diagnostics.Enabled) { ApplyPatch(harmony, null, typeof(UpdateSupportProbe)); ApplyPatch(harmony, null, typeof(ClearCacheProbe)); } Logger.LogInfo((object)$"[AllTheBones] configuration: UseItem={ToggleText(ModConfig.UseItemPatch)} PlantGrowth={ToggleText(ModConfig.PlantGrowthPatch)} StabilityBoost={ToggleText(ModConfig.StabilityBoostPatch)} WeatherImmunity={ToggleText(ModConfig.WeatherImmunityPatch)} diagnostics={Diagnostics.Enabled}"); } private static void ApplyPatch(Harmony harmony, ConfigEntry<bool> toggle, Type patchClass) { if (toggle != null && !toggle.Value) { Logger.LogInfo((object)("[AllTheBones] patch " + patchClass.Name + ": disabled by config")); return; } try { List<MethodInfo> list = harmony.CreateClassProcessor(patchClass).Patch(); Logger.LogInfo((object)$"[AllTheBones] patch {patchClass.Name}: {list.Count} method(s)"); } catch (Exception ex) { Logger.LogError((object)("[AllTheBones] patch " + patchClass.Name + " failed: " + ex.Message)); } } private static string ToggleText(ConfigEntry<bool> toggle) { return (toggle != null && toggle.Value) ? "on" : "off"; } private void Update() { Diagnostics.Tick(); MealBagRadiusIndicator.EnsureExists(); BoostedPlantTint.Tick(); } private void AddLocalizations() { CustomLocalization localization = Localization; string text = "English"; localization.AddTranslation(ref text, new Dictionary<string, string> { { "item_bonemeal", "Bone Meal" }, { "item_bonemeal_description", "Ground bone, rich in nutrients. Spread on a planted crop to speed up its growth. Put it on your hotbar and use it on a crop." }, { "item_ivorypowder", "Ivory Powder" }, { "item_ivorypowder_description", "Bone, ground to a fine white powder. Binds bone glue into bone cement." }, { "atb_plant_mature", "This plant is already fully grown." }, { "atb_growth_maxed", "This plant is already growing as fast as it can." }, { "atb_no_plants_nearby", "There are no plants close enough." }, { "atb_treat_done", "This piece is already treated." }, { "atb_wrong_material", "That material cannot be treated with this." }, { "atb_growth_applied", "Bone Meal applied. Growth time reduced by $1% ($2/$3)." }, { "item_mealbag", "Meal Bag" }, { "item_mealbag_description", "A bag of ground bone. Boosts every plant around you at once. Put it on your hotbar and use it among your crops." }, { "atb_bag_applied", "Meal Bag applied to $1 plant(s). Growth time reduced by $2%." }, { "item_boneglue", "Bone Glue" }, { "item_boneglue_description", "Sticky bone glue. Treats wood and corewood so the rain no longer rots them. Each treated piece lets the structure above it carry one extra metre. Use it on a building piece from your hotbar." }, { "item_bonecement", "Bone Cement" }, { "item_bonecement_description", "Bone glue bound with ivory powder. Turns stone and iron pieces into stronger structures. Each treated piece lets the structure above it carry one extra metre. Use it on a building piece from your hotbar." }, { "atb_glue_applied", "Bone Glue applied. This piece now carries more weight above it." }, { "atb_cement_applied", "Bone Cement applied. This piece now carries more weight above it." } }); } private void AddItems() { BoneMeal.Add(); MealBag.Add(); BoneGlue.Add(); BoneCement.Add(); IvoryPowder.Add(); PrefabManager.OnVanillaPrefabsAvailable -= AddItems; } } } namespace AllTheBones.Utils { internal static class ItemRecolor { private class IconPixels { public Color32[] Pixels; public string Origin; } private const float ShadowFactor = 0.45f; private const float Contrast = 1.15f; private const int MinimumCoveragePercent = 2; private const float MinimumLuminance = 0.05f; private static readonly List<Object> KeepAlive = new List<Object>(); private static Texture2D whiteTexture; public static void Recolor(CustomItem item, Color tint) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) if (item == null || (Object)(object)item.ItemPrefab == (Object)null || (Object)(object)item.ItemDrop == (Object)null) { return; } DisableParticles(item.ItemPrefab); TintMaterials(item.ItemPrefab, tint); Sprite[] array = item.ItemDrop.m_itemData?.m_shared?.m_icons; if (array == null || array.Length == 0) { Logger.LogWarning((object)$"Custom item {item} has no icon to recolour"); return; } Sprite val = RecolorIcon(item.ItemPrefab, array[0], tint); if ((Object)(object)val == (Object)null) { Logger.LogWarning((object)("Keeping the vanilla icon of " + ((Object)item.ItemPrefab).name)); return; } item.ItemDrop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { val }; } public static Sprite RecolorIcon(GameObject prefab, Sprite sourceIcon, Color tint) { //IL_008a: 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) //IL_015b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null || (Object)(object)sourceIcon == (Object)null) { return null; } if ((Object)(object)sourceIcon.texture != (Object)null) { Texture2D texture = sourceIcon.texture; Logger.LogInfo((object)$"Icon source of {((Object)prefab).name}: '{((Object)texture).name}' {((Texture)texture).width}x{((Texture)texture).height}, readable {((Texture)texture).isReadable}, rect {sourceIcon.rect}, textureRect {sourceIcon.textureRect}"); } Sprite val = LoadShippedIcon(prefab, sourceIcon); if ((Object)(object)val != (Object)null) { return val; } IconPixels iconPixels = ReadPixels(sourceIcon); if (iconPixels != null) { Measure(iconPixels.Pixels, out var opaque, out var maxLuminance); Logger.LogInfo((object)$"Icon of {((Object)prefab).name}: {iconPixels.Origin} readback, {opaque}/{iconPixels.Pixels.Length} opaque, max luminance {maxLuminance:0.00}"); if (IsPlausible(iconPixels.Pixels, opaque, maxLuminance)) { Sprite val2 = CreateSprite(sourceIcon, TintPixels(iconPixels.Pixels, tint)); if ((Object)(object)val2 != (Object)null) { return val2; } } else { Logger.LogWarning((object)("Icon readback of " + ((Object)prefab).name + " via " + iconPixels.Origin + " looks empty, discarding it")); } } Sprite val3 = RenderIcon(prefab); if ((Object)(object)val3 != (Object)null) { Logger.LogWarning((object)("Rendered the icon of " + ((Object)prefab).name + " from its model")); return val3; } Logger.LogWarning((object)("Could not create an icon for " + ((Object)prefab).name)); return null; } private static IconPixels ReadPixels(Sprite source) { return ReadPixelsDirect(source) ?? ReadPixelsViaGpu(source); } private static IconPixels ReadPixelsDirect(Sprite source) { Texture2D texture = source.texture; if ((Object)(object)texture == (Object)null || !((Texture)texture).isReadable) { return null; } try { Color32[] array = CopyRegion(texture.GetPixels32(), ((Texture)texture).width, ((Texture)texture).height, source); return (array == null) ? null : new IconPixels { Pixels = array, Origin = "cpu" }; } catch (UnityException) { return null; } } private static IconPixels ReadPixelsViaGpu(Sprite source) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Expected O, but got Unknown //IL_00ed: Unknown result type (might be due to invalid IL or missing references) Texture2D texture = source.texture; if ((Object)(object)texture == (Object)null) { return null; } Rect val = SourceRegion(source); int num = Mathf.RoundToInt(((Rect)(ref val)).width); int num2 = Mathf.RoundToInt(((Rect)(ref val)).height); if (num <= 0 || num2 <= 0) { return null; } RenderTexture active = RenderTexture.active; RenderTexture val2 = null; try { val2 = RenderTexture.GetTemporary(num, num2, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(((Rect)(ref val)).width / (float)((Texture)texture).width, ((Rect)(ref val)).height / (float)((Texture)texture).height); Vector2 val4 = default(Vector2); ((Vector2)(ref val4))..ctor(((Rect)(ref val)).x / (float)((Texture)texture).width, ((Rect)(ref val)).y / (float)((Texture)texture).height); Graphics.Blit((Texture)(object)texture, val2, val3, val4); RenderTexture.active = val2; Texture2D val5 = new Texture2D(num, num2, (TextureFormat)4, false); val5.ReadPixels(new Rect(0f, 0f, (float)num, (float)num2), 0, 0); val5.Apply(); Color32[] pixels = val5.GetPixels32(); Object.Destroy((Object)(object)val5); return new IconPixels { Pixels = pixels, Origin = "gpu" }; } catch (Exception ex) { Logger.LogWarning((object)("Reading the icon texture of " + ((Object)source).name + " failed: " + ex.Message)); return null; } finally { RenderTexture.active = active; if ((Object)(object)val2 != (Object)null) { RenderTexture.ReleaseTemporary(val2); } } } private static Color32[] CopyRegion(Color32[] sourcePixels, int sourceWidth, int sourceHeight, Sprite source) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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) if (sourcePixels == null) { return null; } Rect val = SourceRegion(source); int num = Mathf.RoundToInt(((Rect)(ref val)).width); int num2 = Mathf.RoundToInt(((Rect)(ref val)).height); int num3 = Mathf.RoundToInt(((Rect)(ref val)).x); int num4 = Mathf.RoundToInt(((Rect)(ref val)).y); if (num <= 0 || num2 <= 0 || num3 < 0 || num4 < 0 || num3 + num > sourceWidth || num4 + num2 > sourceHeight) { return null; } Color32[] array = (Color32[])(object)new Color32[num * num2]; for (int i = 0; i < num2; i++) { int num5 = (num4 + i) * sourceWidth + num3; int num6 = i * num; for (int j = 0; j < num; j++) { array[num6 + j] = sourcePixels[num5 + j]; } } return array; } private static void Measure(Color32[] pixels, out int opaque, out float maxLuminance) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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) opaque = 0; maxLuminance = 0f; if (pixels == null) { return; } foreach (Color32 val in pixels) { if (val.a > 8) { opaque++; } float num = (0.299f * (float)(int)val.r + 0.587f * (float)(int)val.g + 0.114f * (float)(int)val.b) / 255f; if (num > maxLuminance) { maxLuminance = num; } } } private static bool IsPlausible(Color32[] pixels, int opaque, float maxLuminance) { if (pixels == null || pixels.Length == 0) { return false; } return opaque * 100 >= pixels.Length * 2 && maxLuminance >= 0.05f; } private static Color32[] TintPixels(Color32[] pixels, Color tint) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) Color32[] array = (Color32[])(object)new Color32[pixels.Length]; for (int i = 0; i < pixels.Length; i++) { Color32 val = pixels[i]; float num = (0.299f * (float)(int)val.r + 0.587f * (float)(int)val.g + 0.114f * (float)(int)val.b) / 255f; float num2 = Mathf.Clamp01(Mathf.Lerp(0.45f, 1f, num) * 1.15f); array[i] = new Color32((byte)(tint.r * num2 * 255f), (byte)(tint.g * num2 * 255f), (byte)(tint.b * num2 * 255f), val.a); } return array; } private static Sprite CreateSprite(Sprite source, Color32[] pixels) { //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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown //IL_00b7: 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) Texture2D texture = source.texture; Rect val = SourceRegion(source); int num = Mathf.RoundToInt(((Rect)(ref val)).width); int num2 = Mathf.RoundToInt(((Rect)(ref val)).height); if ((Object)(object)texture == (Object)null || pixels == null || pixels.Length != num * num2) { return null; } Texture2D val2 = new Texture2D(num, num2, (TextureFormat)4, false) { name = ((Object)texture).name + "_AllTheBones", filterMode = ((Texture)texture).filterMode, wrapMode = (TextureWrapMode)1 }; val2.SetPixels32(pixels); val2.Apply(); KeepAlive.Add((Object)(object)val2); Sprite val3 = Sprite.Create(val2, new Rect(0f, 0f, (float)num, (float)num2), GetPivot(source), source.pixelsPerUnit, 0u, (SpriteMeshType)0); KeepAlive.Add((Object)(object)val3); return val3; } private static Vector2 GetPivot(Sprite sprite) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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) //IL_0046: 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) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) Vector2 pivot = sprite.pivot; if (pivot.x > 1f || pivot.y > 1f) { float x = pivot.x; Rect rect = sprite.rect; float num = x / ((Rect)(ref rect)).width; float y = pivot.y; rect = sprite.rect; return new Vector2(num, y / ((Rect)(ref rect)).height); } return pivot; } private static Sprite RenderIcon(GameObject prefab) { try { return RenderManager.Instance.Render(prefab); } catch (Exception ex) { Logger.LogWarning((object)("Rendering an icon for " + ((Object)prefab).name + " failed: " + ex.Message)); return null; } } private static void TintMaterials(GameObject prefab, Color tint) { //IL_00cf: 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) Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { Material[] materials = val.materials; foreach (Material val2 in materials) { if ((Object)(object)val2 == (Object)null) { continue; } if (val2.HasProperty("_Saturation")) { if (val2.HasProperty("_Hue")) { val2.SetFloat("_Hue", 0f); } val2.SetFloat("_Saturation", -1f); } else if (val2.HasProperty("_MainTex")) { val2.SetTexture("_MainTex", (Texture)(object)WhiteTexture()); } if (val2.HasProperty("_Color")) { val2.SetColor("_Color", tint); } else if (val2.HasProperty("_BaseColor")) { val2.SetColor("_BaseColor", tint); } } } } public static void DisableParticles(GameObject prefab) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) ParticleSystem[] componentsInChildren = prefab.GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem val in componentsInChildren) { if ((Object)(object)((Component)val).gameObject == (Object)(object)prefab) { Logger.LogInfo((object)("Switching off the root particle system of " + ((Object)prefab).name)); EmissionModule emission = val.emission; ((EmissionModule)(ref emission)).enabled = false; val.Stop(true, (ParticleSystemStopBehavior)0); ParticleSystemRenderer component = ((Component)val).GetComponent<ParticleSystemRenderer>(); if ((Object)(object)component != (Object)null) { ((Renderer)component).enabled = false; } } else { Logger.LogInfo((object)("Disabling the particle system '" + ((Object)((Component)val).gameObject).name + "' of " + ((Object)prefab).name)); ((Component)val).gameObject.SetActive(false); } } } private static Rect SourceRegion(Sprite sprite) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) Rect textureRect = sprite.textureRect; if (((Rect)(ref textureRect)).width > 0f && ((Rect)(ref textureRect)).height > 0f) { return textureRect; } return sprite.rect; } private static Sprite LoadShippedIcon(GameObject prefab, Sprite sourceIcon) { //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Expected O, but got Unknown //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) string text = FindIconFile(((Object)prefab).name); if (text == null) { return null; } try { byte[] array = File.ReadAllBytes(text); if (array.Length != 16384) { Logger.LogWarning((object)$"Shipped icon {text} has {array.Length} bytes, expected {16384}"); return null; } Color32[] array2 = (Color32[])(object)new Color32[4096]; for (int i = 0; i < array2.Length; i++) { array2[i] = new Color32(array[i * 4], array[i * 4 + 1], array[i * 4 + 2], array[i * 4 + 3]); } Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false) { name = ((Object)prefab).name + "_AllTheBones", wrapMode = (TextureWrapMode)1 }; if ((Object)(object)sourceIcon != (Object)null && (Object)(object)sourceIcon.texture != (Object)null) { ((Texture)val).filterMode = ((Texture)sourceIcon.texture).filterMode; } val.SetPixels32(array2); val.Apply(); Measure(array2, out var opaque, out var maxLuminance); Logger.LogInfo((object)$"Shipped icon of {((Object)prefab).name}: {((Texture)val).width}x{((Texture)val).height}, {opaque}/{array2.Length} opaque, max luminance {maxLuminance:0.00}"); if (!IsPlausible(array2, opaque, maxLuminance)) { Logger.LogWarning((object)("Shipped icon " + text + " looks empty, ignoring it")); return null; } KeepAlive.Add((Object)(object)val); float num = (((Object)(object)sourceIcon != (Object)null) ? sourceIcon.pixelsPerUnit : 100f); Vector2 val2 = (Vector2)(((Object)(object)sourceIcon != (Object)null) ? GetPivot(sourceIcon) : new Vector2(0.5f, 0.5f)); Sprite val3 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), val2, num, 0u, (SpriteMeshType)0); KeepAlive.Add((Object)(object)val3); return val3; } catch (Exception ex) { Logger.LogWarning((object)("Loading the shipped icon " + text + " failed: " + ex.Message)); return null; } } private static string FindIconFile(string prefabId) { foreach (string item in IconDirectories()) { string text = Path.Combine(item, prefabId + ".bin"); if (File.Exists(text)) { return text; } } return null; } private static IEnumerable<string> IconDirectories() { string assemblyDirectory; try { assemblyDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); } catch (Exception) { assemblyDirectory = null; } if (!string.IsNullOrEmpty(assemblyDirectory)) { yield return Path.Combine(assemblyDirectory, "AllTheBones", "icons"); } if (!string.IsNullOrEmpty(Paths.PluginPath)) { yield return Path.Combine(Paths.PluginPath, "AllTheBones", "icons"); } } private static Texture2D WhiteTexture() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)whiteTexture != (Object)null) { return whiteTexture; } whiteTexture = new Texture2D(1, 1, (TextureFormat)4, false) { name = "AllTheBones_White", filterMode = (FilterMode)0, wrapMode = (TextureWrapMode)1 }; whiteTexture.SetPixels32((Color32[])(object)new Color32[1] { new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue) }); whiteTexture.Apply(); KeepAlive.Add((Object)(object)whiteTexture); return whiteTexture; } } } namespace AllTheBones.Systems { internal static class BoostedPlantTint { private const float UpdateInterval = 1f; private static readonly List<Plant> loaded = new List<Plant>(); private static readonly Dictionary<Material, Material> tintCache = new Dictionary<Material, Material>(); private static readonly HashSet<Material> tintedMaterials = new HashSet<Material>(); private static float nextUpdate; public static void Register(Plant plant) { if ((Object)(object)plant != (Object)null) { loaded.Add(plant); } } public static void Mark(ZNetView nview) { Apply(((Object)(object)nview != (Object)null) ? ((Component)nview).GetComponent<Plant>() : null); } public static void Tick() { if (Time.realtimeSinceStartup < nextUpdate) { return; } nextUpdate = Time.realtimeSinceStartup + 1f; for (int num = loaded.Count - 1; num >= 0; num--) { Plant val = loaded[num]; if ((Object)(object)val == (Object)null) { loaded.RemoveAt(num); } else if (GrowthBoostStore.GetStacks(val.m_nview) > 0) { Apply(val); } } } private static void Apply(Plant plant) { if ((Object)(object)plant == (Object)null) { return; } Renderer[] componentsInChildren = ((Component)plant).GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.sharedMaterial == (Object)null) && !tintedMaterials.Contains(val.sharedMaterial)) { Material val2 = Tinted(val.sharedMaterial); if ((Object)(object)val2 != (Object)null) { val.sharedMaterial = val2; } } } } private static Material Tinted(Material source) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) if (tintCache.TryGetValue(source, out var value)) { return value; } Material val = null; if (source.HasProperty("_Color")) { val = new Material(source) { name = ((Object)source).name + " (boosted)" }; Color color = source.GetColor("_Color"); val.SetColor("_Color", Color.Lerp(color, Constants.PlantTint, 0.45f)); tintedMaterials.Add(val); } tintCache[source] = val; return val; } } internal sealed class Counter { public readonly string Name; public long Calls; public long Ticks; public long WorstTicks; public long Flagged; public Counter(string name) { Name = name; } public void Reset() { Calls = 0L; Ticks = 0L; WorstTicks = 0L; Flagged = 0L; } } internal static class Diagnostics { public static bool Enabled; public static readonly Counter GetSupport = new Counter("GetSupportPostfix"); public static readonly Counter UpdateWear = new Counter("UpdateWearPrefix"); public static readonly Counter ZdoRead = new Counter("TreatmentStoreRead"); public static readonly Counter GrowTime = new Counter("GetGrowTimePostfix"); public static readonly Counter UseItem = new Counter("UseItemPrefix"); public static readonly Counter VanillaUpdateWear = new Counter("vanillaUpdateWear"); public static readonly Counter VanillaUpdateSupport = new Counter("vanillaUpdateSupport"); public static readonly Counter VanillaClearCacheRpc = new Counter("vanillaClearCacheRpc"); private static readonly Counter[] All = new Counter[8] { GetSupport, UpdateWear, ZdoRead, GrowTime, UseItem, VanillaUpdateWear, VanillaUpdateSupport, VanillaClearCacheRpc }; private static float nextReport; private static float nextScaleReport; private static int framesOver50; private static int framesOver100; private static int framesOver200; private static float worstFrame; private static int lastGc0; private static int lastGc1; private static int lastGc2; public static long Begin() { return Enabled ? Stopwatch.GetTimestamp() : 0; } public static void End(Counter counter, long startedAt, bool flagged = false) { if (startedAt != 0L && counter != null) { long num = Stopwatch.GetTimestamp() - startedAt; counter.Calls++; counter.Ticks += num; if (num > counter.WorstTicks) { counter.WorstTicks = num; } if (flagged) { counter.Flagged++; } } } public static void Count(Counter counter) { if (Enabled && counter != null) { counter.Calls++; } } public static void Tick() { if (Enabled) { float realtimeSinceStartup = Time.realtimeSinceStartup; float unscaledDeltaTime = Time.unscaledDeltaTime; if (unscaledDeltaTime > worstFrame) { worstFrame = unscaledDeltaTime; } if (unscaledDeltaTime > 0.05f) { framesOver50++; } if (unscaledDeltaTime > 0.1f) { framesOver100++; } if (unscaledDeltaTime > 0.2f) { framesOver200++; } if (realtimeSinceStartup >= nextReport) { nextReport = realtimeSinceStartup + 1f; ReportInterval(); } if (realtimeSinceStartup >= nextScaleReport) { nextScaleReport = realtimeSinceStartup + 10f; ReportScale(); } } } private static void ReportInterval() { Counter[] all = All; foreach (Counter counter in all) { if (counter.Calls > 0) { Logger.LogInfo((object)$"[ATB-DIAG] {counter.Name} calls={counter.Calls} time={Ms(counter.Ticks):0.00}ms worst={Ms(counter.WorstTicks):0.00}ms flagged={counter.Flagged}"); counter.Reset(); } } int num = GC.CollectionCount(0); int num2 = GC.CollectionCount(1); int num3 = GC.CollectionCount(2); Logger.LogInfo((object)$"[ATB-DIAG] frames>50ms={framesOver50} >100ms={framesOver100} >200ms={framesOver200} worstFrame={worstFrame * 1000f:0}ms gc0=+{num - lastGc0} gc1=+{num2 - lastGc1} gc2=+{num3 - lastGc2} managed={GC.GetTotalMemory(forceFullCollection: false) / 1024 / 1024}MB"); framesOver50 = 0; framesOver100 = 0; framesOver200 = 0; worstFrame = 0f; lastGc0 = num; lastGc1 = num2; lastGc2 = num3; } private static void ReportScale() { List<WearNTear> allInstances = WearNTear.GetAllInstances(); if (allInstances == null) { return; } int num = 0; foreach (WearNTear item in allInstances) { if ((Object)(object)item != (Object)null && TreatmentStore.IsTreated(item.m_nview)) { num++; } } Logger.LogInfo((object)$"[ATB-DIAG] scale pieces={allInstances.Count} treated={num}"); } private static double Ms(long ticks) { return (double)ticks * 1000.0 / (double)Stopwatch.Frequency; } } internal enum GrowthApplyResult { Applied, OtherSource, AtMaximum } internal static class GrowthBoostStore { public static int GetStacks(ZNetView nview) { return Read(nview, Constants.GrowthCountHash); } public static int GetSource(ZNetView nview) { return Read(nview, Constants.GrowthSourceHash); } public static bool IsMature(Plant plant) { return (Object)(object)plant != (Object)null && plant.TimeSincePlanted() >= (double)plant.GetGrowTime(); } public static GrowthApplyResult TryApply(ZNetView nview, int source) { int stacks = GetStacks(nview); int source2 = GetSource(nview); if (stacks > 0) { if (source2 != source) { return GrowthApplyResult.OtherSource; } if (source == 2 || stacks >= 5) { return GrowthApplyResult.AtMaximum; } } nview.ClaimOwnership(); ZDO zDO = nview.GetZDO(); zDO.Set(Constants.GrowthSourceHash, source, false); zDO.Set(Constants.GrowthCountHash, stacks + 1, false); BoostedPlantTint.Mark(nview); return GrowthApplyResult.Applied; } public static float GetGrowTimeMultiplier(ZNetView nview) { int stacks = GetStacks(nview); if (stacks <= 0) { return 1f; } float num = ((GetSource(nview) == 2) ? 0.8f : 0.8f); return Mathf.Pow(num, (float)stacks); } private static int Read(ZNetView nview, int hash) { if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return 0; } return nview.GetZDO().GetInt(hash, 0); } } internal class MealBagRadiusIndicator : MonoBehaviour { private const float UpdateInterval = 0.25f; private const int Segments = 64; private const float HeightAboveGround = 0.06f; private static MealBagRadiusIndicator instance; private LineRenderer line; private float nextUpdate; public static void EnsureExists() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown if (!((Object)(object)instance != (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null)) { GameObject val = new GameObject("AllTheBones_MealBagRadius"); Object.DontDestroyOnLoad((Object)(object)val); instance = val.AddComponent<MealBagRadiusIndicator>(); instance.Build(); } } private void Build() { //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) Material val = CreateMaterial(); if ((Object)(object)val == (Object)null) { Logger.LogWarning((object)"No usable shader for the Meal Bag radius ring, skipping it"); Object.Destroy((Object)(object)((Component)this).gameObject); instance = null; return; } line = ((Component)this).gameObject.AddComponent<LineRenderer>(); line.useWorldSpace = false; line.loop = true; line.positionCount = 64; line.widthMultiplier = 0.05f; line.numCapVertices = 0; line.numCornerVertices = 0; line.alignment = (LineAlignment)0; ((Renderer)line).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)line).receiveShadows = false; ((Renderer)line).material = val; line.startColor = val.color; line.endColor = val.color; for (int i = 0; i < 64; i++) { float num = (float)i / 64f * (float)Math.PI * 2f; line.SetPosition(i, new Vector3(Mathf.Cos(num), Mathf.Sin(num), 0f) * 3f); } ((Component)this).transform.rotation = Quaternion.Euler(90f, 0f, 0f); ((Component)this).gameObject.SetActive(false); Logger.LogInfo((object)"Meal Bag radius ring created"); } private void Update() { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: 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) if (Time.realtimeSinceStartup < nextUpdate) { return; } nextUpdate = Time.realtimeSinceStartup + 0.25f; Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || !HasMealBagInHotbar(localPlayer)) { if (((Component)this).gameObject.activeSelf) { ((Component)this).gameObject.SetActive(false); } return; } Vector3 position = ((Component)localPlayer).transform.position; float num = (((Object)(object)ZoneSystem.instance != (Object)null) ? ZoneSystem.instance.GetGroundHeight(position) : position.y); ((Component)this).transform.position = new Vector3(position.x, num + 0.06f, position.z); if (!((Component)this).gameObject.activeSelf) { ((Component)this).gameObject.SetActive(true); } } private static bool HasMealBagInHotbar(Player player) { Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory == null) { return false; } for (int i = 0; i < 8; i++) { ItemData itemAt = inventory.GetItemAt(i, 0); if (itemAt != null && itemAt.m_shared != null && itemAt.m_shared.m_name == "$item_mealbag") { return true; } } return false; } private static Material CreateMaterial() { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown //IL_00a6: Unknown result type (might be due to invalid IL or missing references) Color color = default(Color); ((Color)(ref color))..ctor(1f, 0.97f, 0.9f, 0.4f); string[] array = new string[3] { "Sprites/Default", "UI/Default", "Particles/Standard Unlit" }; string[] array2 = array; foreach (string text in array2) { Shader val = Shader.Find(text); if ((Object)(object)val != (Object)null) { Material val2 = new Material(val); val2.color = color; return val2; } } Material val3 = FindWardMarkerMaterial(); if ((Object)(object)val3 != (Object)null) { Material val4 = new Material(val3); val4.color = color; return val4; } return null; } private static Material FindWardMarkerMaterial() { GameObject prefab = PrefabManager.Instance.GetPrefab("guard_stone"); if ((Object)(object)prefab == (Object)null) { return null; } Transform val = prefab.transform.Find("marker"); if ((Object)(object)val == (Object)null) { return null; } ParticleSystemRenderer component = ((Component)val).GetComponent<ParticleSystemRenderer>(); return ((Object)(object)component != (Object)null) ? ((Renderer)component).sharedMaterial : null; } } internal static class PlantedCrops { private static HashSet<string> grownPrefabs; private static bool scanned; public static bool IsGrownCrop(GameObject aimed) { if ((Object)(object)aimed == (Object)null) { return false; } Pickable componentInParent = aimed.GetComponentInParent<Pickable>(); if ((Object)(object)componentInParent == (Object)null) { return false; } return GetGrownPrefabs()?.Contains(((Object)((Component)componentInParent).gameObject).name) ?? false; } private static HashSet<string> GetGrownPrefabs() { if (scanned) { return grownPrefabs; } ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null) { return null; } grownPrefabs = new HashSet<string>(); foreach (GameObject prefab in instance.m_prefabs) { if ((Object)(object)prefab == (Object)null) { continue; } Plant component = prefab.GetComponent<Plant>(); if ((Object)(object)component == (Object)null || component.m_grownPrefabs == null) { continue; } GameObject[] array = component.m_grownPrefabs; foreach (GameObject val in array) { if ((Object)(object)val != (Object)null) { grownPrefabs.Add(((Object)val).name); } } } scanned = true; Logger.LogInfo((object)$"Tracked {grownPrefabs.Count} grown plant prefabs"); return grownPrefabs; } } internal static class TargetResolver { private const float RayLength = 50f; private static readonly RaycastHit[] Hits = (RaycastHit[])(object)new RaycastHit[16]; private static readonly Collider[] Colliders = (Collider[])(object)new Collider[64]; public static Plant FindAimedPlant(Player player) { GameObject hoverObject = ((Humanoid)player).GetHoverObject(); if ((Object)(object)hoverObject != (Object)null) { Plant componentInParent = hoverObject.GetComponentInParent<Plant>(); if ((Object)(object)componentInParent != (Object)null) { return componentInParent; } } return FindAimed<Plant>(player, player.m_interactMask); } public static WearNTear FindAimedWearNTear(Player player) { WearNTear val = FindAimed<WearNTear>(player, player.m_removeRayMask); if ((Object)(object)val != (Object)null) { return val; } GameObject hoverObject = ((Humanoid)player).GetHoverObject(); if ((Object)(object)hoverObject != (Object)null) { WearNTear componentInParent = hoverObject.GetComponentInParent<WearNTear>(); if ((Object)(object)componentInParent != (Object)null) { return componentInParent; } } return FindAimed<WearNTear>(player, player.m_interactMask); } public static List<Plant> FindPlantsAround(Player player, float radius) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) List<Plant> list = new List<Plant>(); if ((Object)(object)player == (Object)null) { return list; } Vector3 position = ((Component)player).transform.position; int num = Physics.OverlapSphereNonAlloc(position, radius, Colliders, -1, (QueryTriggerInteraction)1); for (int i = 0; i < num; i++) { Collider val = Colliders[i]; if (!((Object)(object)val == (Object)null)) { Plant componentInParent = ((Component)val).GetComponentInParent<Plant>(); if (!((Object)(object)componentInParent == (Object)null) && !list.Contains(componentInParent) && !(Vector3.Distance(((Component)componentInParent).transform.position, position) > radius)) { list.Add(componentInParent); } } } return list; } public static GameObject FindAimedObject(Player player) { //IL_005c: 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_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) GameObject hoverObject = ((Humanoid)player).GetHoverObject(); if ((Object)(object)hoverObject != (Object)null) { return hoverObject; } GameCamera instance = GameCamera.instance; if ((Object)(object)player == (Object)null || (Object)(object)instance == (Object)null || (Object)(object)((Character)player).m_eye == (Object)null) { return null; } Transform transform = ((Component)instance).transform; int num = Physics.RaycastNonAlloc(transform.position, transform.forward, Hits, 50f, -1, (QueryTriggerInteraction)1); float num2 = Mathf.Max(player.m_maxInteractDistance, player.m_maxPlaceDistance); float num3 = float.MaxValue; GameObject result = null; for (int i = 0; i < num; i++) { RaycastHit val = Hits[i]; if (!((Object)(object)((RaycastHit)(ref val)).collider == (Object)null) && !((Object)(object)((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Player>() != (Object)null) && !((Object)(object)((Component)((RaycastHit)(ref val)).collider).GetComponent<Heightmap>() != (Object)null) && !(Vector3.Distance(((RaycastHit)(ref val)).point, ((Character)player).m_eye.position) > num2) && !(((RaycastHit)(ref val)).distance >= num3)) { num3 = ((RaycastHit)(ref val)).distance; result = ((Component)((RaycastHit)(ref val)).collider).gameObject; } } return result; } private static T FindAimed<T>(Player player, int mask) where T : Component { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: 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) GameCamera instance = GameCamera.instance; if ((Object)(object)player == (Object)null || (Object)(object)instance == (Object)null || (Object)(object)((Character)player).m_eye == (Object)null) { return default(T); } Transform transform = ((Component)instance).transform; int num = Physics.RaycastNonAlloc(transform.position, transform.forward, Hits, 50f, mask); float num2 = Mathf.Max(player.m_maxInteractDistance, player.m_maxPlaceDistance); T result = default(T); float num3 = float.MaxValue; for (int i = 0; i < num; i++) { RaycastHit val = Hits[i]; if (!((Object)(object)((RaycastHit)(ref val)).collider == (Object)null) && !(Vector3.Distance(((RaycastHit)(ref val)).point, ((Character)player).m_eye.position) > num2)) { T componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<T>(); if (!((Object)(object)componentInParent == (Object)null) && !(((RaycastHit)(ref val)).distance >= num3)) { result = componentInParent; num3 = ((RaycastHit)(ref val)).distance; } } } return result; } } internal enum TreatmentApplyResult { Applied, AlreadyTreated } internal static class TreatmentStore { public static int GetTreatments(ZNetView nview) { long startedAt = Diagnostics.Begin(); try { if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return 0; } return nview.GetZDO().GetInt(Constants.TreatmentCountHash, 0); } finally { Diagnostics.End(Diagnostics.ZdoRead, startedAt); } } public static bool IsTreated(ZNetView nview) { return GetTreatments(nview) > 0; } public static bool MatchesGlueMaterial(WearNTear wearNTear) { return HasMaterial(wearNTear, (MaterialType)0, (MaterialType)3); } public static bool MatchesCementMaterial(WearNTear wearNTear) { return HasMaterial(wearNTear, (MaterialType)1, (MaterialType)2); } public static bool IsTreatableStructure(WearNTear wearNTear) { if ((Object)(object)wearNTear == (Object)null) { return false; } return IsStructure(wearNTear) && !IsStorageOrStation(wearNTear); } public static TreatmentApplyResult TryApply(ZNetView nview) { if (IsTreated(nview)) { return TreatmentApplyResult.AlreadyTreated; } nview.ClaimOwnership(); nview.GetZDO().Set(Constants.TreatmentCountHash, 1, false); return TreatmentApplyResult.Applied; } public static float GetSupportMultiplier(ZNetView nview, float verticalLoss) { if (!IsTreated(nview) || verticalLoss >= 1f || verticalLoss < 0f) { return 1f; } return 1f / (1f - verticalLoss); } public static float GetHeightAboveGround(WearNTear wearNTear) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)wearNTear == (Object)null || (Object)(object)ZoneSystem.instance == (Object)null) { return 0f; } Vector3 position = ((Component)wearNTear).transform.position; return position.y - ZoneSystem.instance.GetGroundHeight(position); } private static bool HasMaterial(WearNTear wearNTear, MaterialType first, MaterialType second) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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) if ((Object)(object)wearNTear == (Object)null) { return false; } MaterialType materialType = wearNTear.m_materialType; return materialType == first || materialType == second; } private static bool IsStructure(WearNTear wearNTear) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected I4, but got Unknown Piece piece = wearNTear.m_piece; if ((Object)(object)piece == (Object)null) { return true; } PieceCategory category = piece.m_category; PieceCategory val = category; switch ((int)val) { case 0: case 1: case 4: case 6: case 7: case 8: return false; default: return true; } } private static bool IsStorageOrStation(WearNTear wearNTear) { return HasComponent<Container>(wearNTear) || HasComponent<CraftingStation>(wearNTear) || HasComponent<StationExtension>(wearNTear) || HasComponent<Smelter>(wearNTear) || HasComponent<Fermenter>(wearNTear) || HasComponent<CookingStation>(wearNTear) || HasComponent<Beehive>(wearNTear) || HasComponent<ItemStand>(wearNTear) || HasComponent<Incinerator>(wearNTear) || HasComponent<Feast>(wearNTear) || HasComponent<TeleportWorld>(wearNTear); } private static bool HasComponent<T>(WearNTear wearNTear) where T : Component { return (Object)(object)((Component)wearNTear).GetComponentInParent<T>() != (Object)null || (Object)(object)((Component)wearNTear).GetComponentInChildren<T>(true) != (Object)null; } } } namespace AllTheBones.Patches { [HarmonyPatch(typeof(Plant), "GetGrowTime")] internal static class PlantGrowthPatches { private static void Postfix(Plant __instance, ref float __result) { long startedAt = Diagnostics.Begin(); bool flagged = false; try { if (!((Object)(object)__instance == (Object)null)) { float growTimeMultiplier = GrowthBoostStore.GetGrowTimeMultiplier(__instance.m_nview); if (growTimeMultiplier < 1f) { flagged = true; __result *= growTimeMultiplier; } } } finally { Diagnostics.End(Diagnostics.GrowTime, startedAt, flagged); } } } [HarmonyPatch(typeof(Plant), "Awake")] internal static class PlantAwakePatches { private static void Postfix(Plant __instance) { BoostedPlantTint.Register(__instance); } } [HarmonyPatch(typeof(WearNTear), "GetSupport")] internal static class StabilityBoostPatch { private static void Postfix(WearNTear __instance, ref float __result) { long startedAt = Diagnostics.Begin(); bool flagged = false; try { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsValid() && TreatmentStore.GetTreatments(__instance.m_nview) > 0) { flagged = true; float num = default(float); float num2 = default(float); float num3 = default(float); float verticalLoss = default(float); __instance.GetMaterialProperties(ref num, ref num2, ref num3, ref verticalLoss); float supportMultiplier = TreatmentStore.GetSupportMultiplier(__instance.m_nview, verticalLoss); if (supportMultiplier > 1f) { __result *= supportMultiplier; } } } finally { Diagnostics.End(Diagnostics.GetSupport, startedAt, flagged); } } } [HarmonyPatch(typeof(WearNTear), "UpdateWear")] internal static class WeatherImmunityPatch { private static void Prefix(WearNTear __instance) { long startedAt = Diagnostics.Begin(); bool flagged = false; try { if (!((Object)(object)__instance == (Object)null) && __instance.m_noRoofWear && !((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsValid() && TreatmentStore.GetTreatments(__instance.m_nview) > 0) { flagged = true; __instance.m_noRoofWear = false; } } finally { Diagnostics.End(Diagnostics.UpdateWear, startedAt, flagged); } } } [HarmonyPatch(typeof(Humanoid), "UseItem")] internal static class UseItemPatches { private enum ItemKind { None, BoneMeal, MealBag, BoneGlue, BoneCement } private static readonly HashSet<ItemKind> HintShown = new HashSet<ItemKind>(); private static bool Prefix(Humanoid __instance, Inventory inventory, ItemData item, bool fromInventoryGui) { ItemKind itemKind = GetItemKind(item); if (itemKind != ItemKind.None) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null) { if (inventory == null) { inventory = ((Humanoid)val).GetInventory(); } if (inventory == null) { return false; } ShowFirstUseHint(val, itemKind); long startedAt = Diagnostics.Begin(); try { return itemKind switch { ItemKind.BoneMeal => UseOnPlant(val, inventory, item), ItemKind.MealBag => UseMealBag(val, inventory, item), ItemKind.BoneGlue => UseOnPiece(val, inventory, item, glue: true), ItemKind.BoneCement => UseOnPiece(val, inventory, item, glue: false), _ => true, }; } finally { Diagnostics.End(Diagnostics.UseItem, startedAt, flagged: true); } } } return true; } private static ItemKind GetItemKind(ItemData item) { string text = item?.m_shared?.m_name; if (text == null) { return ItemKind.None; } return text switch { "$item_bonemeal" => ItemKind.BoneMeal, "$item_mealbag" => ItemKind.MealBag, "$item_boneglue" => ItemKind.BoneGlue, "$item_bonecement" => ItemKind.BoneCement, _ => ItemKind.None, }; } private static bool UseOnPlant(Player player, Inventory inventory, ItemData item) { Plant val = TargetResolver.FindAimedPlant(player); if ((Object)(object)val == (Object)null) { return RejectWithoutTarget(player, item); } if (!IsUsable((Component)(object)val, val.m_nview)) { return RejectTarget(player, item, (Component)(object)val); } if (GrowthBoostStore.IsMature(val)) { ShowMessage(player, "$atb_plant_mature"); return false; } switch (GrowthBoostStore.TryApply(val.m_nview, 1)) { case GrowthApplyResult.Applied: ShowGrowthApplied(player, val); inventory.RemoveOneItem(item); return false; case GrowthApplyResult.OtherSource: case GrowthApplyResult.AtMaximum: ShowMessage(player, "$atb_growth_maxed"); return false; default: return RejectTarget(player, item, (Component)(object)val); } } private static bool UseMealBag(Player player, Inventory inventory, ItemData item) { List<Plant> list = TargetResolver.FindPlantsAround(player, 3f); if (list.Count == 0) { ShowMessage(player, "$atb_no_plants_nearby"); return false; } int num = 0; int num2 = 0; foreach (Plant item2 in list) { if (IsUsable((Component)(object)item2, item2.m_nview)) { if (GrowthBoostStore.IsMature(item2)) { num2++; } else if (GrowthBoostStore.TryApply(item2.m_nview, 2) == GrowthApplyResult.Applied) { num++; } } } if (num == 0) { ShowMessage(player, (num2 > 0) ? "$atb_plant_mature" : "$atb_growth_maxed"); return false; } ShowBagApplied(player, num); inventory.RemoveOneItem(item); return false; } private static bool UseOnPiece(Player player, Inventory inventory, ItemData item, bool glue) { WearNTear val = TargetResolver.FindAimedWearNTear(player); if ((Object)(object)val == (Object)null) { return RejectWithoutTarget(player, item); } if (!IsUsable((Component)(object)val, val.m_nview)) { return RejectTarget(player, item, (Component)(object)val); } if (!(glue ? TreatmentStore.MatchesGlueMaterial(val) : TreatmentStore.MatchesCementMaterial(val))) { ShowMessage(player, "$atb_wrong_material"); return false; } if (!glue) { } if (!TreatmentStore.IsTreatableStructure(val)) { return RejectTarget(player, item, (Component)(object)val); } if (TreatmentStore.TryApply(val.m_nview) == TreatmentApplyResult.AlreadyTreated) { ShowMessage(player, "$atb_treat_done"); return false; } val.ClearCachedSupport(); ShowTreatmentApplied(player, val, glue); inventory.RemoveOneItem(item); return false; } private static void ShowGrowthApplied(Player player, Plant plant) { int stacks = GrowthBoostStore.GetStacks(plant.m_nview); int num = Mathf.RoundToInt(19.999998f); ShowMessage(player, "$atb_growth_applied", num.ToString(), stacks.ToString(), 5.ToString()); } private static void ShowBagApplied(Player player, int plants) { int num = Mathf.RoundToInt(19.999998f); ShowMessage(player, "$atb_bag_applied", plants.ToString(), num.ToString()); } private static void ShowFirstUseHint(Player player, ItemKind kind) { if (HintShown.Add(kind)) { switch (kind) { case ItemKind.BoneMeal: ShowMessage(player, "$atb_hint_bonemeal"); break; case ItemKind.MealBag: ShowMessage(player, "$atb_hint_mealbag"); break; case ItemKind.BoneGlue: ShowMessage(player, "$atb_hint_boneglue"); break; case ItemKind.BoneCement: ShowMessage(player, "$atb_hint_bonecement"); break; } } } private static void ShowTreatmentApplied(Player player, WearNTear wearNTear, bool glue) { Logger.LogInfo((object)string.Format("Treated {0} with {1} at {2:0.0} m above ground", ((Object)((Component)wearNTear).gameObject).name, glue ? "Bone Glue" : "Bone Cement", TreatmentStore.GetHeightAboveGround(wearNTear))); ShowMessage(player, glue ? "$atb_glue_applied" : "$atb_cement_applied"); } private static bool IsUsable(Component target, ZNetView nview) { return (Object)(object)target != (Object)null && (Object)(object)nview != (Object)null && nview.IsValid(); } private static bool RejectWithoutTarget(Player player, ItemData item) { GameObject val = TargetResolver.FindAimedObject(player); string text = Localization.instance.Localize(item.m_shared.m_name); if ((Object)(object)val == (Object)null) { ShowMessage(player, "$msg_useonwhat", text); return false; } if (PlantedCrops.IsGrownCrop(val)) { ShowMessage(player, "$atb_plant_mature"); return false; } ShowMessage(player, "$msg_cantuseon", text, GetTargetName(val)); return false; } private static bool RejectTarget(Player player, ItemData item, Component target) { ShowMessage(player, "$msg_cantuseon", Localization.instance.Localize(item.m_shared.m_name), GetTargetName(target.gameObject)); return false; } private static string GetTargetName(GameObject target) { if ((Object)(object)target == (Object)null) { return string.Empty; } Plant componentInParent = target.GetComponentInParent<Plant>(); if ((Object)(object)componentInParent != (Object)null && !string.IsNullOrEmpty(componentInParent.m_name)) { return Localization.instance.Localize(componentInParent.m_name); } WearNTear componentInParent2 = target.GetComponentInParent<WearNTear>(); if ((Object)(object)componentInParent2 != (Object)null && (Object)(object)componentInParent2.m_piece != (Object)null && !string.IsNullOrEmpty(componentInParent2.m_piece.m_name)) { return Localization.instance.Localize(componentInParent2.m_piece.m_name); } return ((Object)target).name; } private static void ShowMessage(Player player, string token, params string[] arguments) { string text = ((arguments == null || arguments.Length == 0) ? Localization.instance.Localize(token) : Localization.instance.Localize(token, arguments)); ((Character)player).Message((MessageType)1, text, 0, (Sprite)null, false); } } [HarmonyPatch(typeof(WearNTear), "UpdateWear")] internal static class UpdateWearProbe { private static void Prefix(out long __state) { __state = Diagnostics.Begin(); } private static void Postfix(long __state) { Diagnostics.End(Diagnostics.VanillaUpdateWear, __state); } } [HarmonyPatch(typeof(WearNTear), "UpdateSupport")] internal static class UpdateSupportProbe { private static void Prefix(out long __state) { __state = Diagnostics.Begin(); } private static void Postfix(long __state) { Diagnostics.End(Diagnostics.VanillaUpdateSupport, __state); } } [HarmonyPatch(typeof(WearNTear), "RPC_ClearCachedSupport")] internal static class ClearCacheProbe { private static void Postfix() { Diagnostics.Count(Diagnostics.VanillaClearCacheRpc); } } } namespace AllTheBones.Items { internal static class BoneCement { public static void Add() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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_0066: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_00a4: Unknown result type (might be due to invalid IL or missing references) ItemConfig val = new ItemConfig(); val.Name = "$item_bonecement"; val.Description = "$item_bonecement_description"; val.CraftingStation = CraftingStations.Cauldron; val.MinStationLevel = 1; val.Amount = 1; val.Requirements = (RequirementConfig[])(object)new RequirementConfig[2] { new RequirementConfig { Item = "BoneGlue", Amount = 1, Recover = false }, new RequirementConfig { Item = "IvoryPowder", Amount = 1, Recover = false } }; ItemConfig val2 = val; CustomItem val3 = new CustomItem("BoneCement", "Guck", val2); ItemRecolor.Recolor(val3, Constants.CementGray); ItemManager.Instance.AddItem(val3); Logger.LogInfo((object)"Bone Cement has been added to the game"); } } internal static class BoneGlue { public static void Add() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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_0066: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_00a4: Unknown result type (might be due to invalid IL or missing references) ItemConfig val = new ItemConfig(); val.Name = "$item_boneglue"; val.Description = "$item_boneglue_description"; val.CraftingStation = CraftingStations.Workbench; val.MinStationLevel = 1; val.Amount = 1; val.Requirements = (RequirementConfig[])(object)new RequirementConfig[2] { new RequirementConfig { Item = "Resin", Amount = 1, Recover = false }, new RequirementConfig { Item = "BoneMeal", Amount = 1, Recover = false } }; ItemConfig val2 = val; CustomItem val3 = new CustomItem("BoneGlue", "Guck", val2); ItemRecolor.Recolor(val3, Constants.ChalkWhite); ItemManager.Instance.AddItem(val3); Logger.LogInfo((object)"Bone Glue has been added to the game"); } } internal static class BoneMeal { public static void Add() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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_0066: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0080: Unknown result type (might be due to invalid IL or missing references) ItemConfig val = new ItemConfig(); val.Name = "$item_bonemeal"; val.Description = "$item_bonemeal_description"; val.CraftingStation = CraftingStations.Cauldron; val.MinStationLevel = 1; val.Amount = 1; val.Requirements = (RequirementConfig[])(object)new RequirementConfig[1] { new RequirementConfig { Item = "BoneFragments", Amount = 1, Recover = false } }; ItemConfig val2 = val; CustomItem val3 = new CustomItem("BoneMeal", "Blueberries", val2); ItemRecolor.Recolor(val3, Constants.BoneWhite); SharedData shared = val3.ItemDrop.m_itemData.m_shared; shared.m_food = 0f; shared.m_foodStamina = 0f; shared.m_foodEitr = 0f; shared.m_foodBurnTime = 0f; shared.m_foodRegen = 0f; shared.m_foodEatAnimTime = 0f; ItemManager.Instance.AddItem(val3); Logger.LogInfo((object)"Bone Meal has been added to the game"); } } internal static class IvoryPowder { public static void Add() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) ItemConfig val = new ItemConfig(); val.Name = "$item_ivorypowder"; val.Description = "$item_ivorypowder_description"; val.CraftingStation = CraftingStations.Cauldron; val.MinStationLevel = 2; val.Amount = 1; val.Requirements = (RequirementConfig[])(object)new RequirementConfig[1] { new RequirementConfig { Item = "BoneFragments", Amount = 20, Recover = false } }; ItemConfig val2 = val; CustomItem val3 = new CustomItem("IvoryPowder", "SpiceMountains", val2); ItemRecolor.Recolor(val3, Constants.BoneWhite); ItemManager.Instance.AddItem(val3); Logger.LogInfo((object)"Ivory Powder has been added to the game"); } } internal static class MealBag { public static void Add() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) ItemConfig val = new ItemConfig(); val.Name = "$item_mealbag"; val.Description = "$item_mealbag_description"; val.CraftingStation = CraftingStations.Cauldron; val.MinStationLevel = 3; val.Amount = 1; val.Requirements = (RequirementConfig[])(object)new RequirementConfig[1] { new RequirementConfig { Item = "BoneFragments", Amount = 10, Recover = false } }; ItemConfig val2 = val; CustomItem val3 = new CustomItem("MealBag", "BarleyFlour", val2); ItemRecolor.Recolor(val3, Constants.MealBagWarmWhite); ItemManager.Instance.AddItem(val3); Logger.LogInfo((object)"Meal Bag has been added to the game"); } } } namespace AllTheBones.Configuration { internal static class Constants { public const string BoneMeal = "BoneMeal"; public const string MealBag = "MealBag"; public const string BoneGlue = "BoneGlue"; public const string BoneCement = "BoneCement"; public const string IvoryPowder = "IvoryPowder"; public const string BlueberriesPrefab = "Blueberries"; public const string BarleyFlourPrefab = "BarleyFlour"; public const string GuckPrefab = "Guck"; public const string SpiceMountainsPrefab = "SpiceMountains"; public const string BoneFragments = "BoneFragments"; public const string Resin = "Resin"; public const string BoneMealToken = "$item_bonemeal"; public const string BoneMealDescriptionToken = "$item_bonemeal_description"; public const string MealBagToken = "$item_mealbag"; public const string MealBagDescriptionToken = "$item_mealbag_description"; public const string BoneGlueToken = "$item_boneglue"; public const string BoneGlueDescriptionToken = "$item_boneglue_description"; public const string BoneCementToken = "$item_bonecement"; public const string BoneCementDescriptionToken = "$item_bonecement_description"; public const string IvoryPowderToken = "$item_ivorypowder"; public const string IvoryPowderDescriptionToken = "$item_ivorypowder_description"; public const string UseOnWhatToken = "$msg_useonwhat"; public const string CantUseOnToken = "$msg_cantuseon"; public const string PlantMatureToken = "$atb_plant_mature"; public const string GrowthMaxedToken = "$atb_growth_maxed"; public const string NoPlantsNearbyToken = "$atb_no_plants_nearby"; public const string TreatmentDoneToken = "$atb_treat_done"; public const string BoneMealHintToken = "$atb_hint_bonemeal"; public const string MealBagHintToken = "$atb_hint_mealbag"; public const string BoneGlueHintToken = "$atb_hint_boneglue"; public const string BoneCementHintToken = "$atb_hint_bonecement"; public const string WrongMaterialToken = "$atb_wrong_material"; public const string GrowthAppliedToken = "$atb_growth_applied"; public const string MealBagAppliedToken = "$atb_bag_applied"; public const string GlueAppliedToken = "$atb_glue_applied"; public const string CementAppliedToken = "$atb_cement_applied"; public const string English = "English"; public const string GrowthCountKey = "AllTheBones_growthCount"; public const string GrowthSourceKey = "AllTheBones_growthSource"; public const string TreatmentCountKey = "AllTheBones_treatmentCount"; public static readonly int GrowthCountHash = StringExtensionMethods.GetStableHashCode("AllTheBones_growthCount"); public static readonly int GrowthSourceHash = StringExtensionMethods.GetStableHashCode("AllTheBones_growthSource"); public static readonly int TreatmentCountHash = StringExtensionMethods.GetStableHashCode("AllTheBones_treatmentCount"); public const int GrowthSourceNone = 0; public const int GrowthSourceBoneMeal = 1; public const int GrowthSourceMealBag = 2; public const float BoneMealGrowthFactor = 0.8f; public const int MaxBoneMealStacks = 5; public const float MealBagGrowthFactor = 0.8f; public const float MealBagRadius = 3f; public const float StabilityBoostPerTreatment = 1f; public const bool ExcludeStationsForCement = true; public const string PlantTintProperty = "_Color"; public const float PlantTintStrength = 0.45f; public static readonly Color PlantTint = new Color(1f, 0.94f, 0.7f); public static readonly Color BoneWhite = new Color(0.96f, 0.95f, 0.9f); public static readonly Color ChalkWhite = new Color(0.93f, 0.94f, 0.93f); public static readonly Color MealBagWarmWhite = new Color(0.9f, 0.87f, 0.78f); public static readonly Color CementGray = new Color(0.63f, 0.64f, 0.62f); } internal static class ModConfig { public static ConfigEntry<bool> Diagnostics; public static ConfigEntry<bool> UseItemPatch; public static ConfigEntry<bool> PlantGrowthPatch; public static ConfigEntry<bool> StabilityBoostPatch; public static ConfigEntry<bool> WeatherImmunityPatch; public static void Init(ConfigFile config) { Diagnostics = ConfigFileExtensions.BindConfig<bool>(config, "Diagnostics", "Enabled", false, "Log per second counters for the mod's patches, frame spikes and GC activity.", false, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); UseItemPatch = ConfigFileExtensions.BindConfig<bool>(config, "Patches", "UseItem", true, "Route using the mod's items (hotbar key or inventory) to plants and building pieces.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); PlantGrowthPatch = ConfigFileExtensions.BindConfig<bool>(config, "Patches", "PlantGrowth", true, "Apply Bone Meal and Meal Bag growth boosts to plants.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); StabilityBoostPatch = ConfigFileExtensions.BindConfig<bool>(config, "Patches", "StabilityBoost", true, "Let treated pieces hand extra support to the structure above them.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); WeatherImmunityPatch = ConfigFileExtensions.BindConfig<bool>(config, "Patches", "WeatherImmunity", true, "Stop treated pieces from taking rain damage.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); } } }