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 BetterOreMining v1.0.0
BetterOreMining.dll
Decompiled 2 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BetterOreMining.Config; using BetterOreMining.Features; using BetterOreMining.Infrastructure; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("BetterOreMining")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+7c103c8b5af121683d895a79b51f152b3ba67084")] [assembly: AssemblyProduct("BetterOreMining")] [assembly: AssemblyTitle("BetterOreMining")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BetterOreMining { [BepInPlugin("JevMods.BetterOreMining", "BetterOreMining", "1.0.0")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "JevMods.BetterOreMining"; public const string PluginName = "BetterOreMining"; private IFeature[] _features; private Harmony _harmony; private void Awake() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown GameEvents events = (GameEvents.Instance = new GameEvents()); _features = CreateFeatures(events, new ModSettings(((BaseUnityPlugin)this).Config), LoadShader()); IFeature[] features = _features; for (int i = 0; i < features.Length; i++) { features[i].Enable(); } _harmony = new Harmony("JevMods.BetterOreMining"); _harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded"); } private void Update() { GameEvents.Instance?.RaiseFrameUpdated(); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } if (_features != null) { IFeature[] features = _features; for (int i = 0; i < features.Length; i++) { features[i].Disable(); } } GameEvents.Instance = null; } private Shader LoadShader() { return ShaderBundle.Load(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "assets", "betteroremining")); } private static IFeature[] CreateFeatures(IGameEvents events, ModSettings settings, Shader rippleShader) { OreReachFeature oreReachFeature = new OreReachFeature(events, new PhysicsOreScanner()); if (!((Object)(object)rippleShader == (Object)null)) { RippleFeature rippleFeature = new RippleFeature(events, settings, new PhysicsVeinScanner(), new ZoneGroundProbe(), new OverlayGlowRenderer(rippleShader, settings, new GroundTextures())); return new IFeature[2] { rippleFeature, oreReachFeature }; } return new IFeature[1] { oreReachFeature }; } } internal static class BuildInfo { public const string Version = "1.0.0"; } } namespace BetterOreMining.Patches { internal static class AttackPatches { [HarmonyPatch(typeof(Attack), "DoMeleeAttack")] private static class DoMeleeAttack { private static void Prefix(Attack __instance) { GameEvents.Instance?.RaiseMeleeAttackStarting(__instance); } } [HarmonyPatch(typeof(Attack), "AddHitPoint")] private static class AddHitPoint { private static void Postfix(Attack __instance, GameObject go, Vector3 point) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (IsLocalPickaxe(__instance) && !IsDynamic(go)) { GameEvents.Instance?.RaisePickaxeStruck(point); } } private static bool IsLocalPickaxe(Attack attack) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 bool num = (Object)(object)attack.m_character == (Object)(object)Player.m_localPlayer; ItemData weapon = attack.m_weapon; bool flag = weapon != null && (int)weapon.m_shared.m_skillType == 12; return num && flag; } private static bool IsDynamic(GameObject go) { return (Object)(object)go.GetComponentInParent<Rigidbody>() != (Object)null; } } } } namespace BetterOreMining.Infrastructure { public sealed class GameEvents : IGameEvents { internal static GameEvents Instance { get; set; } public event Action<Attack> MeleeAttackStarting; public event Action<Vector3> PickaxeStruck; public event Action FrameUpdated; internal void RaiseMeleeAttackStarting(Attack attack) { this.MeleeAttackStarting?.Invoke(attack); } internal void RaisePickaxeStruck(Vector3 point) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) this.PickaxeStruck?.Invoke(point); } internal void RaiseFrameUpdated() { this.FrameUpdated?.Invoke(); } } public sealed class GroundTextures { private readonly Dictionary<GroundMap, Texture2D> _textures = new Dictionary<GroundMap, Texture2D>(); private readonly List<GroundMap> _stale = new List<GroundMap>(); public Texture2D Get(GroundMap ground) { if (!_textures.TryGetValue(ground, out var value)) { value = Upload(ground); _textures[ground] = value; } return value; } public void KeepOnly(IReadOnlyList<RippleWave> waves) { _stale.Clear(); foreach (GroundMap key in _textures.Keys) { if (!IsUsed(key, waves)) { _stale.Add(key); } } foreach (GroundMap item in _stale) { Object.Destroy((Object)(object)_textures[item]); _textures.Remove(item); } } private static bool IsUsed(GroundMap ground, IReadOnlyList<RippleWave> waves) { foreach (RippleWave wave in waves) { if (wave.Ground == ground) { return true; } } return false; } private static Texture2D Upload(GroundMap ground) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown Texture2D val = new Texture2D(32, 32, (TextureFormat)18, false, true) { wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1 }; val.SetPixelData<float>(ground.Heights, 0, 0); val.Apply(false, true); return val; } } internal static class OreRocks { private const string DepositPrefix = "MineRock_"; private static readonly string[] OreSuffixes = new string[2] { "Ore", "OreNew" }; private static readonly string[] OreItems = new string[4] { "Obsidian", "IronScrap", "CopperScrap", "Softtissue" }; public static bool IsOre(GameObject target) { if ((Object)(object)target == (Object)null) { return false; } MineRock5 component = target.GetComponent<MineRock5>(); if ((Object)(object)component != (Object)null) { return DropsOre(component.m_dropItems); } MineRock component2 = target.GetComponent<MineRock>(); if ((Object)(object)component2 != (Object)null) { return DropsOre(component2.m_dropItems); } Destructible component3 = target.GetComponent<Destructible>(); if ((Object)(object)component3 != (Object)null) { return IsOreWhenIntact(target, component3); } return false; } private static bool IsOreWhenIntact(GameObject target, Destructible intact) { DropOnDestroyed component = target.GetComponent<DropOnDestroyed>(); if (((Object)target).name.StartsWith("MineRock_") && (Object)(object)component != (Object)null && DropsOre(component.m_dropWhenDestroyed)) { return true; } GameObject spawnWhenDestroyed = intact.m_spawnWhenDestroyed; if ((Object)(object)spawnWhenDestroyed != (Object)null) { return IsFracturedOre(spawnWhenDestroyed); } return false; } private static bool IsFracturedOre(GameObject fractured) { MineRock5 component = fractured.GetComponent<MineRock5>(); if ((Object)(object)component != (Object)null) { return DropsOre(component.m_dropItems); } MineRock component2 = fractured.GetComponent<MineRock>(); if ((Object)(object)component2 != (Object)null) { return DropsOre(component2.m_dropItems); } return false; } private static bool DropsOre(DropTable table) { //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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (table == null) { return false; } foreach (DropData drop in table.m_drops) { if ((Object)(object)drop.m_item != (Object)null && IsOreItem(((Object)drop.m_item).name)) { return true; } } return false; } private static bool IsOreItem(string name) { string[] oreSuffixes = OreSuffixes; foreach (string value in oreSuffixes) { if (name.EndsWith(value)) { return true; } } return Array.IndexOf(OreItems, name) >= 0; } } public sealed class OverlayGlowRenderer : IGlowRenderer { private const int DepthPass = 0; private const int RingPass = 1; private const float DepthAboveMain = 0.5f; private const float CharacterRange = 40f; private const CameraEvent DrawEvent = (CameraEvent)17; private static readonly int CenterId = Shader.PropertyToID("_Center"); private static readonly int FrontId = Shader.PropertyToID("_Front"); private static readonly int WidthId = Shader.PropertyToID("_Width"); private static readonly int OpacityId = Shader.PropertyToID("_Opacity"); private static readonly int VisibleId = Shader.PropertyToID("_VisibleColor"); private static readonly int BlockedId = Shader.PropertyToID("_BlockedColor"); private static readonly int GroundMapId = Shader.PropertyToID("_GroundMap"); private static readonly int GroundRectId = Shader.PropertyToID("_GroundRect"); private readonly Material _material; private readonly IColorSettings _colors; private readonly GroundTextures _groundTextures; private readonly CommandBuffer _commands = new CommandBuffer { name = "BetterOreMining" }; private readonly List<Renderer> _characterParts = new List<Renderer>(); private readonly HashSet<Renderer> _depthDrawn = new HashSet<Renderer>(); private IReadOnlyList<RippleWave> _waves = Array.Empty<RippleWave>(); private float _ringWidth; private bool _subscribed; private Camera _overlay; public OverlayGlowRenderer(Shader shader, IColorSettings colors, GroundTextures groundTextures) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown _material = new Material(shader); _colors = colors; _groundTextures = groundTextures; } public void Draw(IReadOnlyList<RippleWave> waves, float ringWidth) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown _waves = waves; _ringWidth = ringWidth; _groundTextures.KeepOnly(waves); if (!_subscribed) { Camera.onPreCull = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(OnPreCull)); _subscribed = true; } SyncOverlay(); } public void Clear() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown _waves = Array.Empty<RippleWave>(); _groundTextures.KeepOnly(_waves); if (_subscribed) { Camera.onPreCull = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(OnPreCull)); _subscribed = false; } if ((Object)(object)_overlay != (Object)null) { ((Behaviour)_overlay).enabled = false; } } private static bool IsShown(Renderer renderer) { if ((Object)(object)renderer != (Object)null && renderer.enabled) { return ((Component)renderer).gameObject.activeInHierarchy; } return false; } private static bool IsMesh(Renderer renderer) { if (!(renderer is MeshRenderer)) { return renderer is SkinnedMeshRenderer; } return true; } private void SyncOverlay() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; if (!((Object)(object)main == (Object)null)) { if ((Object)(object)_overlay == (Object)null) { _overlay = new GameObject("BetterOreMining.Overlay").AddComponent<Camera>(); } if ((Object)(object)((Component)_overlay).transform.parent != (Object)(object)((Component)main).transform) { ((Component)_overlay).transform.SetParent(((Component)main).transform, false); } _overlay.CopyFrom(main); _overlay.clearFlags = (CameraClearFlags)3; _overlay.cullingMask = 0; _overlay.renderingPath = (RenderingPath)1; _overlay.depth = main.depth + 0.5f; if (_overlay.commandBufferCount == 0) { _overlay.AddCommandBuffer((CameraEvent)17, _commands); } ((Behaviour)_overlay).enabled = true; } } private void OnPreCull(Camera camera) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)camera != (Object)(object)_overlay) { return; } _commands.Clear(); _depthDrawn.Clear(); AddCharacterDepth(((Component)camera).transform.position); foreach (RippleWave wave in _waves) { AddOreDepth(wave); } _commands.SetGlobalColor(VisibleId, _colors.VisibleColor); _commands.SetGlobalColor(BlockedId, _colors.BlockedColor); _commands.SetGlobalFloat(WidthId, _ringWidth); foreach (RippleWave wave2 in _waves) { AddRing(wave2); } } private void AddCharacterDepth(Vector3 viewpoint) { //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_002c: Unknown result type (might be due to invalid IL or missing references) float num = 1600f; foreach (Character allCharacter in Character.GetAllCharacters()) { Vector3 val = ((Component)allCharacter).transform.position - viewpoint; if (!(((Vector3)(ref val)).sqrMagnitude < num)) { continue; } ((Component)allCharacter).GetComponentsInChildren<Renderer>(false, _characterParts); foreach (Renderer characterPart in _characterParts) { if (IsMesh(characterPart)) { DrawIfShown(characterPart, 0); } } } } private void AddOreDepth(RippleWave wave) { Renderer[] ore = wave.Ore; foreach (Renderer val in ore) { if (_depthDrawn.Add(val)) { DrawIfShown(val, 0); } } } private void AddRing(RippleWave wave) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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_0088: 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_009f: Unknown result type (might be due to invalid IL or missing references) GroundMap ground = wave.Ground; float num = 1f / ground.Size; _commands.SetGlobalVector(CenterId, Vector4.op_Implicit(wave.Center)); _commands.SetGlobalFloat(FrontId, wave.Front); _commands.SetGlobalFloat(OpacityId, wave.Alpha); _commands.SetGlobalTexture(GroundMapId, RenderTargetIdentifier.op_Implicit((Texture)(object)_groundTextures.Get(ground))); _commands.SetGlobalVector(GroundRectId, new Vector4(ground.Origin.x, ground.Origin.y, num, num)); Renderer[] ore = wave.Ore; foreach (Renderer renderer in ore) { DrawIfShown(renderer, 1); } } private void DrawIfShown(Renderer renderer, int pass) { if (IsShown(renderer)) { int num = renderer.sharedMaterials.Length; for (int i = 0; i < num; i++) { _commands.DrawRenderer(renderer, _material, i, pass); } } } } public sealed class PhysicsOreScanner : IOreScanner { public bool TryFindOre(Vector3 origin, Vector3 direction, float radius, float maxDistance, out float distance) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) distance = 0f; RaycastHit val = default(RaycastHit); if (!Physics.SphereCast(origin, radius, direction, ref val, maxDistance, Attack.m_attackMask, (QueryTriggerInteraction)1)) { return false; } GameObject target = Projectile.FindHitObject(((RaycastHit)(ref val)).collider); distance = ((RaycastHit)(ref val)).distance; return OreRocks.IsOre(target); } } public sealed class PhysicsVeinScanner : IVeinScanner { private static readonly Collider[] Colliders = (Collider[])(object)new Collider[256]; public VeinScan Scan(Vector3 center, float radius) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0056: 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_005b: Unknown result type (might be due to invalid IL or missing references) int num = Physics.OverlapSphereNonAlloc(center, radius, Colliders, Attack.m_attackMask, (QueryTriggerInteraction)1); HashSet<GameObject> hashSet = new HashSet<GameObject>(); float num2 = radius; for (int i = 0; i < num; i++) { Collider val = Colliders[i]; GameObject val2 = Projectile.FindHitObject(val); if (OreRocks.IsOre(val2)) { hashSet.Add(val2); Bounds bounds = val.bounds; Vector3 val3 = ((Bounds)(ref bounds)).ClosestPoint(center); num2 = Mathf.Min(num2, Vector3.Distance(val3, center)); } } List<Renderer> list = new List<Renderer>(); foreach (GameObject item in hashSet) { list.AddRange((IEnumerable<Renderer>)(object)item.GetComponentsInChildren<MeshRenderer>()); } return new VeinScan(list.ToArray(), num2); } } internal static class ShaderBundle { public static Shader Load(string path) { if (!File.Exists(path)) { return null; } AssetBundle val = AssetBundle.LoadFromFile(path); if ((Object)(object)val == (Object)null) { return null; } Shader[] array = val.LoadAllAssets<Shader>(); if (array.Length == 0 || !array[0].isSupported) { return null; } return array[0]; } } public sealed class ZoneGroundProbe : IGroundProbe { public float GroundHeight(Vector3 point) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return ZoneSystem.instance.GetGroundHeight(point); } } } namespace BetterOreMining.Features { public sealed class GroundMap { public const int Resolution = 32; public Vector2 Origin { get; } public float Size { get; } public float[] Heights { get; } private GroundMap(Vector2 origin, float size, float[] heights) { //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) Origin = origin; Size = size; Heights = heights; } public static GroundMap Sample(IGroundProbe ground, Vector3 center, float radius) { //IL_0012: 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_0097: 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_0050: 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_0077: Unknown result type (might be due to invalid IL or missing references) float num = radius * 2f; float num2 = num / 32f; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(center.x - radius, center.z - radius); float[] array = new float[1024]; Vector3 point = default(Vector3); for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { ((Vector3)(ref point))..ctor(val.x + ((float)j + 0.5f) * num2, center.y, val.y + ((float)i + 0.5f) * num2); array[i * 32 + j] = ground.GroundHeight(point); } } return new GroundMap(val, num, array); } } public interface IColorSettings { Color VisibleColor { get; } Color BlockedColor { get; } } public interface IFeature { void Enable(); void Disable(); } public interface IGameEvents { event Action<Attack> MeleeAttackStarting; event Action<Vector3> PickaxeStruck; event Action FrameUpdated; } public interface IGlowRenderer { void Draw(IReadOnlyList<RippleWave> waves, float ringWidth); void Clear(); } public interface IGroundProbe { float GroundHeight(Vector3 point); } public interface IOreScanner { bool TryFindOre(Vector3 origin, Vector3 direction, float radius, float maxDistance, out float distance); } public interface IRippleSettings { float Radius { get; } float WaveSpeed { get; } float RingWidth { get; } float Opacity { get; } } public interface IVeinScanner { VeinScan Scan(Vector3 center, float radius); } public sealed class OreReachFeature : IFeature { private const float MaxReach = 4f; private const float ReachMargin = 0.5f; private const float MaxPitchDegrees = 45f; private const float MinRayWidth = 0.2f; private readonly IGameEvents _events; private readonly IOreScanner _scanner; public OreReachFeature(IGameEvents events, IOreScanner scanner) { _events = events; _scanner = scanner; } public void Enable() { _events.MeleeAttackStarting += OnMeleeAttackStarting; } public void Disable() { _events.MeleeAttackStarting -= OnMeleeAttackStarting; } private static bool IsLocalPickaxeSwing(Attack attack) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 bool num = (Object)(object)attack.m_character == (Object)(object)Player.m_localPlayer; bool flag = (int)attack.m_weapon.m_shared.m_skillType == 12; return num && flag; } private void OnMeleeAttackStarting(Attack attack) { //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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: 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_0080: Unknown result type (might be due to invalid IL or missing references) if (IsLocalPickaxeSwing(attack)) { float maxYAngle = attack.m_maxYAngle; attack.m_maxYAngle = Mathf.Max(maxYAngle, 45f); Transform val = default(Transform); Vector3 direction = default(Vector3); attack.GetMeleeAttackDir(ref val, ref direction); Vector3 origin = val.position + Vector3.up * attack.m_attackHeight + ((Component)attack.m_character).transform.right * attack.m_attackOffset; float num = Mathf.Max(attack.m_attackRayWidth, 0.2f); if (!_scanner.TryFindOre(origin, direction, num, 4f, out var distance)) { attack.m_maxYAngle = maxYAngle; return; } attack.m_hitTerrain = false; attack.m_attackRange = Mathf.Max(attack.m_attackRange, distance + num + 0.5f); } } } public sealed class RippleFeature : IFeature { private const int MaxWaves = 4; private readonly IGameEvents _events; private readonly IRippleSettings _settings; private readonly IVeinScanner _scanner; private readonly IGroundProbe _ground; private readonly IGlowRenderer _renderer; private readonly List<RippleWave> _waves = new List<RippleWave>(); private int _strikeFrame = -1; private Vector3? _pendingStrike; public RippleFeature(IGameEvents events, IRippleSettings settings, IVeinScanner scanner, IGroundProbe ground, IGlowRenderer renderer) { _events = events; _settings = settings; _scanner = scanner; _ground = ground; _renderer = renderer; } public void Enable() { _events.PickaxeStruck += OnPickaxeStruck; _events.FrameUpdated += OnFrameUpdated; } public void Disable() { _events.PickaxeStruck -= OnPickaxeStruck; _events.FrameUpdated -= OnFrameUpdated; _pendingStrike = null; _waves.Clear(); _renderer.Clear(); } private void OnPickaxeStruck(Vector3 point) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (Time.frameCount != _strikeFrame) { _strikeFrame = Time.frameCount; _pendingStrike = point; } } private void StartWave(Vector3 point) { //IL_0012: 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_0051: Unknown result type (might be due to invalid IL or missing references) float radius = _settings.Radius; VeinScan veinScan = _scanner.Scan(point, radius); if (veinScan.Renderers.Length != 0) { if (_waves.Count == 4) { _waves.RemoveAt(0); } _waves.Add(new RippleWave(point, veinScan.Renderers, GroundMap.Sample(_ground, point, radius), Time.time, veinScan.NearestDistance)); } } private void OnFrameUpdated() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (_pendingStrike.HasValue && Time.frameCount > _strikeFrame) { StartWave(_pendingStrike.Value); _pendingStrike = null; } if (_waves.Count == 0) { return; } foreach (RippleWave wave in _waves) { wave.Advance(Time.time, _settings); } _waves.RemoveAll((RippleWave wave) => wave.IsFinished); if (_waves.Count == 0) { _renderer.Clear(); } else { _renderer.Draw(_waves, _settings.RingWidth); } } } public static class RippleTimeline { public static float Front(float elapsed, float waveSpeed) { return elapsed * waveSpeed; } public static float End(float radius, float ringWidth) { return radius + ringWidth; } public static bool IsFinished(float front, float radius, float ringWidth) { return front >= End(radius, ringWidth); } public static float Fade(float front, float radius, float ringWidth) { return 1f - Mathf.Clamp01(front / End(radius, ringWidth)); } } public sealed class RippleWave { private readonly float _startTime; private readonly float _startFront; public Vector3 Center { get; } public Renderer[] Ore { get; } public GroundMap Ground { get; } public float Front { get; private set; } public float Alpha { get; private set; } public bool IsFinished { get; private set; } public RippleWave(Vector3 center, Renderer[] ore, GroundMap ground, float startTime, float startFront) { //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) Center = center; Ore = ore; Ground = ground; _startTime = startTime; _startFront = startFront; } public void Advance(float now, IRippleSettings settings) { float num = RippleTimeline.Front(now - _startTime, settings.WaveSpeed); Front = _startFront + num; float num2 = RippleTimeline.Fade(Front, settings.Radius, settings.RingWidth); Alpha = settings.Opacity * num2; IsFinished = RippleTimeline.IsFinished(Front, settings.Radius, settings.RingWidth); } } public sealed class VeinScan { public Renderer[] Renderers { get; } public float NearestDistance { get; } public VeinScan(Renderer[] renderers, float nearestDistance) { Renderers = renderers; NearestDistance = nearestDistance; } } } namespace BetterOreMining.Config { public sealed class ModSettings : IRippleSettings, IColorSettings { private readonly ConfigEntry<float> _radius; private readonly ConfigEntry<float> _waveSpeed; private readonly ConfigEntry<float> _ringWidth; private readonly ConfigEntry<float> _opacity; private readonly ConfigEntry<Color> _visibleColor; private readonly ConfigEntry<Color> _blockedColor; public float Radius => _radius.Value; public float WaveSpeed => _waveSpeed.Value; public float RingWidth => _ringWidth.Value; public float Opacity => _opacity.Value; public Color VisibleColor => _visibleColor.Value; public Color BlockedColor => _blockedColor.Value; public ModSettings(ConfigFile file) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Expected O, but got Unknown //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) _radius = file.Bind<float>("Ripple", "Radius", 8f, new ConfigDescription("How far the ripple spreads from where you hit, in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 40f), Array.Empty<object>())); _waveSpeed = file.Bind<float>("Ripple", "WaveSpeed", 4.5f, new ConfigDescription("How fast the ripple spreads, in meters per second.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 100f), Array.Empty<object>())); _ringWidth = file.Bind<float>("Ripple", "RingWidth", 2f, new ConfigDescription("How thick the glowing ring is, in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 10f), Array.Empty<object>())); _opacity = file.Bind<float>("Ripple", "Opacity", 0.8f, new ConfigDescription("How strong the ring is at its brightest, from 0 to 1.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>())); _visibleColor = file.Bind<Color>("Colors", "Visible", new Color(0.2f, 1f, 0.35f, 1f), "Ring color on ore at or above the ground, as RGBA hex (RRGGBBAA)."); _blockedColor = file.Bind<Color>("Colors", "Blocked", new Color(1f, 0.15f, 0.1f, 1f), "Ring color on ore buried 2 meters or deeper, as RGBA hex (RRGGBBAA)."); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }