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 FrostVale ServerPack 3 v1.0.1
plugins/FrostValeCompat/FrostValeCompat.dll
Decompiled 2 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyVersion("0.0.0.0")] namespace FrostValeCompat; [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("frostvale.compat", "FrostVale Compat", "1.0.1")] public sealed class RiceWaterLevelPlugin : BaseUnityPlugin { public const string PluginGuid = "frostvale.compat"; public const string PluginName = "FrostVale Compat"; public const string PluginVersion = "1.0.1"; internal static ConfigEntry<float> MinGroundOffset; internal static ConfigEntry<float> MaxGroundOffset; internal static ConfigEntry<bool> BlockRiceAwayFromWater; internal static RiceWaterLevelPlugin Instance; internal static ManualLogSource Log; private void Awake() { Instance = this; Log = ((BaseUnityPlugin)this).Logger; BlockRiceAwayFromWater = ((BaseUnityPlugin)this).Config.Bind<bool>("RtDOcean Rice", "Block rice away from water level", true, "If enabled, RtDOcean rice saplings can only be placed near the configured water-level band."); MinGroundOffset = ((BaseUnityPlugin)this).Config.Bind<float>("RtDOcean Rice", "Minimum ground offset from water", -0.35f, "Lowest allowed terrain height relative to water level, in meters."); MaxGroundOffset = ((BaseUnityPlugin)this).Config.Bind<float>("RtDOcean Rice", "Maximum ground offset from water", 0.15f, "Highest allowed terrain height relative to water level, in meters."); Harmony.CreateAndPatchAll(typeof(RiceWaterLevelPlugin).Assembly, "frostvale.compat"); DiscordNameDisplayPatches.Patch(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"FrostVale rice water-level placement patch loaded."); } } [HarmonyPatch(typeof(Player), "TryPlacePiece")] internal static class RicePlacementPatch { private static bool Prefix(Piece piece, ref bool __result) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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) if (!RiceWaterLevelPlugin.BlockRiceAwayFromWater.Value || !RiceWaterLevelRules.IsRiceSapling(piece)) { return true; } Vector3 position = ((Component)piece).transform.position; if (RiceWaterLevelRules.IsWithinWaterBand(position, out var groundHeight, out var waterLevel)) { return true; } __result = false; ShowMessage($"Rice must be planted at water level. Ground {groundHeight - waterLevel:0.00}m from water."); return false; } private static void ShowMessage(string message) { try { if ((Object)(object)MessageHud.instance != (Object)null) { MessageHud.instance.ShowMessage((MessageType)2, message, 0, (Sprite)null, false); } } catch (Exception ex) { RiceWaterLevelPlugin.Log.LogDebug((object)("Could not show rice placement message: " + ex.Message)); } } } [HarmonyPatch(typeof(Plant), "GetStatus")] internal static class RicePlantStatusPatch { private static void Postfix(Plant __instance, ref Status __result) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (RiceWaterLevelPlugin.BlockRiceAwayFromWater.Value && (int)__result == 0 && RiceWaterLevelRules.IsRicePlant(__instance) && !RiceWaterLevelRules.IsWithinWaterBand(((Component)__instance).transform.position, out var _, out var _)) { __result = (Status)3; } } } internal static class RiceWaterLevelRules { public static bool IsRiceSapling(Piece piece) { if ((Object)(object)piece == (Object)null) { return false; } if (!LooksLikeRice(((Object)piece).name) && !LooksLikeRice(((Object)((Component)piece).gameObject).name)) { return LooksLikeRice(piece.m_name); } return true; } public static bool IsRicePlant(Plant plant) { if ((Object)(object)plant == (Object)null) { return false; } if (!LooksLikeRice(((Object)plant).name) && !LooksLikeRice(((Object)((Component)plant).gameObject).name)) { return LooksLikeRice(plant.m_name); } return true; } public static bool IsWithinWaterBand(Vector3 position, out float groundHeight, out float waterLevel) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) ZoneSystem instance = ZoneSystem.instance; waterLevel = (((Object)(object)instance != (Object)null) ? instance.m_waterLevel : 30f); groundHeight = position.y; float num = default(float); if ((Object)(object)instance != (Object)null && instance.GetGroundHeight(position, ref num)) { groundHeight = num; } float num2 = groundHeight - waterLevel; if (num2 >= RiceWaterLevelPlugin.MinGroundOffset.Value) { return num2 <= RiceWaterLevelPlugin.MaxGroundOffset.Value; } return false; } private static bool LooksLikeRice(string value) { if (!string.IsNullOrEmpty(value) && value.IndexOf("Rice", StringComparison.OrdinalIgnoreCase) >= 0) { return value.IndexOf("_RtD", StringComparison.OrdinalIgnoreCase) >= 0; } return false; } } internal static class DiscordNameDisplayPatches { private static readonly Dictionary<string, string> NamesById = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); private static readonly Regex NumericIdPattern = new Regex("\\b\\d{15,20}\\b", RegexOptions.Compiled); public static void Patch() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown try { Harmony harmony = new Harmony("frostvale.compat.discord-names"); PatchPrefix(harmony, "FiresDiscordIntegration.Discord.DiscordIntegrationCore", "OnPlayerJoin", typeof(DiscordPlayerNameTracker).GetMethod("PlayerNameFirstPrefix", BindingFlags.Static | BindingFlags.NonPublic)); PatchPrefix(harmony, "FiresDiscordIntegration.Discord.DiscordIntegrationCore", "OnPlayerLeave", typeof(DiscordPlayerNameTracker).GetMethod("PlayerNameFirstPrefix", BindingFlags.Static | BindingFlags.NonPublic)); PatchPrefix(harmony, "FiresDiscordIntegration.Discord.DiscordIntegrationCore", "OnClientLoginArtifacts", typeof(DiscordPlayerNameTracker).GetMethod("PlayerNameFirstPrefix", BindingFlags.Static | BindingFlags.NonPublic)); PatchPrefix(harmony, "FiresDiscordIntegration.Discord.DiscordIntegrationCore", "SendClientLogOnRequest", typeof(DiscordPlayerNameTracker).GetMethod("PlayerNameFirstPrefix", BindingFlags.Static | BindingFlags.NonPublic)); PatchPrefix(harmony, "FiresDiscordIntegration.ClientLogRelay.ClientLogRelayIntegration", "PostDisconnectLog", typeof(DiscordPlayerNameTracker).GetMethod("IdFirstPrefix", BindingFlags.Static | BindingFlags.NonPublic)); PatchPrefix(harmony, "FiresDiscordIntegration.ClientLogRelay.ClientLogRelayIntegration", "PostDisconnectLogAsync", typeof(DiscordPlayerNameTracker).GetMethod("IdFirstPrefix", BindingFlags.Static | BindingFlags.NonPublic)); PatchPrefix(harmony, "FiresDiscordIntegration.Discord.DiscordStatusTracker", "RecordJoin", typeof(DiscordPlayerNameTracker).GetMethod("PlayerNameFirstPrefix", BindingFlags.Static | BindingFlags.NonPublic)); PatchPrefix(harmony, "FiresDiscordIntegration.Discord.DiscordStatusTracker", "RecordLeave", typeof(DiscordPlayerNameTracker).GetMethod("PlayerNameFirstPrefix", BindingFlags.Static | BindingFlags.NonPublic)); PatchPrefix(harmony, "FiresDiscordIntegration.Discord.DiscordWebhookService", "SendMessage", typeof(DiscordVisibleTextRewriter).GetMethod("Prefix", BindingFlags.Static | BindingFlags.NonPublic)); PatchPrefix(harmony, "FiresDiscordIntegration.Discord.DiscordWebhookService", "SendEmbed", typeof(DiscordVisibleTextRewriter).GetMethod("Prefix", BindingFlags.Static | BindingFlags.NonPublic)); PatchPrefix(harmony, "FiresDiscordIntegration.Discord.DiscordWebhookService", "SendEmbedWithFiles", typeof(DiscordVisibleTextRewriter).GetMethod("Prefix", BindingFlags.Static | BindingFlags.NonPublic)); PatchPrefix(harmony, "FiresDiscordIntegration.Discord.DiscordWebhookService", "EnqueuePost", typeof(DiscordVisibleTextRewriter).GetMethod("Prefix", BindingFlags.Static | BindingFlags.NonPublic)); RiceWaterLevelPlugin.Log.LogInfo((object)"FrostVale Discord name-display patch loaded."); } catch (Exception ex) { RiceWaterLevelPlugin.Log.LogWarning((object)("FrostVale Discord name-display patch skipped: " + ex.Message)); } } private static void PatchPrefix(Harmony harmony, string typeName, string methodName, MethodInfo prefix) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown if (prefix == null) { return; } Type type = AccessTools.TypeByName(typeName); if (type == null) { return; } foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(type)) { if (declaredMethod.Name == methodName) { harmony.Patch((MethodBase)declaredMethod, new HarmonyMethod(prefix), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } internal static void Remember(string platformId, string playerName) { if (!string.IsNullOrWhiteSpace(platformId) && !string.IsNullOrWhiteSpace(playerName) && !IsRawId(playerName)) { NamesById[platformId.Trim()] = playerName.Trim(); } } internal static string RewriteText(string value) { if (string.IsNullOrEmpty(value) || NamesById.Count == 0) { return value; } string value2; return NumericIdPattern.Replace(value, (Match match) => (!NamesById.TryGetValue(match.Value, out value2)) ? match.Value : value2); } internal static bool IsRawId(string value) { if (!string.IsNullOrWhiteSpace(value)) { return NumericIdPattern.IsMatch(value.Trim()); } return false; } } internal static class DiscordPlayerNameTracker { private static void PlayerNameFirstPrefix(object[] __args) { if (__args != null && __args.Length >= 2) { DiscordNameDisplayPatches.Remember(__args[1] as string, __args[0] as string); } } private static void IdFirstPrefix(object[] __args) { if (__args != null && __args.Length >= 2) { DiscordNameDisplayPatches.Remember(__args[0] as string, __args[1] as string); } } } internal static class DiscordVisibleTextRewriter { private static void Prefix(object[] __args) { if (__args == null) { return; } for (int i = 0; i < __args.Length; i++) { object obj = __args[i]; if (obj is string value) { __args[i] = DiscordNameDisplayPatches.RewriteText(value); } else { RewriteObject(obj, new HashSet<object>(ReferenceEqualityComparer.Instance)); } } } private static void RewriteObject(object value, HashSet<object> visited) { if (value == null || value is string || value.GetType().IsPrimitive || !visited.Add(value)) { return; } if (value is IDictionary dictionary) { List<object> list = new List<object>(); foreach (object key in dictionary.Keys) { list.Add(key); } { foreach (object item in list) { object obj = dictionary[item]; string text = obj as string; dictionary[item] = ((text != null) ? DiscordNameDisplayPatches.RewriteText(text) : RewriteAndReturn(obj, visited)); } return; } } if (value is IList list2) { for (int i = 0; i < list2.Count; i++) { object obj2 = list2[i]; string text2 = obj2 as string; list2[i] = ((text2 != null) ? DiscordNameDisplayPatches.RewriteText(text2) : RewriteAndReturn(obj2, visited)); } return; } FieldInfo[] fields = value.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (fieldInfo.FieldType == typeof(string)) { string value2 = fieldInfo.GetValue(value) as string; fieldInfo.SetValue(value, DiscordNameDisplayPatches.RewriteText(value2)); } else if (!fieldInfo.FieldType.IsValueType) { RewriteObject(fieldInfo.GetValue(value), visited); } } } private static object RewriteAndReturn(object value, HashSet<object> visited) { RewriteObject(value, visited); return value; } } internal sealed class ReferenceEqualityComparer : IEqualityComparer<object> { public static readonly ReferenceEqualityComparer Instance = new ReferenceEqualityComparer(); private ReferenceEqualityComparer() { } public new bool Equals(object x, object y) { return object.ReferenceEquals(x, y); } public int GetHashCode(object obj) { return RuntimeHelpers.GetHashCode(obj); } }