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 DeepSeaTreasures v1.1.3
DeepSeaTreasures.dll
Decompiled 2 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace DeepSeaTreasures { [BepInPlugin("alkin.DeepSeaTreasures", "DeepSeaTreasures", "1.1.3")] public sealed class Plugin : BaseUnityPlugin { public const string GUID = "alkin.DeepSeaTreasures"; public const string NAME = "DeepSeaTreasures"; public const string VERSION = "1.1.3"; internal static Plugin Instance; internal static ConfigEntry<bool> ModEnabled; internal static ConfigEntry<bool> DepthMultiplierEnabled; internal static ConfigEntry<float> BaseMultiplier; internal static ConfigEntry<float> IncreasePerMeter; internal static ConfigEntry<float> MinimumDepthBonus; internal static ConfigEntry<float> MaximumDepthBonus; internal static ConfigEntry<float> ScanRadius; internal static ConfigEntry<int> CellsPerFrame; internal static readonly Dictionary<Biome, ConfigEntry<string>> LootConfigs = new Dictionary<Biome, ConfigEntry<string>>(); private readonly Queue<CellCoord> _pending = new Queue<CellCoord>(); private readonly HashSet<CellCoord> _queued = new HashSet<CellCoord>(); private ProcessedCellStore _store; private float _nextScan; internal const float CellArea = 1000f; internal static readonly float CellSize = Mathf.Sqrt(1000f); private void Awake() { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Expected O, but got Unknown //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Expected O, but got Unknown //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Expected O, but got Unknown Instance = this; ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enables DeepSeaTreasures."); ScanRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ScanRadius", 180f, new ConfigDescription("Radius in meters around active players in which new 1000 m² seabed cells are evaluated.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(32f, 1000f), Array.Empty<object>())); CellsPerFrame = ((BaseUnityPlugin)this).Config.Bind<int>("General", "CellsPerFrame", 2, new ConfigDescription("Maximum new seabed cells evaluated per frame.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 64), Array.Empty<object>())); DepthMultiplierEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Depth Multipliers", "DepthMultiplierEnabled", true, "If true, all item spawn chances are multiplied according to water depth."); BaseMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Depth Multipliers", "BaseMultiplier", 1f, new ConfigDescription("Base multiplier applied to every item chance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); IncreasePerMeter = ((BaseUnityPlugin)this).Config.Bind<float>("Depth Multipliers", "IncreasePerMeter", 0.01f, new ConfigDescription("Relative multiplier added for each eligible meter of depth. 0.01 = +1% of the base chance per meter.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>())); MinimumDepthBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Depth Multipliers", "MinimumDepthBonus", 5f, new ConfigDescription("Depth in meters at which IncreasePerMeter begins accumulating.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10000f), Array.Empty<object>())); MaximumDepthBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Depth Multipliers", "MaximumDepthBonus", 100f, new ConfigDescription("Maximum NUMBER OF METERS counted for IncreasePerMeter, starting after MinimumDepthBonus.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10000f), Array.Empty<object>())); BindBiome((Biome)1, "Meadows", "Stone,0.396,1,1,1,0;Wood,0.192,1,1,1,0;Flint,0.128,1,1,1,0;BoneFragments,0.04,1,1,3,0;LeatherScraps,0.0168,1,1,2,500;DeerHide,0.0112,1,1,3,750;Coins,0.003,1,5,4,1000;AxeFlint,0.0004,1,1,6,2500,0.05,0.25"); BindBiome((Biome)8, "BlackForest", "Stone,0.44,1,1,1,0;Wood,0.18,1,1,1,0;RoundLog,0.112,1,1,2,0;CopperOre,0.0252,1,1,5,1500;TinOre,0.021,1,1,4,1200;BoneFragments,0.0288,1,1,4,0;SurtlingCore,0.006,1,1,7,1800;Amber,0.0084,1,1,5,2000;AmberPearl,0.0025,1,1,7,2500;Coins,0.005,2,8,5,1800;SwordBronze,0.00035,1,1,10,4500,0.05,0.22;ArmorBronzeChest,0.00018,1,1,12,6000,0.04,0.18"); BindBiome((Biome)2, "Swamp", "Stone,0.252,1,1,1,0;Wood,0.112,1,1,1,0;ElderBark,0.072,1,1,2,0;IronScrap,0.0252,1,1,5,2500;BoneFragments,0.045,1,1,3,0;Entrails,0.0168,1,1,3,1500;Chain,0.0035,1,1,8,3500;Coins,0.006,2,10,5,2500;SwordIron,0.00035,1,1,10,6000,0.04,0.20;ArmorIronChest,0.00016,1,1,12,6500,0.03,0.15"); BindBiome((Biome)4, "Mountain", "Stone,0.288,1,1,1,0;Crystal,0.049,1,1,4,0;Obsidian,0.04,1,1,4,2500;SilverOre,0.0126,1,1,7,4000;WolfPelt,0.0098,1,1,4,3000;FreezeGland,0.0084,1,1,5,3500;Coins,0.004,2,10,6,4000;SwordSilver,0.00028,1,1,12,7500,0.04,0.18;ArmorWolfChest,0.00014,1,1,14,9000,0.03,0.14"); BindBiome((Biome)256, "Ocean", "Stone,0.55,1,1,2,0;Wood,0.32,1,1,2,0;FineWood,0.12,1,1,4,2000;Coins,0.06,3,15,5,2000;Amber,0.04,1,1,6,2500;AmberPearl,0.025,1,1,8,3000;Chitin,0.03,1,1,8,3500;IronScrap,0.028,1,1,8,4000;SilverOre,0.012,1,1,12,6500;BlackMetalScrap,0.006,1,1,15,7500;SwordIron,0.00055,1,1,12,6000,0.03,0.18;SwordSilver,0.0004,1,1,15,7000,0.03,0.16;SwordBlackmetal,0.00022,1,1,18,8000,0.02,0.12"); BindBiome((Biome)16, "Plains", "Stone,0.324,1,1,1,0;Wood,0.096,1,1,1,0;FineWood,0.056,1,1,3,2500;BlackMetalScrap,0.0196,1,1,6,4500;Needle,0.0192,1,1,4,3000;LoxPelt,0.0098,1,1,4,3500;Coins,0.008,3,12,5,4500;Barley,0.0096,1,1,3,4000;Flax,0.0096,1,1,3,4000;SwordBlackmetal,0.00025,1,1,12,6500,0.03,0.17;ArmorPaddedCuirass,0.00012,1,1,14,7500,0.02,0.12"); BindBiome((Biome)512, "Mistlands", "Stone,0.288,1,1,1,0;BlackMarble,0.112,1,1,3,2500;CopperScrap,0.04,1,1,4,3500;IronScrap,0.0196,1,1,5,4500;Softtissue,0.0084,1,1,7,6500;YggdrasilWood,0.04,1,1,3,3000;SurtlingCore,0.004,1,1,8,5000;Coins,0.009,3,15,5,5000;Carapace,0.0084,1,1,7,7000;SwordMistwalker,0.00018,1,1,14,8000,0.02,0.14;ArmorCarapaceChest,0.00009,1,1,16,8500,0.02,0.10"); BindBiome((Biome)32, "Ashlands", "Stone,0.32,1,1,1,0;BlackMarble,0.088,1,1,3,3000;Ashwood,0.064,1,1,3,3500;BoneFragments,0.045,1,1,3,0;SurtlingCore,0.0126,1,1,7,5000;FlametalOreNew,0.006,1,1,9,7000;FlametalNew,0.002,1,1,12,6500;Coins,0.010,4,18,6,6000;CharredBone,0.0192,1,1,5,5000;ArmorFlametalChest,0.00007,1,1,18,8750,0.01,0.08;ArmorAshlandsMediumChest,0.00007,1,1,18,8750,0.01,0.08"); BindBiome((Biome)64, "DeepNorth", "Stone,0.32,1,1,1,0;Crystal,0.112,1,1,3,0;Obsidian,0.04,1,1,4,5000;SilverOre,0.0168,1,1,6,7000;FreezeGland,0.024,1,1,4,5000;FlametalNew,0.0015,1,1,15,8500;Coins,0.012,4,20,6,7000;ArmorFlametalChest,0.00005,1,1,20,9000,0.01,0.06"); _store = new ProcessedCellStore(((BaseUnityPlugin)this).Logger); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} {1} loaded. Cell size: {2:0.###} m ({3:0} m²).", "DeepSeaTreasures", "1.1.3", CellSize, 1000f)); } private void BindBiome(Biome biome, string section, string defaults) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) LootConfigs[biome] = ((BaseUnityPlugin)this).Config.Bind<string>(section, "Loot", defaults, "Entries: Prefab,Chance,MinAmount,MaxAmount,MinimumDepth,MinimumDistanceFromCenter[,MinDurability,MaxDurability]. Chance/durability are 0..1; distances are meters. Example: SwordIron,0.001,1,1,15,9000,0.03,0.15"); } private void Update() { if (!ModEnabled.Value || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } if (Time.unscaledTime >= _nextScan) { _nextScan = Time.unscaledTime + 2f; QueueCellsAroundPlayers(); } int num = Mathf.Min(CellsPerFrame.Value, _pending.Count); for (int i = 0; i < num; i++) { CellCoord cellCoord = _pending.Dequeue(); _queued.Remove(cellCoord); if (!_store.IsProcessed(cellCoord)) { try { EvaluateCell(cellCoord); _store.MarkProcessed(cellCoord); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogWarning((object)$"Failed evaluating cell {cellCoord}: {arg}"); } } } } private void QueueCellsAroundPlayers() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) List<Player> allPlayers = Player.GetAllPlayers(); if (allPlayers == null) { return; } int num = Mathf.CeilToInt(ScanRadius.Value / CellSize); Vector2 val = default(Vector2); foreach (Player item in allPlayers) { if ((Object)(object)item == (Object)null) { continue; } CellCoord cellCoord = CellCoord.FromWorld(((Component)item).transform.position); for (int i = -num; i <= num; i++) { for (int j = -num; j <= num; j++) { CellCoord cellCoord2 = new CellCoord(cellCoord.X + i, cellCoord.Z + j); Vector3 center = cellCoord2.Center; ((Vector2)(ref val))..ctor(center.x - ((Component)item).transform.position.x, center.z - ((Component)item).transform.position.z); if (!(((Vector2)(ref val)).sqrMagnitude > ScanRadius.Value * ScanRadius.Value) && !_store.IsProcessed(cellCoord2) && _queued.Add(cellCoord2)) { _pending.Enqueue(cellCoord2); } } } } } private void EvaluateCell(CellCoord cell) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: 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) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) Random random = new Random(cell.StableSeed()); float num = 2f; float num2 = Mathf.Max(0.1f, CellSize - num * 2f); Vector3 xz = default(Vector3); ((Vector3)(ref xz))..ctor((float)cell.X * CellSize + num + (float)random.NextDouble() * num2, 0f, (float)cell.Z * CellSize + num + (float)random.NextDouble() * num2); if (!WorldQueries.TryGetNaturalSeabed(xz, out var seabed, out var _, out var depth, out var biome) || !LootConfigs.TryGetValue(biome, out var value)) { return; } List<LootRule> list = LootRule.ParseList(value.Value, ((BaseUnityPlugin)this).Logger); foreach (LootRule item in list) { if (depth < item.MinimumDepth) { continue; } Vector2 val = new Vector2(seabed.x, seabed.z); float magnitude = ((Vector2)(ref val)).magnitude; if (!(magnitude < item.MinimumDistanceFromCenter)) { float num3 = item.Chance; if (DepthMultiplierEnabled.Value) { float num4 = Mathf.Clamp(depth - MinimumDepthBonus.Value, 0f, MaximumDepthBonus.Value); float num5 = BaseMultiplier.Value + num4 * IncreasePerMeter.Value; num3 *= num5; } num3 = Mathf.Clamp01(num3); if (!(random.NextDouble() > (double)num3)) { int amount = ((item.MinAmount == item.MaxAmount) ? item.MinAmount : random.Next(item.MinAmount, item.MaxAmount + 1)); SpawnItem(item, amount, seabed, random); } } } } private void SpawnItem(LootRule rule, int amount, Vector3 seabed, Random rng) { //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) string prefab = rule.Prefab; if (amount <= 0 || (Object)(object)ZNetScene.instance == (Object)null) { return; } GameObject prefab2 = ZNetScene.instance.GetPrefab(prefab); if ((Object)(object)prefab2 == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Unknown prefab '" + prefab + "'. Entry skipped.")); return; } ItemDrop component = prefab2.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Prefab '" + prefab + "' is not an ItemDrop. Entry skipped.")); return; } int num = Mathf.Max(1, component.m_itemData.m_shared.m_maxStackSize); int num2 = amount; Vector3 val = default(Vector3); while (num2 > 0) { int num3 = Mathf.Min(num, num2); num2 -= num3; ((Vector3)(ref val))..ctor(((float)rng.NextDouble() - 0.5f) * 1.2f, 0.15f, ((float)rng.NextDouble() - 0.5f) * 1.2f); GameObject val2 = Object.Instantiate<GameObject>(prefab2, seabed + val, Quaternion.Euler(0f, (float)rng.NextDouble() * 360f, 0f)); ItemDrop component2 = val2.GetComponent<ItemDrop>(); if ((Object)(object)component2 != (Object)null) { component2.m_itemData.m_stack = num3; if (rule.HasDurabilityRange && component2.m_itemData.m_shared.m_useDurability && component2.m_itemData.GetMaxDurability() > 0f) { float num4 = Mathf.Lerp(rule.MinDurability, rule.MaxDurability, (float)rng.NextDouble()); component2.m_itemData.m_durability = Mathf.Max(1f, component2.m_itemData.GetMaxDurability() * num4); } } } } private void OnDestroy() { _store?.Save(); } } internal readonly struct CellCoord : IEquatable<CellCoord> { public readonly int X; public readonly int Z; public Vector3 Center => new Vector3(((float)X + 0.5f) * Plugin.CellSize, 0f, ((float)Z + 0.5f) * Plugin.CellSize); public CellCoord(int x, int z) { X = x; Z = z; } public static CellCoord FromWorld(Vector3 p) { //IL_0000: 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) return new CellCoord(Mathf.FloorToInt(p.x / Plugin.CellSize), Mathf.FloorToInt(p.z / Plugin.CellSize)); } public int StableSeed() { int num = 17; num = num * 31 + X; return num * 31 + Z; } public bool Equals(CellCoord other) { return X == other.X && Z == other.Z; } public override bool Equals(object obj) { return obj is CellCoord other && Equals(other); } public override int GetHashCode() { return (X * 397) ^ Z; } public override string ToString() { return $"{X},{Z}"; } } internal sealed class LootRule { public string Prefab; public float Chance; public int MinAmount; public int MaxAmount; public float MinimumDepth; public float MinimumDistanceFromCenter; public bool HasDurabilityRange; public float MinDurability; public float MaxDurability; public static List<LootRule> ParseList(string text, ManualLogSource log) { List<LootRule> list = new List<LootRule>(); if (string.IsNullOrWhiteSpace(text)) { return list; } string[] array = text.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); string[] array2 = array; foreach (string text2 in array2) { string[] array3 = text2.Split(new char[1] { ',' }); if (array3.Length != 6 && array3.Length != 8) { log.LogWarning((object)("Invalid loot entry '" + text2 + "'. Expected Prefab,Chance,MinAmount,MaxAmount,MinimumDepth,MinimumDistanceFromCenter[,MinDurability,MaxDurability].")); continue; } string text3 = array3[0].Trim(); if (string.IsNullOrWhiteSpace(text3)) { continue; } if (!float.TryParse(array3[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || !int.TryParse(array3[2].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2) || !int.TryParse(array3[3].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result3) || !float.TryParse(array3[4].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result4) || !float.TryParse(array3[5].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result5)) { log.LogWarning((object)("Invalid numeric value in loot entry '" + text2 + "'.")); continue; } if (result < 0f || result > 1f) { log.LogWarning((object)("Chance for '" + text3 + "' must be between 0 and 1. Entry skipped.")); continue; } if (result2 < 1 || result3 < result2) { log.LogWarning((object)("Invalid amount range for '" + text3 + "'. Entry skipped.")); continue; } if (result4 < 0f || result5 < 0f) { log.LogWarning((object)("MinimumDepth for '" + text3 + "' cannot be negative. Entry skipped.")); continue; } LootRule lootRule = new LootRule { Prefab = text3, Chance = result, MinAmount = result2, MaxAmount = result3, MinimumDepth = result4, MinimumDistanceFromCenter = result5 }; if (array3.Length == 8) { if (!float.TryParse(array3[6].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result6) || !float.TryParse(array3[7].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result7) || result6 < 0f || result7 > 1f || result7 < result6) { log.LogWarning((object)("Invalid durability range in loot entry '" + text2 + "'.")); continue; } lootRule.HasDurabilityRange = true; lootRule.MinDurability = result6; lootRule.MaxDurability = result7; } list.Add(lootRule); } return list; } } internal static class WorldQueries { private static readonly MethodInfo FindHeightmap = AccessTools.Method(typeof(Heightmap), "FindHeightmap", new Type[1] { typeof(Vector3) }, (Type[])null); private static readonly MethodInfo HeightmapGetBiome = typeof(Heightmap).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == "GetBiome" && m.ReturnType == typeof(Biome) && m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == typeof(Vector3)); private static readonly MethodInfo ZoneGetGroundHeight = typeof(ZoneSystem).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == "GetGroundHeight" && m.ReturnType == typeof(bool) && m.GetParameters().Length >= 2 && m.GetParameters()[0].ParameterType == typeof(Vector3)); private static readonly MethodInfo ZoneGetWaterLevel = typeof(ZoneSystem).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == "GetWaterLevel" && m.GetParameters().Length >= 1 && m.GetParameters()[0].ParameterType == typeof(Vector3)); public static bool TryGetNaturalSeabed(Vector3 xz, out Vector3 seabed, out float waterLevel, out float depth, out Biome biome) { //IL_0002: 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_012c: 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_0133: Expected I4, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Expected I4, but got Unknown //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Expected I4, but got Unknown //IL_00b8: Unknown result type (might be due to invalid IL or missing references) seabed = default(Vector3); waterLevel = 0f; depth = 0f; biome = (Biome)0; if ((Object)(object)ZoneSystem.instance == (Object)null) { return false; } if (!TryGroundHeight(xz, out var height)) { return false; } Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(xz.x, height, xz.z); if (!TryWaterLevel(val, out waterLevel)) { return false; } depth = waterLevel - height; if (depth <= 0.05f) { return false; } Heightmap val2 = null; try { if (FindHeightmap != null) { object? obj = FindHeightmap.Invoke(null, new object[1] { val }); val2 = (Heightmap)((obj is Heightmap) ? obj : null); } } catch { } if ((Object)(object)val2 == (Object)null) { return false; } try { if (HeightmapGetBiome != null) { biome = (Biome)(int)(Biome)HeightmapGetBiome.Invoke(val2, new object[1] { val }); } else { biome = (Biome)(int)Heightmap.FindBiome(val); } } catch { try { biome = (Biome)(int)Heightmap.FindBiome(val); } catch { return false; } } seabed = val; return (int)biome != 0; } private static bool TryGroundHeight(Vector3 p, out float height) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) height = 0f; if (ZoneGetGroundHeight == null) { return false; } try { ParameterInfo[] parameters = ZoneGetGroundHeight.GetParameters(); object[] array = new object[parameters.Length]; array[0] = p; for (int i = 1; i < parameters.Length; i++) { Type parameterType = parameters[i].ParameterType; Type type = (parameterType.IsByRef ? parameterType.GetElementType() : parameterType); array[i] = ((type == typeof(float)) ? ((object)0f) : ((type == typeof(Vector3)) ? ((object)Vector3.zero) : (type.IsValueType ? Activator.CreateInstance(type) : null))); } if (!(ZoneGetGroundHeight.Invoke(ZoneSystem.instance, array) is bool flag) || !flag) { return false; } for (int j = 1; j < parameters.Length; j++) { Type type2 = (parameters[j].ParameterType.IsByRef ? parameters[j].ParameterType.GetElementType() : parameters[j].ParameterType); if (type2 == typeof(float)) { height = (float)array[j]; return true; } } } catch { } return false; } private static bool TryWaterLevel(Vector3 p, out float water) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) water = 0f; if (ZoneGetWaterLevel != null) { try { ParameterInfo[] parameters = ZoneGetWaterLevel.GetParameters(); object[] array = new object[parameters.Length]; array[0] = p; for (int i = 1; i < parameters.Length; i++) { Type parameterType = parameters[i].ParameterType; Type type = (parameterType.IsByRef ? parameterType.GetElementType() : parameterType); array[i] = ((type == typeof(float)) ? ((object)0f) : ((type == typeof(Vector3)) ? ((object)Vector3.zero) : (type.IsValueType ? Activator.CreateInstance(type) : null))); } object obj = ZoneGetWaterLevel.Invoke(ZoneSystem.instance, array); if (obj is float num) { water = num; return !float.IsNaN(num); } bool flag = default(bool); int num2; if (obj is bool) { flag = (bool)obj; num2 = 1; } else { num2 = 0; } if (((uint)num2 & (flag ? 1u : 0u)) != 0) { for (int j = 1; j < parameters.Length; j++) { Type type2 = (parameters[j].ParameterType.IsByRef ? parameters[j].ParameterType.GetElementType() : parameters[j].ParameterType); if (type2 == typeof(float)) { water = (float)array[j]; return true; } } } } catch { } } try { FieldInfo fieldInfo = AccessTools.Field(typeof(ZoneSystem), "m_waterLevel"); if (fieldInfo != null) { water = Convert.ToSingle(fieldInfo.GetValue(ZoneSystem.instance)); return true; } } catch { } return false; } } internal sealed class ProcessedCellStore { private readonly HashSet<CellCoord> _cells = new HashSet<CellCoord>(); private readonly ManualLogSource _log; private string _loadedWorld = ""; private string _path = ""; private bool _dirty; public ProcessedCellStore(ManualLogSource log) { _log = log; } public bool IsProcessed(CellCoord c) { EnsureWorld(); return _cells.Contains(c); } public void MarkProcessed(CellCoord c) { EnsureWorld(); if (_cells.Add(c)) { _dirty = true; if ((_cells.Count & 0x7F) == 0) { Save(); } } } private void EnsureWorld() { string worldKey = GetWorldKey(); if (worldKey == _loadedWorld) { return; } Save(); _cells.Clear(); _loadedWorld = worldKey; string text = MakeSafeFileName(worldKey); string text2 = Path.Combine(Paths.ConfigPath, "DeepSeaTreasures"); Directory.CreateDirectory(text2); _path = Path.Combine(text2, "processed_" + text + ".txt"); if (!File.Exists(_path)) { return; } string[] array = File.ReadAllLines(_path); foreach (string text3 in array) { string[] array2 = text3.Split(new char[1] { ',' }); if (array2.Length == 2 && int.TryParse(array2[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && int.TryParse(array2[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2)) { _cells.Add(new CellCoord(result, result2)); } } _log.LogInfo((object)$"Loaded {_cells.Count} processed treasure cells for world '{worldKey}'."); } public void Save() { if (!_dirty || string.IsNullOrEmpty(_path)) { return; } try { using (StreamWriter streamWriter = new StreamWriter(_path, append: false)) { foreach (CellCoord cell in _cells) { int x = cell.X; string text = x.ToString(CultureInfo.InvariantCulture); x = cell.Z; streamWriter.WriteLine(text + "," + x.ToString(CultureInfo.InvariantCulture)); } } _dirty = false; } catch (Exception ex) { _log.LogWarning((object)("Could not save processed-cell database: " + ex.Message)); } } private static string GetWorldKey() { try { if ((Object)(object)ZNet.instance != (Object)null) { World world = ZNet.instance.GetWorld(); if (world != null) { return world.m_name + "_" + world.m_seedName; } } } catch { } return "unknown_world"; } private static string MakeSafeFileName(string s) { char[] invalidFileNameChars = Path.GetInvalidFileNameChars(); foreach (char oldChar in invalidFileNameChars) { s = s.Replace(oldChar, '_'); } return s; } } }