Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of MightyOaks v1.2.0
MightyOaks.dll
Decompiled 6 days agousing System; using System.Collections; using System.Collections.Generic; 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 HarmonyLib; using Jotunn.Utils; 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.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("MightyOaks")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Scales Oak trees in Valheim.")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+56285c100ce128ff8c9a74dec38b3df89e8279d9")] [assembly: AssemblyProduct("MightyOaks")] [assembly: AssemblyTitle("MightyOaks")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace MightyOaks { [BepInPlugin("com.lailoken.mightyoaks", "MightyOaks", "1.2.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class MightyOaksPlugin : BaseUnityPlugin { [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static class ZNet_OnNewConnection_Patch { private static void Postfix(ZNet __instance, ZNetPeer peer) { peer.m_rpc.Register<string>("MightyOaks_VersionCheck", (Action<ZRpc, string>)RPC_MightyOaks_VersionCheck); if (!__instance.IsServer()) { peer.m_rpc.Invoke("MightyOaks_VersionCheck", new object[1] { "1.2.0" }); } else { ((MonoBehaviour)__instance).StartCoroutine(VerifyPeerHasMod(peer)); } } } [HarmonyPatch(typeof(ZNetView), "Awake")] private static class ZNetView_Awake_Patch { private static void Postfix(ZNetView __instance) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)__instance) || !__instance.IsValid()) { return; } ZDO zDO = __instance.GetZDO(); if (zDO == null || !IsScalableTree(__instance, out var prefabName, out var chance)) { return; } float @float = zDO.GetFloat(OakScaleFactorHash, 0f); if (@float > 0.1f) { ApplyScale(__instance, @float); return; } int worldSeed = GetWorldSeed(); float num = ComputeScale(((Component)__instance).transform.position, worldSeed, chance); bool flag = worldSeed != 0; if (zDO.IsOwner()) { if (flag) { zDO.Set(OakScaleFactorHash, num); ApplyScale(__instance, num); ManualLogSource logger = _Logger; if (logger != null) { logger.LogInfo((object)$"[MightyOaks] {prefabName} scale written pos={((Component)__instance).transform.position} scale={num:F2} seed={worldSeed} owner={GetOakWriteOwnerDescription()}"); } return; } ApplyScale(__instance, num); ManualLogSource logger2 = _Logger; if (logger2 != null) { logger2.LogInfo((object)$"[MightyOaks] {prefabName} no-write (seed not ready) pos={((Component)__instance).transform.position} scale={num:F2} seed={worldSeed} owner={GetOakWriteOwnerDescription()} -> reapply next frame"); } if ((Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).gameObject != (Object)null) { ((MonoBehaviour)__instance).StartCoroutine(ReapplyScaleWhenSeedReady(__instance)); } } else { ApplyScale(__instance, num); if (!flag && (Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).gameObject != (Object)null) { ((MonoBehaviour)__instance).StartCoroutine(ReapplyScaleWhenSeedReady(__instance)); } } } } [CompilerGenerated] private sealed class <ReapplyScaleWhenSeedReady>d__33 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ZNetView view; private ZDO <zdo>5__1; private string <prefabName>5__2; private float <scalingChance>5__3; private int <seed>5__4; private float <scale>5__5; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ReapplyScaleWhenSeedReady>d__33(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <zdo>5__1 = null; <prefabName>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)view == (Object)null || !view.IsValid()) { return false; } <zdo>5__1 = view.GetZDO(); if (<zdo>5__1 == null) { return false; } if (!IsScalableTree(view, out <prefabName>5__2, out <scalingChance>5__3)) { return false; } if (<zdo>5__1.GetFloat(OakScaleFactorHash, 0f) > 0.1f) { return false; } <seed>5__4 = GetWorldSeed(); if (<seed>5__4 == 0) { return false; } <scale>5__5 = ComputeScale(((Component)view).transform.position, <seed>5__4, <scalingChance>5__3); ApplyScale(view, <scale>5__5); if (<zdo>5__1.IsOwner()) { <zdo>5__1.Set(OakScaleFactorHash, <scale>5__5); ManualLogSource logger = _Logger; if (logger != null) { logger.LogInfo((object)$"[MightyOaks] {<prefabName>5__2} reapply scale written pos={((Component)view).transform.position} scale={<scale>5__5:F2} seed={<seed>5__4} owner={GetOakWriteOwnerDescription()}"); } } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <VerifyPeerHasMod>d__23 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ZNetPeer peer; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <VerifyPeerHasMod>d__23(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(10f); <>1__state = 1; return true; case 1: { <>1__state = -1; if (peer.m_socket.IsConnected() && !ValidatedPeers.TryGetValue(peer, out var _)) { _Logger.LogWarning((object)$"Peer {peer.m_uid} did not send MightyOaks version (missing mod?). Kicking."); ZNet.instance.Disconnect(peer); } return false; } } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string PluginGUID = "com.lailoken.mightyoaks"; public const string PluginName = "MightyOaks"; public const string PluginVersion = "1.2.0"; private static ConfigEntry<float> ChanceScaleOak; private static ConfigEntry<float> ChanceScaleAshlandsOaks; private static ConfigEntry<float> ChanceScalePlainsStoneColumns; private static ConfigEntry<float> ChanceScaleSwampAncientTrees; private static ConfigEntry<float> ChanceScaleMistlandsTrees; private static ConfigEntry<float> MinScale; private static ConfigEntry<float> MaxScale; private static ConfigEntry<float> ScaleExponent; private static ConfigEntry<bool> ScaleToughness; private static ConfigEntry<float> InvulnerabilityThreshold; private static ConfigEntry<float> SpawnProtectionRadius; private static ManualLogSource _Logger; private static readonly int OakScaleFactorHash = StringExtensionMethods.GetStableHashCode("OakScaleFactor"); private static readonly HashSet<string> AshlandsOakPrefabs = new HashSet<string> { "AshlandsTree6", "AshlandsTree6_big" }; private static readonly HashSet<string> PlainsStoneColumnPrefabs = new HashSet<string> { "HeathRockPillar", "HeathRockPillar_frac" }; private static readonly HashSet<string> SwampAncientTreePrefabs = new HashSet<string> { "SwampTree2", "SwampTree2_darkland" }; private static readonly HashSet<string> MistlandsTreePrefabs = new HashSet<string> { "YggaShoot1", "YggaShoot2", "YggaShoot3" }; private static readonly ConditionalWeakTable<ZNetPeer, object> ValidatedPeers = new ConditionalWeakTable<ZNetPeer, object>(); private void Awake() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Expected O, but got Unknown //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Expected O, but got Unknown //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Expected O, but got Unknown //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Expected O, but got Unknown //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Expected O, but got Unknown //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Expected O, but got Unknown //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Expected O, but got Unknown //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Expected O, but got Unknown //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Expected O, but got Unknown _Logger = ((BaseUnityPlugin)this).Logger; ConfigurationManagerAttributes val = new ConfigurationManagerAttributes { IsAdminOnly = true }; AcceptableValueRange<float> val2 = new AcceptableValueRange<float>(0f, 100f); AcceptableValueRange<float> val3 = new AcceptableValueRange<float>(0.1f, 20f); AcceptableValueRange<float> val4 = new AcceptableValueRange<float>(0f, 21f); ChanceScaleOak = ((BaseUnityPlugin)this).Config.Bind<float>("Chances", "ChanceScaleOak", 15f, new ConfigDescription("Chance (0-100) to scale Oak trees. 0 = off.", (AcceptableValueBase)(object)val2, new object[1] { val })); ChanceScaleAshlandsOaks = ((BaseUnityPlugin)this).Config.Bind<float>("Chances", "ChanceScaleAshlandsOaks", 5f, new ConfigDescription("Chance (0-100) to scale Ashlands burnt oaks. 0 = off.", (AcceptableValueBase)(object)val2, new object[1] { val })); ChanceScalePlainsStoneColumns = ((BaseUnityPlugin)this).Config.Bind<float>("Chances", "ChanceScalePlainsStoneColumns", 0f, new ConfigDescription("Chance (0-100) to scale Plains stone columns. 0 = off.", (AcceptableValueBase)(object)val2, new object[1] { val })); ChanceScaleSwampAncientTrees = ((BaseUnityPlugin)this).Config.Bind<float>("Chances", "ChanceScaleSwampAncientTrees", 0f, new ConfigDescription("Chance (0-100) to scale Swamp ancient trees. 0 = off.", (AcceptableValueBase)(object)val2, new object[1] { val })); ChanceScaleMistlandsTrees = ((BaseUnityPlugin)this).Config.Bind<float>("Chances", "ChanceScaleMistlandsTrees", 0f, new ConfigDescription("Chance (0-100) to scale Mistlands trees (Yggdrasil shoots). 0 = off.", (AcceptableValueBase)(object)val2, new object[1] { val })); MinScale = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MinScale", 1f, new ConfigDescription("Minimum scale factor.", (AcceptableValueBase)(object)val3, new object[1] { val })); MaxScale = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MaxScale", 10f, new ConfigDescription("Maximum scale factor.", (AcceptableValueBase)(object)val3, new object[1] { val })); ScaleExponent = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ScaleExponent", 3f, new ConfigDescription("Exponent for scale distribution. 1.0 is linear (uniform). Higher values (e.g. 2.0, 3.0) make large trees rarer.", (AcceptableValueBase)(object)val3, new object[1] { val })); ScaleToughness = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ScaleToughness", true, new ConfigDescription("If true, scales the tree's health/toughness along with its size.", (AcceptableValueBase)null, new object[1] { val })); InvulnerabilityThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("General", "InvulnerabilityThreshold", 2f, new ConfigDescription("Scale threshold above which trees become invulnerable. Set to max to disable.", (AcceptableValueBase)(object)val4, new object[1] { val })); SpawnProtectionRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SpawnProtectionRadius", 300f, new ConfigDescription("Radius from world center (spawn) where no giant oaks spawn. Default 300 keeps spawn area clear (beyond ~180m render). Set 0 to allow everywhere.", (AcceptableValueBase)null, new object[1] { val })); Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "com.lailoken.mightyoaks"); } [IteratorStateMachine(typeof(<VerifyPeerHasMod>d__23))] private static IEnumerator VerifyPeerHasMod(ZNetPeer peer) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <VerifyPeerHasMod>d__23(0) { peer = peer }; } private static void RPC_MightyOaks_VersionCheck(ZRpc rpc, string clientVersion) { if (!ZNet.instance.IsServer()) { return; } ZNetPeer val = null; foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer.m_rpc == rpc) { val = peer; break; } } object value; if (val == null) { _Logger.LogWarning((object)"Received MightyOaks version check from unknown peer."); } else if (!IsVersionCompatible(clientVersion, "1.2.0")) { _Logger.LogWarning((object)string.Format("Peer {0} has incompatible MightyOaks version {1} (server: {2}). Kicking.", val.m_uid, clientVersion, "1.2.0")); ZNet.instance.Disconnect(val); } else if (!ValidatedPeers.TryGetValue(val, out value)) { ValidatedPeers.Add(val, null); } } private static bool IsVersionCompatible(string v1, string v2) { try { Version version = new Version(v1); Version version2 = new Version(v2); return version.Major == version2.Major && version.Minor == version2.Minor; } catch { return false; } } private static int GetWorldSeed() { if (WorldGenerator.instance != null) { World value = Traverse.Create((object)WorldGenerator.instance).Field("m_world").GetValue<World>(); if (value != null) { return value.m_seed; } } if ((Object)(object)ZNet.instance != (Object)null) { World value2 = Traverse.Create((object)ZNet.instance).Field("m_world").GetValue<World>(); if (value2 != null) { return value2.m_seed; } } return 0; } private static string GetOakWriteOwnerDescription() { if ((Object)(object)ZNet.instance == (Object)null) { return "?"; } if (ZNet.instance.IsServer()) { return "server"; } string text = TryGetLocalPlayerName(); return string.IsNullOrEmpty(text) ? "client" : text; } private static string TryGetLocalPlayerName() { try { Type typeFromHandle = typeof(Player); Traverse val = Traverse.Create(typeFromHandle); object obj = val.Field("m_localPlayer").GetValue() ?? val.Field("s_localPlayer").GetValue(); if (obj == null) { return null; } string value = Traverse.Create(obj).Method("GetPlayerName", Array.Empty<object>()).GetValue<string>(); if (!string.IsNullOrEmpty(value)) { return value; } Game instance = Game.instance; if ((Object)(object)instance != (Object)null) { object value2 = Traverse.Create((object)instance).Method("GetPlayerProfile", Array.Empty<object>()).GetValue(); if (value2 != null) { string value3 = Traverse.Create(value2).Method("GetName", Array.Empty<object>()).GetValue<string>(); if (!string.IsNullOrEmpty(value3)) { return value3; } } } return null; } catch { return null; } } private static string GetTreePrefabName(ZNetView view) { if (!Object.op_Implicit((Object)(object)view) || !view.IsValid()) { return ""; } ZDO zDO = view.GetZDO(); if (zDO != null && (Object)(object)ZNetScene.instance != (Object)null) { GameObject prefab = ZNetScene.instance.GetPrefab(zDO.GetPrefab()); if (Object.op_Implicit((Object)(object)prefab)) { return ((Object)prefab).name; } } return ((Object)((Component)view).gameObject).name.Replace("(Clone)", ""); } private static bool IsScalableTree(ZNetView view, out string prefabName, out float chance) { prefabName = GetTreePrefabName(view); chance = 0f; if (string.IsNullOrEmpty(prefabName)) { return false; } if (prefabName == "Oak1" && ChanceScaleOak.Value > 0f) { chance = ChanceScaleOak.Value; return true; } if (AshlandsOakPrefabs.Contains(prefabName) && ChanceScaleAshlandsOaks.Value > 0f) { chance = ChanceScaleAshlandsOaks.Value; return true; } if (PlainsStoneColumnPrefabs.Contains(prefabName) && ChanceScalePlainsStoneColumns.Value > 0f) { chance = ChanceScalePlainsStoneColumns.Value; return true; } if (SwampAncientTreePrefabs.Contains(prefabName) && ChanceScaleSwampAncientTrees.Value > 0f) { chance = ChanceScaleSwampAncientTrees.Value; return true; } if (MistlandsTreePrefabs.Contains(prefabName) && ChanceScaleMistlandsTrees.Value > 0f) { chance = ChanceScaleMistlandsTrees.Value; return true; } return false; } private static float ComputeScale(Vector3 pos, int worldSeed, float scalingChance) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //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) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) if (worldSeed == 0 || scalingChance <= 0f) { return 1f; } float value = SpawnProtectionRadius.Value; if (value > 0f) { float num = pos.x * pos.x + pos.z * pos.z; if (num < value * value) { return 1f; } } int num2 = worldSeed + (int)(pos.x * 1000f) + (int)(pos.z * 1000f); State state = Random.state; Random.InitState(num2); float result = 1f; if (Random.Range(0f, 100f) <= scalingChance) { float value2 = Random.value; float num3 = Mathf.Pow(value2, ScaleExponent.Value); result = Mathf.Lerp(MinScale.Value, MaxScale.Value, num3); } Random.state = state; return result; } [IteratorStateMachine(typeof(<ReapplyScaleWhenSeedReady>d__33))] private static IEnumerator ReapplyScaleWhenSeedReady(ZNetView view) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ReapplyScaleWhenSeedReady>d__33(0) { view = view }; } private static void ApplyScale(ZNetView view, float scale) { //IL_001b: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) if (scale <= 1.01f || Mathf.Abs(((Component)view).transform.localScale.x - scale) < 0.01f) { return; } ((Component)view).transform.localScale = Vector3.one * scale; Destructible component = ((Component)view).GetComponent<Destructible>(); TreeBase component2 = ((Component)view).GetComponent<TreeBase>(); if (ScaleToughness.Value) { if (Object.op_Implicit((Object)(object)component)) { component.m_health *= scale * scale; } if (Object.op_Implicit((Object)(object)component2)) { component2.m_health *= scale * scale; } } if (InvulnerabilityThreshold.Value > 0f && scale >= InvulnerabilityThreshold.Value) { if (Object.op_Implicit((Object)(object)component)) { component.m_minToolTier = 1000; component.m_damages.m_chop = (DamageModifier)3; component.m_damages.m_pickaxe = (DamageModifier)3; } if (Object.op_Implicit((Object)(object)component2)) { component2.m_minToolTier = 1000; component2.m_damageModifiers.m_chop = (DamageModifier)3; component2.m_damageModifiers.m_pickaxe = (DamageModifier)3; } } } } public static class PluginInfo { public const string PLUGIN_GUID = "MightyOaks"; public const string PLUGIN_NAME = "MightyOaks"; public const string PLUGIN_VERSION = "1.0.0"; } }