Decompiled source of MineLab v1.0.0
Bonelab/Mods/Bonecraft.dll
Decompiled 20 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.MemoryMappedFiles; using System.Net.WebSockets; using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using BoneLib; using BoneLib.BoneMenu; using Bonecraft; using Bonecraft.Geo; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSLZ.Data; using Il2CppSLZ.Marrow; using Il2CppSLZ.Marrow.Data; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(BonecraftMod), "Bonecraft", "0.4.0", "Dante", null)] [assembly: MelonGame("Stress Level Zero", "BONELAB")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("Bonecraft")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Bonecraft")] [assembly: AssemblyTitle("Bonecraft")] [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 Bonecraft { internal sealed class BlockLook { private const string StandardShader = "SLZ/LitMAS/LitMAS Standard"; private const string CrackShader = "SLZ/Mod2x"; private static readonly string[] LitShaders = new string[2] { "Universal Render Pipeline/Lit", "Universal Render Pipeline/Simple Lit" }; private static readonly string[] UnlitShaders = new string[1] { "Universal Render Pipeline/Unlit" }; private static readonly string[] Maps = new string[9] { "_BumpMap", "_MetallicGlossMap", "_OcclusionMap", "_EmissionMap", "_DetailAlbedoMap", "_DetailNormalMap", "_DetailMask", "_ParallaxMap", "_SpecGlossMap" }; private static readonly string[] Keywords = new string[9] { "_NORMALMAP", "_EMISSION", "_METALLICSPECGLOSSMAP", "_DETAIL_MULX2", "_PARALLAXMAP", "_OCCLUSIONMAP", "_ALPHATEST_ON", "_ALPHABLEND_ON", "_SURFACE_TYPE_TRANSPARENT" }; private const HideFlags Keep = (HideFlags)32; private static readonly (string[] words, string block)[] Guesses = new(string[], string)[12] { (new string[3] { "grass", "lawn", "turf" }, "minecraft:grass_block"), (new string[5] { "dirt", "soil", "mud", "earth", "ground" }, "minecraft:dirt"), (new string[3] { "sand", "desert", "beach" }, "minecraft:sand"), (new string[1] { "gravel" }, "minecraft:gravel"), (new string[2] { "snow", "ice" }, "minecraft:snow_block"), (new string[1] { "brick" }, "minecraft:bricks"), (new string[5] { "wood", "plank", "timber", "crate", "log" }, "minecraft:oak_planks"), (new string[2] { "glass", "window" }, "minecraft:glass"), (new string[6] { "metal", "steel", "iron", "pipe", "vent", "grate" }, "minecraft:iron_block"), (new string[3] { "tile", "marble", "lab" }, "minecraft:smooth_stone"), (new string[2] { "lava", "magma" }, "minecraft:magma_block"), (new string[8] { "concrete", "cement", "rock", "stone", "cliff", "cave", "wall", "floor" }, "minecraft:stone") }; private readonly Link link; private readonly Instance log; private readonly Dictionary<string, Material> materials = new Dictionary<string, Material>(); private readonly Dictionary<string, List<Material>> waiting = new Dictionary<string, List<Material>>(); private readonly Dictionary<string, Texture2D> textures = new Dictionary<string, Texture2D>(); private readonly HashSet<string> requested = new HashSet<string>(); private readonly HashSet<string> seeThroughKeys = new HashSet<string>(); private readonly HashSet<string> missing = new HashSet<string>(); private Material template; private Texture2D roughMas; private bool warnedCracks; public BlockLook(Link link, Instance log) { this.link = link; this.log = log; link.Connected += Reask; } private void Reask() { requested.RemoveWhere((string k) => !textures.ContainsKey(k) && !missing.Contains(k)); foreach (string key in waiting.Keys) { if (requested.Add(key)) { link.Send(Json.Obj("t", "tex", "block", key)); } } } public void Reset() { materials.Clear(); waiting.Clear(); template = null; } public void SetTemplate(Material m) { if ((Object)(object)template == (Object)null && (Object)(object)m != (Object)null && (Object)(object)m.shader != (Object)null && m.renderQueue < 2450) { template = m; } } public Material For(string key) { return Get(key, key, 1f); } public Material Particle(string key) { return Get(key + "#particle", key, 0.6f); } public Material Crack(int stage) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: 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_006a: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) string key = "destroy:" + stage; if (materials.TryGetValue(key, out var value) && (Object)(object)value != (Object)null) { return value; } Shader val = Shader.Find("SLZ/Mod2x"); if ((Object)(object)val != (Object)null) { value = new Material(val) { name = "Bonecraft crack " + stage, hideFlags = (HideFlags)32 }; SetColor(value, "_Color", Color.white); SetFloat(value, "_Multiplier", 1f); SetFloat(value, "_alpha", 1f); SetFloat(value, "_AlphaCutoff", 0f); SetFloat(value, "_OffsetFactor", -1f); SetFloat(value, "_OffsetUnits", -1f); } else { value = Glow("SLZ/LitMAS/LitMAS Standard", "Bonecraft crack " + stage, 1f); if ((Object)(object)value == (Object)null) { if (!warnedCracks) { warnedCracks = true; log.Warning("no shader for cracks in this level: no crack animation"); } return null; } Blend(value, 2, 3); } materials[key] = value; Texture(key, value); return value; } private Material Glow(string shaderName, string name, float shade) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) Shader val = Shader.Find(shaderName); if ((Object)(object)val == (Object)null) { return null; } Material val2 = new Material(val) { name = name, hideFlags = (HideFlags)32 }; SetColor(val2, "_BaseColor", new Color(0f, 0f, 0f, 1f)); SetFloat(val2, "_Emission", 1f); val2.EnableKeyword("_EMISSION"); SetColor(val2, "_EmissionColor", new Color(shade, shade, shade, 1f)); Matte(val2); return val2; } private static void Blend(Material m, int src, int dst) { SetFloat(m, "_Surface", 1f); m.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); SetFloat(m, "_BlendSrc", src); SetFloat(m, "_BlendDst", dst); SetFloat(m, "_ZWrite", 0f); m.renderQueue = 3000; } private Material Get(string id, string textureKey, float shade) { if (materials.TryGetValue(id, out var value) && (Object)(object)value != (Object)null) { return value; } value = Create(textureKey, shade); ((Object)value).hideFlags = (HideFlags)32; materials[id] = value; Texture(textureKey, value); return value; } private void Texture(string key, Material m) { if (textures.TryGetValue(key, out var value) && (Object)(object)value != (Object)null) { Apply(m, value); if (seeThroughKeys.Contains(key) && m.renderQueue < 2450) { Blend(m, 5, 10); } return; } if (!waiting.TryGetValue(key, out var value2)) { value2 = (waiting[key] = new List<Material>()); } value2.Add(m); if (requested.Add(key)) { link.Send(Json.Obj("t", "tex", "block", key)); } } public unsafe void OnTexture(string key, int w, int h, string rgba) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: 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_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown if (rgba == null || w <= 0 || h <= 0) { log.Warning("Minecraft has no texture for " + key); missing.Add(key); return; } byte[] array = Convert.FromBase64String(rgba); if (key.StartsWith("destroy:")) { for (int i = 0; i + 3 < array.Length; i += 4) { if (array[i + 3] < 26) { int num = i; int num2 = i + 1; byte b; array[i + 2] = (b = 128); array[num] = (array[num2] = b); } array[i + 3] = byte.MaxValue; } } Texture2D val = new Texture2D(w, h, (TextureFormat)4, false) { name = "Bonecraft " + key, filterMode = (FilterMode)0, wrapMode = (TextureWrapMode)0, hideFlags = (HideFlags)32 }; fixed (byte* ptr = array) { val.LoadRawTextureData((IntPtr)ptr, array.Length); } val.Apply(false); textures[key] = val; bool flag = key.Contains('|') && SeeThrough(array); if (flag) { seeThroughKeys.Add(key); } if (!waiting.Remove(key, out var value)) { return; } foreach (Material item in value) { if ((Object)(object)item != (Object)null) { Apply(item, val); if (flag && item.renderQueue < 2450) { Blend(item, 5, 10); } } } } private static void Apply(Material m, Texture2D t) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) m.mainTexture = (Texture)(object)t; string[] array = new string[3] { "_BaseMap", "_MainTex", "_EmissionMap" }; foreach (string text in array) { if (m.HasProperty(text)) { m.SetTexture(text, (Texture)(object)t); m.SetTextureScale(text, Vector2.one); m.SetTextureOffset(text, Vector2.zero); } } } private static bool SeeThrough(byte[] rgba) { int num = 0; for (int i = 3; i < rgba.Length; i += 4) { if (rgba[i] < 200) { num++; } } return num > rgba.Length / 4 / 20; } private Material Create(string key, float shade) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Expected O, but got Unknown //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Expected O, but got Unknown //IL_010d: Unknown result type (might be due to invalid IL or missing references) Shader val = (BonecraftMod.Settings.UnlitBlocks.Value ? null : Shader.Find("SLZ/LitMAS/LitMAS Standard")); bool flag = (Object)(object)template != (Object)null && ((Object)template.shader).name.Contains("Triplanar", StringComparison.OrdinalIgnoreCase); Material val2; if ((Object)(object)val != (Object)null) { val2 = new Material(val); } else if ((Object)(object)template != (Object)null && !BonecraftMod.Settings.UnlitBlocks.Value && (!flag || (Object)(object)Find(LitShaders) == (Object)null)) { val2 = new Material(template); string[] maps = Maps; foreach (string text in maps) { if (val2.HasProperty(text)) { val2.SetTexture(text, (Texture)null); } } maps = Keywords; foreach (string text2 in maps) { val2.DisableKeyword(text2); } SetColor(val2, "_EmissionColor", Color.black); log.Msg($"{key}: a copy of {((Object)template).name} ({((Object)template.shader).name})"); } else { Shader val3 = Find(BonecraftMod.Settings.UnlitBlocks.Value ? UnlitShaders : LitShaders) ?? Find(UnlitShaders); if ((Object)(object)val3 == (Object)null) { throw new InvalidOperationException("no shader for blocks yet (none of the URP shaders is loaded)"); } val2 = new Material(val3); log.Msg(key + ": " + ((Object)val3).name); } ((Object)val2).name = "Bonecraft " + key; float num = BonecraftMod.Settings.BlockBrightness.Value * shade; Color c = default(Color); ((Color)(ref c))..ctor(num, num, num, 1f); SetColor(val2, "_BaseColor", c); SetColor(val2, "_Color", c); Matte(val2); return val2; } private unsafe void Matte(Material m) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown if ((Object)(object)roughMas == (Object)null) { roughMas = new Texture2D(1, 1, (TextureFormat)4, false, true) { name = "Bonecraft rough MAS", hideFlags = (HideFlags)32 }; byte[] array = new byte[4] { 0, 255, 0, 255 }; fixed (byte* ptr = array) { roughMas.LoadRawTextureData((IntPtr)ptr, array.Length); } roughMas.Apply(false); } string[] array2 = new string[3] { "_MetallicGlossMap", "_MASMap", "_MAS" }; foreach (string text in array2) { if (m.HasProperty(text)) { m.SetTexture(text, (Texture)(object)roughMas); } } SetFloat(m, "_Metallic", 0f); SetFloat(m, "_Smoothness", 0f); SetFloat(m, "_Glossiness", 0f); SetFloat(m, "_GlossMapScale", 0f); SetFloat(m, "_SpecularHighlights", 0f); SetFloat(m, "_EnvironmentReflections", 0f); m.EnableKeyword("_SPECULARHIGHLIGHTS_OFF"); m.EnableKeyword("_ENVIRONMENTREFLECTIONS_OFF"); } private static Shader Find(string[] names) { for (int i = 0; i < names.Length; i++) { Shader val = Shader.Find(names[i]); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static void SetColor(Material m, string p, Color c) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (m.HasProperty(p)) { m.SetColor(p, c); } } private static void SetFloat(Material m, string p, float f) { if (m.HasProperty(p)) { m.SetFloat(p, f); } } public static string Guess(Collider c, Renderer surface) { string text = Match(((Object)((Component)c).gameObject).name + " " + (((Object)(object)c.sharedMaterial != (Object)null) ? ((Object)c.sharedMaterial).name : "")); if (text != null) { return text; } if ((Object)(object)surface != (Object)null) { foreach (Material item in (Il2CppArrayBase<Material>)(object)surface.sharedMaterials) { if ((Object)(object)item != (Object)null && (text = Match(((Object)item).name + " " + ((Object)((Component)surface).gameObject).name)) != null) { return text; } } } return "minecraft:stone"; } private static string Match(string names) { string text = names.ToLowerInvariant(); (string[], string)[] guesses = Guesses; for (int i = 0; i < guesses.Length; i++) { (string[], string) tuple = guesses[i]; string[] item = tuple.Item1; string item2 = tuple.Item2; string[] array = item; foreach (string value in array) { if (text.Contains(value)) { return item2; } } } return null; } } internal sealed class Blocks { public sealed class Info { public float Hardness = 1.5f; public float Resistance = 6f; public string Hit; public string Break; public float Volume = 1f; public float Pitch = 1f; public bool Known; } private readonly Link link; private readonly Dictionary<string, Info> infos = new Dictionary<string, Info>(); private readonly HashSet<string> asked = new HashSet<string>(); public Blocks(Link link) { this.link = link; link.Connected += delegate { asked.RemoveWhere((string id) => !infos.TryGetValue(id, out var value) || !value.Known); }; } public Info InfoFor(string id) { if (!infos.TryGetValue(id, out var value)) { value = (infos[id] = new Info()); } if (!value.Known && asked.Add(id)) { link.Send(Json.Obj("t", "blockinfo", "block", id)); } return value; } public void OnInfo(JsonElement m) { string key = m.GetProperty("block").GetString(); if (!infos.TryGetValue(key, out var value)) { value = (infos[key] = new Info()); } if (m.TryGetProperty("hardness", out var value2)) { value.Hardness = value2.GetSingle(); value.Resistance = m.GetProperty("resistance").GetSingle(); value.Known = true; } if (m.TryGetProperty("sound", out var value3)) { value.Hit = value3.GetProperty("hit").GetString(); value.Break = value3.GetProperty("break").GetString(); value.Volume = value3.GetProperty("volume").GetSingle(); value.Pitch = value3.GetProperty("pitch").GetSingle(); } } } public sealed class BonecraftMod : MelonMod { internal static Settings Settings; private Link link; private PunchDetector left; private PunchDetector right; private Digger digger; private Weapons weapons; private MinecraftScreen screen; private bool levelReady; private bool keysBroken; private bool reportedRunning; private bool menuBuilt; private float nextRejectLog; public override void OnInitializeMelon() { Settings = new Settings(); ClassInjector.RegisterTypeInIl2Cpp<HitRelay>(); link = new Link(Settings.Url.Value, ((MelonBase)this).LoggerInstance); link.Start(); left = new PunchDetector("L"); right = new PunchDetector("R"); digger = new Digger(link, ((MelonBase)this).LoggerInstance); weapons = new Weapons(digger, ((MelonBase)this).LoggerInstance); Hooking.OnLevelLoaded += delegate(LevelInfo info) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) OnLevel(info.title); }; Hooking.OnLevelLoading += delegate { levelReady = false; }; Hooking.OnLevelUnloaded += delegate { levelReady = false; }; } private void OnLevel(string title) { levelReady = true; reportedRunning = false; digger.Reset(); weapons.Reset(); left.Reset(); right.Reset(); link.Send(Json.Obj("t", "hello", "game", "bonelab", "level", title)); BuildMenu(); if (Settings.ScreenEnabled.Value) { if (screen == null) { screen = new MinecraftScreen(Settings.ShmName.Value, ((MelonBase)this).LoggerInstance); } screen.Spawn(); } } private void BuildMenu() { //IL_002c: 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_006b: 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_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) if (menuBuilt || Page.Root == null) { return; } try { Settings s = Settings; Page obj = Page.Root.CreatePage("Bonecraft", Color.green, 0, true); obj.CreateBool("Bonecraft On", Color.green, s.Enabled.Value, (Action<bool>)delegate(bool v) { Set(s.Enabled, v); }); obj.CreateBool("Fists Break Blocks", Color.white, s.FistsBreak.Value, (Action<bool>)delegate(bool v) { Set(s.FistsBreak, v); }); obj.CreateBool("Guns Break Blocks", Color.white, s.GunsBreak.Value, (Action<bool>)delegate(bool v) { Set(s.GunsBreak, v); }); obj.CreateBool("Melee Breaks Blocks", Color.white, s.MeleeBreaks.Value, (Action<bool>)delegate(bool v) { Set(s.MeleeBreaks, v); }); obj.CreateBool("Physics Breaks Blocks", Color.white, s.PhysicsBreaks.Value, (Action<bool>)delegate(bool v) { Set(s.PhysicsBreaks, v); }); obj.CreateFloat("Gun Damage x", Color.yellow, s.GunDamage.Value, 0.25f, 0f, 5f, (Action<float>)delegate(float v) { Set(s.GunDamage, v); }); obj.CreateFloat("Melee Damage x", Color.yellow, s.MeleeDamage.Value, 0.25f, 0f, 5f, (Action<float>)delegate(float v) { Set(s.MeleeDamage, v); }); obj.CreateFloat("Physics Damage x", Color.yellow, s.PhysicsDamage.Value, 0.25f, 0f, 5f, (Action<float>)delegate(float v) { Set(s.PhysicsDamage, v); }); obj.CreateFloat("Block Sound Volume", Color.cyan, s.SoundVolume.Value, 0.1f, 0f, 2f, (Action<float>)delegate(float v) { Set(s.SoundVolume, v); }); menuBuilt = true; ((MelonBase)this).LoggerInstance.Msg("BoneMenu → Bonecraft: settings"); } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Warning("BoneMenu: " + ex.Message); } } private static void Set<T>(MelonPreferences_Entry<T> entry, T value) { entry.Value = value; Settings.Save(); } public override void OnFixedUpdate() { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) if (levelReady && !((Object)(object)Player.Head == (Object)null)) { if (!reportedRunning) { reportedRunning = true; ((MelonBase)this).LoggerInstance.Msg("hands found: left " + (((Object)(object)Player.LeftHand != (Object)null) ? "yes" : "NO") + ", right " + (((Object)(object)Player.RightHand != (Object)null) ? "yes" : "NO")); } weapons.FixedUpdate(); Vector3 position = Player.Head.position; float fixedDeltaTime = Time.fixedDeltaTime; Detect(left, Player.LeftHand, position, fixedDeltaTime); Detect(right, Player.RightHand, position, fixedDeltaTime); } } private void Detect(PunchDetector detector, Hand hand, Vector3 head, float dt) { //IL_0039: 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_0147: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)hand == (Object)null) { return; } bool holding = Settings.IgnoreWhileHolding.Value && (Object)(object)Player.GetObjectInHand(hand) != (Object)null; float curl = Curl(hand); Punch punch; string rejected; bool num = detector.Step(((Component)hand).transform.position, head, dt, holding, curl, out punch, out rejected); if (rejected != null && Settings.LogRejected.Value && Time.unscaledTime >= nextRejectLog) { nextRejectLog = Time.unscaledTime + 0.5f; ((MelonBase)this).LoggerInstance.Msg("no punch (" + detector.Hand + "): " + rejected); } if (num && Settings.Enabled.Value && Settings.FistsBreak.Value) { if (Settings.LogPunches.Value) { ((MelonBase)this).LoggerInstance.Msg($"punch {punch.Hand} {punch.Speed:0.0} m/s on {punch.ObjectName} at {punch.Point}"); } digger.Punched(in punch); } } private static float Curl(Hand hand) { BaseController controller = hand.Controller; if ((Object)(object)controller == (Object)null) { return 1f; } return Mathf.Min(Mathf.Min(controller.GetIndexCurlAxis(), controller.GetMiddleCurlAxis()), Mathf.Min(controller.GetRingCurlAxis(), controller.GetPinkyCurlAxis())); } public override void OnUpdate() { if (levelReady) { digger.Update(); } foreach (string item in link.Drain()) { if (Settings.LogPunches.Value && item.StartsWith("{\"t\":\"mined\"")) { ((MelonBase)this).LoggerInstance.Msg("minecraft: " + ((item.Length > 160) ? (item.Substring(0, 160) + "…") : item)); } try { digger.OnMessage(item); } catch (Exception value) { ((MelonBase)this).LoggerInstance.Error($"handling {((item.Length > 120) ? item.Substring(0, 120) : item)}: {value}"); } } if (keysBroken || !levelReady) { return; } try { if (Input.GetKeyDown((KeyCode)290)) { screen?.PlaceInFrontOfPlayer(); } if (Input.GetKeyDown((KeyCode)291)) { screen?.Toggle(); } } catch (Exception ex) { keysBroken = true; ((MelonBase)this).LoggerInstance.Warning("hotkeys disabled: " + ex.Message); } } public override void OnLateUpdate() { if (levelReady) { screen?.Tick(); digger.LateUpdate(); } } public override void OnDeinitializeMelon() { link?.Dispose(); screen?.Dispose(); } } internal sealed class Carver { public sealed class CellCut { public readonly Surfaces Removed = new Surfaces(); public int Pending; public float Started; public bool Done => Pending <= 0; } private sealed class CutRenderer { public MeshRenderer Source; public MeshFilter Target; public MeshCopy Copy; public Mesh Written; public MeshReader.PendingRead Pending; public bool Batched; public bool Failed; public bool Surface; public readonly List<(Box box, CellCut job)> Holes = new List<(Box, CellCut)>(); public readonly HashSet<Vector3> Applied = new HashSet<Vector3>(); } private sealed class CutCollider { public MeshCollider Target; public MeshCopy Copy; public MeshReader.PendingRead Pending; public bool Failed; public readonly List<Box> Holes = new List<Box>(); } private sealed class BoxSet { public BoxCollider Original; public GameObject Holder; public List<Box> Boxes; public Matrix4x4 WorldToLocal; public PhysicMaterial Material; } public const string CarvePrefix = "Bonecraft carve"; private static readonly string[] NotSurfaces = new string[11] { "occluder", "collider", "col_", "shadow", "sky", "inverted_sphere", "volume", "fog", "light", "beam", "glow" }; private readonly Instance log; private readonly Dictionary<IntPtr, CutRenderer> cuts = new Dictionary<IntPtr, CutRenderer>(); private readonly Dictionary<IntPtr, BoxSet> boxSets = new Dictionary<IntPtr, BoxSet>(); private readonly Dictionary<IntPtr, MeshCopy> meshColliders = new Dictionary<IntPtr, MeshCopy>(); private readonly Dictionary<IntPtr, CutCollider> gpuColliders = new Dictionary<IntPtr, CutCollider>(); private readonly Dictionary<IntPtr, HashSet<Vector3>> colliderHoles = new Dictionary<IntPtr, HashSet<Vector3>>(); private readonly HashSet<IntPtr> warned = new HashSet<IntPtr>(); private readonly HashSet<IntPtr> known = new HashSet<IntPtr>(); private List<(MeshRenderer r, Box b)> renderers; private float indexedAt = -100f; public Carver(Instance log) { this.log = log; } public void Reset() { cuts.Clear(); boxSets.Clear(); meshColliders.Clear(); gpuColliders.Clear(); colliderHoles.Clear(); warned.Clear(); known.Clear(); renderers = null; } public bool Known(Collider c) { return known.Contains(((Il2CppObjectBase)c).Pointer); } public CellCut Carve(in Box cell) { //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) CellCut cellCut = new CellCut { Started = Time.unscaledTime }; int num = 0; int num2 = 0; foreach (var item2 in Candidates(cell)) { MeshRenderer item = item2.Item1; try { if (CarveRenderer(item, in cell, cellCut)) { num++; } } catch (Exception ex) { Warn(((Il2CppObjectBase)item).Pointer, "couldn't cut mesh of " + ((Object)((Component)item).gameObject).name + ": " + ex.Message); } } Vector3 center = cell.Center; Vector3 v = cell.Size * 0.5f + new Vector3(0.01f); foreach (Collider item3 in (Il2CppArrayBase<Collider>)(object)Physics.OverlapBox(U.V3(center), U.V3(v), Quaternion.identity, -1, (QueryTriggerInteraction)1)) { if ((Object)(object)item3 == (Object)null || (Object)(object)item3.attachedRigidbody != (Object)null || ((Object)((Component)item3).gameObject).name.StartsWith("Bonecraft wall")) { continue; } known.Add(((Il2CppObjectBase)item3).Pointer); try { if (CarveCollider(item3, in cell)) { num2++; } } catch (Exception ex2) { Warn(((Il2CppObjectBase)item3).Pointer, "couldn't cut collider " + ((Object)((Component)item3).gameObject).name + ": " + ex2.Message); } } log.Msg($"carved cell {cell.Min}: {num} mesh(es), {num2} collider(s)"); return cellCut; } public void Prefetch(in Box region) { foreach (var item2 in Candidates(region)) { MeshRenderer item = item2.Item1; if (cuts.ContainsKey(((Il2CppObjectBase)item).Pointer)) { continue; } try { CutRenderer cutRenderer = Begin(item); if (cutRenderer != null) { cuts[((Il2CppObjectBase)item).Pointer] = cutRenderer; } } catch (Exception ex) { Warn(((Il2CppObjectBase)item).Pointer, "couldn't read mesh of " + ((Object)((Component)item).gameObject).name + ": " + ex.Message); } } } public bool Ready(in Box region) { foreach (var item2 in Candidates(region)) { MeshRenderer item = item2.Item1; if (cuts.TryGetValue(((Il2CppObjectBase)item).Pointer, out var value) && value.Pending != null) { return false; } } return true; } public TriangleField Field(in Box region) { TriangleField triangleField = new TriangleField(); foreach (var item2 in Candidates(region)) { MeshRenderer item = item2.Item1; if (!cuts.TryGetValue(((Il2CppObjectBase)item).Pointer, out var value) || value.Copy == null || !value.Surface) { continue; } foreach (var (vector, vector2, vector3) in value.Copy.Original) { if (new Box(Vector3.Min(vector, Vector3.Min(vector2, vector3)), Vector3.Max(vector, Vector3.Max(vector2, vector3))).Overlaps(in region)) { triangleField.Add(vector, vector2, vector3); } } } return triangleField; } public void Update() { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) GpuRead.Pump(); UpdateColliders(); List<IntPtr> list = null; foreach (var (item, cutRenderer2) in cuts) { if ((Object)(object)cutRenderer2.Source == (Object)null) { (list ?? (list = new List<IntPtr>())).Add(item); Release(cutRenderer2); } else { if (cutRenderer2.Pending == null || !cutRenderer2.Pending.Done) { continue; } MeshReader.PendingRead pending = cutRenderer2.Pending; cutRenderer2.Pending = null; try { cutRenderer2.Copy = pending.Finish(); CheckBounds(cutRenderer2); ApplyHoles(cutRenderer2); } catch (Exception ex) { cutRenderer2.Failed = true; cutRenderer2.Copy = null; float value = BonecraftMod.Settings.BlockSize.Value; float num = Largest(U.Box(((Renderer)cutRenderer2.Source).bounds)); bool flag = ((Object)((Component)cutRenderer2.Source).gameObject).name.Contains("decal", StringComparison.OrdinalIgnoreCase); bool flag2 = cutRenderer2.Holes.Count > 0 && (num <= 1.5f * value || (flag && num <= 3f * value)); if (flag2) { ((Renderer)cutRenderer2.Source).enabled = false; } Warn(((Il2CppObjectBase)cutRenderer2.Source).Pointer, $"couldn't cut mesh of {((Object)((Component)cutRenderer2.Source).gameObject).name}: {ex.Message}{(flag2 ? " (small: hidden instead)" : "")}"); Release(cutRenderer2); } } } if (list == null) { return; } foreach (IntPtr item2 in list) { cuts.Remove(item2); } } private static void Release(CutRenderer cut) { foreach (var hole in cut.Holes) { CellCut item = hole.job; if (item != null) { item.Pending--; } } cut.Holes.Clear(); } private static void CheckBounds(CutRenderer cut) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) Box box = U.Box(((Renderer)cut.Source).bounds); Box bounds = cut.Copy.Bounds; float num = 0.1f + 0.05f * box.Size.Length(); if ((bounds.Min - box.Min).Length() > num || (bounds.Max - box.Max).Length() > num) { throw new InvalidOperationException($"read-back geometry {bounds.Min}..{bounds.Max} isn't where it draws ({box.Min}..{box.Max}); left as it is"); } } public MeshRenderer SurfaceAt(Vector3 p) { Box region = new Box(p - new Vector3(0.05f), p + new Vector3(0.05f)); MeshRenderer result = null; float num = float.MaxValue; foreach (var item3 in Candidates(region)) { MeshRenderer item = item3.Item1; Box item2 = item3.Item2; float volume = item2.Volume; if (volume < num && IsSurface(item)) { result = item; num = volume; } } return result; } private IEnumerable<(MeshRenderer, Box)> Candidates(Box region) { if (renderers == null || Time.unscaledTime - indexedAt > 15f) { Index(); } foreach (var (val, item) in renderers) { if (item.Overlaps(in region, 0.01f) && (Object)(object)val != (Object)null && (((Renderer)val).enabled || cuts.ContainsKey(((Il2CppObjectBase)val).Pointer))) { yield return (val, item); } } } private void Index() { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) indexedAt = Time.unscaledTime; renderers = new List<(MeshRenderer, Box)>(); Transform val = (((Object)(object)Player.RigManager != (Object)null) ? ((Component)Player.RigManager).transform : null); foreach (MeshRenderer item in Object.FindObjectsOfType<MeshRenderer>()) { if (!((Object)(object)item == (Object)null) && (((Renderer)item).enabled || cuts.ContainsKey(((Il2CppObjectBase)item).Pointer)) && !((Object)((Component)item).gameObject).name.StartsWith("Bonecraft") && !((Object)(object)((Component)item).GetComponentInParent<Rigidbody>() != (Object)null) && (!((Object)(object)val != (Object)null) || !((Component)item).transform.IsChildOf(val))) { renderers.Add((item, U.Box(((Renderer)item).bounds))); } } } private static bool IsSurface(MeshRenderer r) { string text = ((Object)((Component)r).gameObject).name.ToLowerInvariant(); string[] notSurfaces = NotSurfaces; foreach (string value in notSurfaces) { if (text.Contains(value)) { return false; } } foreach (Material item in (Il2CppArrayBase<Material>)(object)((Renderer)r).sharedMaterials) { if ((Object)(object)item == (Object)null || item.renderQueue >= 2450) { return false; } } return true; } private bool CarveRenderer(MeshRenderer r, in Box cell, CellCut job) { if (!cuts.TryGetValue(((Il2CppObjectBase)r).Pointer, out var value)) { value = Begin(r); if (value == null) { return false; } cuts[((Il2CppObjectBase)r).Pointer] = value; } if (value.Failed || !value.Applied.Add(cell.Min)) { return false; } job.Pending++; value.Holes.Add((cell, job)); if (value.Copy != null) { ApplyHoles(value); } return true; } private void ApplyHoles(CutRenderer cut) { bool flag = false; foreach (var hole2 in cut.Holes) { Box hole = hole2.box; CellCut item = hole2.job; flag |= cut.Copy.Subtract(in hole, item?.Removed); if (item != null) { item.Pending--; } } cut.Holes.Clear(); if (flag) { if ((Object)(object)cut.Target == (Object)null) { Install(cut); } Mesh written = cut.Written; cut.Written = cut.Copy.Build("Bonecraft cut " + ((Object)((Component)cut.Source).gameObject).name); cut.Target.sharedMesh = cut.Written; if ((Object)(object)written != (Object)null) { Object.Destroy((Object)(object)written); } log.Msg("cut " + ((Object)((Component)cut.Source).gameObject).name); } } private CutRenderer Begin(MeshRenderer r) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) MeshFilter component = ((Component)r).GetComponent<MeshFilter>(); Mesh val = (((Object)(object)component != (Object)null) ? component.sharedMesh : null); if ((Object)(object)val == (Object)null) { return null; } if (!((Renderer)r).isPartOfStaticBatch) { return new CutRenderer { Source = r, Target = component, Surface = IsSurface(r), Pending = MeshReader.BeginGpu(val, U.M(((Renderer)r).localToWorldMatrix), 0, val.subMeshCount) }; } Transform staticBatchRootTransform = ((Renderer)r).staticBatchRootTransform; Matrix4x4 rootToWorld = (((Object)(object)staticBatchRootTransform != (Object)null) ? U.M(staticBatchRootTransform.localToWorldMatrix) : Matrix4x4.Identity); int length = ((Il2CppArrayBase<Material>)(object)((Renderer)r).sharedMaterials).Length; var (num, subCount) = BatchRange(val, r, length, in rootToWorld); if (num < 0) { Warn(((Il2CppObjectBase)r).Pointer, "couldn't find " + ((Object)((Component)r).gameObject).name + " in its static batch"); return null; } return new CutRenderer { Source = r, Batched = true, Surface = IsSurface(r), Pending = MeshReader.BeginGpu(val, in rootToWorld, num, subCount) }; } private static void Install(CutRenderer cut) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Expected O, but got Unknown MeshRenderer source = cut.Source; Transform staticBatchRootTransform = ((Renderer)source).staticBatchRootTransform; GameObject val = new GameObject("Bonecraft cut " + ((Object)((Component)source).gameObject).name) { layer = ((Component)source).gameObject.layer }; if ((Object)(object)staticBatchRootTransform != (Object)null) { val.transform.SetParent(staticBatchRootTransform, false); } MeshFilter target = val.AddComponent<MeshFilter>(); MeshRenderer val2 = val.AddComponent<MeshRenderer>(); ((Renderer)val2).sharedMaterials = ((Renderer)source).sharedMaterials; ((Renderer)val2).shadowCastingMode = ((Renderer)source).shadowCastingMode; ((Renderer)val2).receiveShadows = ((Renderer)source).receiveShadows; ((Renderer)val2).lightProbeUsage = ((Renderer)source).lightProbeUsage; ((Renderer)val2).reflectionProbeUsage = ((Renderer)source).reflectionProbeUsage; ((Renderer)val2).probeAnchor = ((Renderer)source).probeAnchor; ((Renderer)val2).renderingLayerMask = ((Renderer)source).renderingLayerMask; ((Renderer)val2).rendererPriority = ((Renderer)source).rendererPriority; ((Renderer)val2).lightmapIndex = ((Renderer)source).lightmapIndex; ((Renderer)val2).lightmapScaleOffset = (Vector4)(BakedLightmapUvs(cut.Copy, ((Renderer)source).lightmapScaleOffset) ? new Vector4(1f, 1f, 0f, 0f) : ((Renderer)source).lightmapScaleOffset); MaterialPropertyBlock val3 = new MaterialPropertyBlock(); ((Renderer)source).GetPropertyBlock(val3); ((Renderer)val2).SetPropertyBlock(val3); cut.Target = target; ReplaceInLods((Renderer)(object)source, (Renderer)(object)val2); ((Renderer)source).enabled = false; } private static void ReplaceInLods(Renderer from, Renderer to) { try { LODGroup componentInParent = ((Component)from).GetComponentInParent<LODGroup>(); if ((Object)(object)componentInParent == (Object)null) { return; } Il2CppReferenceArray<LOD> lODs = componentInParent.GetLODs(); bool flag = false; for (int i = 0; i < ((Il2CppArrayBase<LOD>)(object)lODs).Length; i++) { Il2CppReferenceArray<Renderer> val = ((Il2CppArrayBase<LOD>)(object)lODs)[i].renderers; int num = 0; while (val != null && num < ((Il2CppArrayBase<Renderer>)(object)val).Length) { if ((Object)(object)((Il2CppArrayBase<Renderer>)(object)val)[num] != (Object)null && ((Il2CppObjectBase)((Il2CppArrayBase<Renderer>)(object)val)[num]).Pointer == ((Il2CppObjectBase)from).Pointer) { ((Il2CppArrayBase<Renderer>)(object)val)[num] = to; flag = true; } num++; } } if (flag) { componentInParent.SetLODs(lODs); } } catch { } } private static bool BakedLightmapUvs(MeshCopy copy, Vector4 st) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) (Vector2, Vector2)? tuple = copy.LightmapUvRange(); if (!tuple.HasValue || (MathF.Abs(st.x - 1f) < 0.0001f && MathF.Abs(st.y - 1f) < 0.0001f && MathF.Abs(st.z) < 0.0001f && MathF.Abs(st.w) < 0.0001f)) { return false; } var (vector, vector2) = tuple.Value; if (vector.X >= st.z - 0.002f && vector.Y >= st.w - 0.002f && vector2.X <= st.z + st.x + 0.002f) { return vector2.Y <= st.w + st.y + 0.002f; } return false; } private static (int first, int count) BatchRange(Mesh mesh, MeshRenderer r, int materials, in Matrix4x4 rootToWorld) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) int subMeshCount = mesh.subMeshCount; int num = -1; try { num = r.subMeshStartIndex; } catch { } if (num >= 0 && num < subMeshCount) { Box box = U.Box(((Renderer)r).bounds); float num2 = 0.02f + 0.01f * box.Size.Length(); Vector3 vector = new Vector3(float.MaxValue); Vector3 vector2 = new Vector3(float.MinValue); for (int i = 0; i < materials && num + i < subMeshCount; i++) { Box box2 = SubBox(mesh, num + i, in rootToWorld); vector = Vector3.Min(vector, box2.Min); vector2 = Vector3.Max(vector2, box2.Max); if ((vector - box.Min).Length() < num2 && (vector2 - box.Max).Length() < num2) { return (first: num, count: i + 1); } } return (first: num, count: Math.Max(1, Math.Min(materials, subMeshCount - num))); } return (first: FindBatchRange(mesh, (Renderer)(object)r, materials, in rootToWorld), count: materials); } private static Box SubBox(Mesh mesh, int s, in Matrix4x4 rootToWorld) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) Vector3[] array = U.Box(mesh.GetSubMesh(s)._bounds_k__BackingField).Corners(); for (int i = 0; i < 8; i++) { array[i] = U.Point(in rootToWorld, array[i]); } return Box.Around(array); } private static int FindBatchRange(Mesh mesh, Renderer r, int count, in Matrix4x4 rootToWorld) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Box box = U.Box(r.bounds); float num = 0.02f + 0.01f * box.Size.Length(); int subMeshCount = mesh.subMeshCount; Box[] array = new Box[subMeshCount]; for (int i = 0; i < subMeshCount; i++) { array[i] = SubBox(mesh, i, in rootToWorld); } for (int j = 0; j + count <= subMeshCount; j++) { Vector3 vector = array[j].Min; Vector3 vector2 = array[j].Max; for (int k = 1; k < count; k++) { vector = Vector3.Min(vector, array[j + k].Min); vector2 = Vector3.Max(vector2, array[j + k].Max); } if ((vector - box.Min).Length() < num && (vector2 - box.Max).Length() < num) { return j; } } return -1; } private bool CarveCollider(Collider col, in Box cell) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: 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) //IL_0103: Expected O, but got Unknown //IL_01db: Unknown result type (might be due to invalid IL or missing references) if (((Object)((Component)col).gameObject).name == "Bonecraft carve") { Transform parent = ((Component)col).transform.parent; if ((Object)(object)parent != (Object)null && boxSets.TryGetValue(((Il2CppObjectBase)((Component)parent).gameObject).Pointer, out var value)) { return Subtract(value, in cell); } return false; } BoxCollider val = ((Il2CppObjectBase)col).TryCast<BoxCollider>(); if ((Object)(object)val != (Object)null) { if (!boxSets.TryGetValue(((Il2CppObjectBase)val).Pointer, out var value2)) { Vector3 vector = U.N3(val.center); Vector3 vector2 = U.N3(val.size) * 0.5f; Box piece = new Box(vector - vector2, vector + vector2); Matrix4x4 worldToLocal = U.M(((Component)val).transform.worldToLocalMatrix); if (!Clip.Cuts(in piece, LocalHole(in worldToLocal, in cell))) { return false; } GameObject val2 = new GameObject("Bonecraft carve") { layer = ((Component)val).gameObject.layer }; val2.transform.SetParent(((Component)val).transform, false); value2 = new BoxSet { Original = val, Holder = val2, Boxes = new List<Box> { piece }, WorldToLocal = worldToLocal, Material = ((Collider)val).sharedMaterial }; boxSets[((Il2CppObjectBase)val).Pointer] = value2; boxSets[((Il2CppObjectBase)val2).Pointer] = value2; } return Subtract(value2, in cell); } MeshCollider val3 = ((Il2CppObjectBase)col).TryCast<MeshCollider>(); if ((Object)(object)val3 != (Object)null) { Mesh sharedMesh = val3.sharedMesh; if ((Object)(object)sharedMesh == (Object)null) { return false; } if (!sharedMesh.isReadable) { return CarveGpuCollider(val3, sharedMesh, in cell); } if (!meshColliders.TryGetValue(((Il2CppObjectBase)val3).Pointer, out var value3)) { value3 = MeshReader.ReadCpu(sharedMesh, U.M(((Component)val3).transform.localToWorldMatrix)); meshColliders[((Il2CppObjectBase)val3).Pointer] = value3; } if (!Holes((Collider)(object)val3).Add(cell.Min) || !value3.Subtract(in cell)) { return false; } Mesh sharedMesh2 = value3.Build("Bonecraft cut collider " + ((Object)((Component)val3).gameObject).name); val3.convex = false; val3.sharedMesh = sharedMesh2; return true; } if ((Object)(object)((Il2CppObjectBase)col).TryCast<TerrainCollider>() != (Object)null) { Warn(((Il2CppObjectBase)col).Pointer, "terrain " + ((Object)((Component)col).gameObject).name + " can't be dug yet; it stays solid"); } return false; } private HashSet<Vector3> Holes(Collider c) { if (!colliderHoles.TryGetValue(((Il2CppObjectBase)c).Pointer, out var value)) { value = (colliderHoles[((Il2CppObjectBase)c).Pointer] = new HashSet<Vector3>()); } return value; } private bool CarveGpuCollider(MeshCollider mc, Mesh mesh, in Box cell) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (!gpuColliders.TryGetValue(((Il2CppObjectBase)mc).Pointer, out var value)) { value = new CutCollider { Target = mc }; try { value.Pending = MeshReader.BeginGpu(mesh, U.M(((Component)mc).transform.localToWorldMatrix), 0, mesh.subMeshCount); } catch (Exception ex) { value.Failed = true; NoCollisionCut(mc, ex.Message); } gpuColliders[((Il2CppObjectBase)mc).Pointer] = value; } if (value.Failed || !Holes((Collider)(object)mc).Add(cell.Min)) { return false; } value.Holes.Add(cell); if (value.Copy != null) { ApplyColliderHoles(value); } return true; } private void UpdateColliders() { foreach (CutCollider value in gpuColliders.Values) { if (value.Pending == null || !value.Pending.Done || (Object)(object)value.Target == (Object)null) { continue; } MeshReader.PendingRead pending = value.Pending; value.Pending = null; try { MeshCopy copy = pending.Finish(); string text = CheckCollider(value.Target, copy); if (text != null) { throw new InvalidOperationException(text); } value.Copy = copy; ApplyColliderHoles(value); log.Msg("cut collision of " + ((Object)((Component)value.Target).gameObject).name + " (read from the GPU, checked against the collider)"); } catch (Exception ex) { value.Failed = true; value.Holes.Clear(); NoCollisionCut(value.Target, ex.Message); } } } private static void ApplyColliderHoles(CutCollider cut) { bool flag = false; foreach (Box hole2 in cut.Holes) { Box hole = hole2; flag |= cut.Copy.Subtract(in hole); } cut.Holes.Clear(); if (flag) { cut.Target.convex = false; cut.Target.sharedMesh = cut.Copy.Build("Bonecraft cut collider " + ((Object)((Component)cut.Target).gameObject).name); } } private void NoCollisionCut(MeshCollider mc, string why) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) float value = BonecraftMod.Settings.BlockSize.Value; bool flag = Largest(U.Box(((Collider)mc).bounds)) <= 1.5f * value; if (flag) { ((Collider)mc).enabled = false; } Warn(((Il2CppObjectBase)mc).Pointer, $"collision of {((Object)((Component)mc).gameObject).name} can't be cut ({why}); {(flag ? "small: switched off" : "it stays solid")}"); } private static float Largest(in Box b) { return MathF.Max(b.Size.X, MathF.Max(b.Size.Y, b.Size.Z)); } private static string CheckCollider(MeshCollider mc, MeshCopy copy) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) Box box = U.Box(((Collider)mc).bounds); Box bounds = copy.Bounds; float num = 0.05f + 0.02f * box.Size.Length(); if ((bounds.Min - box.Min).Length() > num || (bounds.Max - box.Max).Length() > num) { return $"read-back geometry {bounds.Min}..{bounds.Max} isn't the collider's ({box.Min}..{box.Max})"; } List<(Vector3, Vector3, Vector3)> original = copy.Original; int num2 = Math.Min(64, original.Count); int num3 = 0; int num4 = 0; int mask = 1 << ((Component)mc).gameObject.layer; bool convex = mc.convex; for (int i = 0; i < num2; i++) { (Vector3, Vector3, Vector3) tuple = original[(int)((long)i * (long)original.Count / num2)]; Vector3 item = tuple.Item1; Vector3 item2 = tuple.Item2; Vector3 item3 = tuple.Item3; Vector3 vector = Vector3.Cross(item2 - item, item3 - item); float num5 = vector.Length(); if (num5 < 1E-06f) { continue; } vector /= num5; Vector3 vector2 = (item + item2 + item3) / 3f; num3++; bool num6; if (!convex) { if (Hits((Collider)(object)mc, vector2 + vector * 0.05f, -vector, mask)) { goto IL_022a; } num6 = Hits((Collider)(object)mc, vector2 - vector * 0.05f, vector, mask); } else { num6 = (U.N3(((Collider)mc).ClosestPoint(U.V3(vector2))) - vector2).Length() < 0.02f; } if (!num6) { continue; } goto IL_022a; IL_022a: num4++; } if (num3 == 0) { return "nothing but degenerate triangles read back"; } if (num4 * 4 < num3 * 3) { return $"read-back triangles aren't where the collider is ({num4} of {num3} probes found it)"; } return null; } private static bool Hits(Collider target, Vector3 from, Vector3 dir, int mask) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_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) foreach (RaycastHit item in (Il2CppArrayBase<RaycastHit>)(object)Physics.RaycastAll(U.V3(from), U.V3(dir), 0.1f, mask, (QueryTriggerInteraction)1)) { RaycastHit current = item; if ((Object)(object)((RaycastHit)(ref current)).collider != (Object)null && ((Il2CppObjectBase)((RaycastHit)(ref current)).collider).Pointer == ((Il2CppObjectBase)target).Pointer) { return true; } } return false; } private static Box LocalHole(in Matrix4x4 worldToLocal, in Box cell) { Vector3[] array = cell.Corners(); for (int i = 0; i < 8; i++) { array[i] = U.Point(in worldToLocal, array[i]); } return Box.Around(array); } private static bool Subtract(BoxSet set, in Box cell) { //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_010a: 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) Box hole = LocalHole(in set.WorldToLocal, in cell); List<Box> list = new List<Box>(); bool flag = false; foreach (Box box in set.Boxes) { Box piece = box; if (Clip.Cuts(in piece, in hole)) { flag = true; list.AddRange(Clip.SubtractBox(in piece, in hole)); } else { list.Add(piece); } } if (!flag) { return false; } set.Boxes = list; for (int num = set.Holder.transform.childCount - 1; num >= 0; num--) { Object.Destroy((Object)(object)((Component)set.Holder.transform.GetChild(num)).gameObject); } foreach (Box item in list) { GameObject val = new GameObject("Bonecraft carve") { layer = set.Holder.layer }; val.transform.SetParent(set.Holder.transform, false); BoxCollider obj = val.AddComponent<BoxCollider>(); obj.center = U.V3(item.Center); obj.size = U.V3(item.Size); ((Collider)obj).sharedMaterial = set.Material; } if ((Object)(object)set.Original != (Object)null && ((Collider)set.Original).enabled) { ((Collider)set.Original).enabled = false; } return true; } private void Warn(IntPtr key, string message) { if (warned.Add(key)) { log.Warning(message); } } } internal readonly record struct Cell(int G, int X, int Y, int Z) { public (int, int, int) Key => (X, Y, Z); public Cell(int G, int X, int Y, int Z) { this.G = G; this.X = X; this.Y = Y; this.Z = Z; } public Cell((int x, int y, int z) c) : this(0, c.x, c.y, c.z) { } public Cell Step(int face) { (int, int, int) tuple = Walls.Dirs[face]; return new Cell(G, X + tuple.Item1, Y + tuple.Item2, Z + tuple.Item3); } public override string ToString() { return $"({X}, {Y}, {Z})"; } } internal sealed class Digger { private sealed class Struck { public Cell Cell; public string Block; public int Layer; public Vector3 Point; public Vector3 Normal; } private sealed class Unfinished { public Cell Cell; public int Layer; public string Block; public Carver.CellCut Cut; public Box Region; } private const float Reach = 3f; private readonly Instance log; private readonly Link link; private readonly Carver carver; private readonly Walls walls; private readonly BlockLook look; private readonly Sounds sounds; private readonly Cracks cracks; private readonly Particles particles; private readonly Blocks blocks; private readonly HashSet<Cell> dug = new HashSet<Cell>(); private readonly Dictionary<Cell, string> revealed = new Dictionary<Cell, string>(); private readonly Dictionary<(int, int, int), Struck> pending = new Dictionary<(int, int, int), Struck>(); private readonly Dictionary<Cell, int> recarves = new Dictionary<Cell, int>(); private readonly List<Unfinished> unfinished = new List<Unfinished>(); private float nextRestoreCheck; private static float Size => BonecraftMod.Settings.BlockSize.Value; public Digger(Link link, Instance log) { this.log = log; this.link = link; carver = new Carver(log); look = new BlockLook(link, log); walls = new Walls(look); sounds = new Sounds(link, log); cracks = new Cracks(look); particles = new Particles(look); blocks = new Blocks(link); } public static (int, int, int) CellOf(Vector3 p) { float size = Size; return ((int)MathF.Floor(p.X / size), (int)MathF.Floor(p.Y / size), (int)MathF.Floor(p.Z / size)); } public static Box BoxOf(Cell c) { float size = Size; Vector3 vector = new Vector3(c.X, c.Y, c.Z) * size; return new Box(vector, vector + new Vector3(size)); } public void Reset() { dug.Clear(); revealed.Clear(); pending.Clear(); recarves.Clear(); unfinished.Clear(); carver.Reset(); walls.Reset(); look.Reset(); cracks.Reset(); particles.Reset(); } public void Update() { carver.Update(); for (int num = this.unfinished.Count - 1; num >= 0; num--) { Unfinished unfinished = this.unfinished[num]; if ((unfinished.Cut.Done && carver.Ready(in unfinished.Region)) || Time.unscaledTime - unfinished.Cut.Started > 2f) { this.unfinished.RemoveAt(num); try { Sides(unfinished); } catch (Exception value) { log.Error($"sides of {unfinished.Cell}: {value}"); } } } cracks.Update(); particles.Update(Time.deltaTime); if (Time.unscaledTime >= nextRestoreCheck) { nextRestoreCheck = Time.unscaledTime + 1f; RecarveRestored(); } } public void LateUpdate() { particles.Render(); } private void RecarveRestored() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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) if (dug.Count == 0 || (Object)(object)Player.Head == (Object)null) { return; } Vector3 vector = U.N3(Player.Head.position); foreach (Cell item in dug) { Box cell = BoxOf(item); if ((cell.Center - vector).Length() > 40f) { continue; } Vector3 v = cell.Size * 0.5f - new Vector3(0.05f); foreach (Collider item2 in (Il2CppArrayBase<Collider>)(object)Physics.OverlapBox(U.V3(cell.Center), U.V3(v), Quaternion.identity, -1, (QueryTriggerInteraction)1)) { if (Walls.Level(item2) && !(((Object)((Component)item2).gameObject).name == "Bonecraft carve") && !carver.Known(item2)) { int value; int num = ((!recarves.TryGetValue(item, out value)) ? 1 : (value + 1)); recarves[item] = num; if (num <= 3) { log.Msg($"level geometry came back in dug cell {item} ({((Object)((Component)item2).gameObject).name}): carving it again"); carver.Carve(in cell); } break; } } } } private (Cell cell, string block) Target(Vector3 p, Vector3 n, Collider c) { Cell cell = new Cell(CellOf(p - n * (0.02f * Size))); if (dug.Contains(cell)) { cell = new Cell(CellOf(p - n * (0.6f * Size))); } if (walls.OwnerOf(c, out var _) && revealed.TryGetValue(cell, out var value)) { return (cell: cell, block: value); } MeshRenderer val = carver.SurfaceAt(p); if ((Object)(object)val != (Object)null) { foreach (Material item in (Il2CppArrayBase<Material>)(object)((Renderer)val).sharedMaterials) { look.SetTemplate(item); } } return (cell: cell, block: Materials.BlockFor(c, (Renderer)(object)val)); } public void Hit(Vector3 p, Vector3 n, Collider c, string tool, float ticks, string hand) { if (BonecraftMod.Settings.Enabled.Value && !(ticks <= 0f)) { var (cell, text) = Target(p, n, c); if (!dug.Contains(cell)) { pending[cell.Key] = new Struck { Cell = cell, Block = text, Layer = ((Component)c).gameObject.layer, Point = p, Normal = n }; link.Send(Json.Obj("t", "punch", "cell", new int[3] { cell.X, cell.Y, cell.Z }, "hint", text, "tool", tool, "ticks", ticks, "hand", hand)); } } } public void Punched(in Punch punch) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) float ticks = Math.Clamp(8f * punch.Speed / 3f, 1f, 24f); Hit(U.N3(punch.Point), U.N3(punch.Normal), punch.Collider, "hand", ticks, punch.Hand); } public void Shot(Vector3 p, Vector3 n, Collider c, float ticks) { Hit(p, n, c, "best", ticks, "G"); } public void OnMessage(string json) { using JsonDocument jsonDocument = JsonDocument.Parse(json); JsonElement rootElement = jsonDocument.RootElement; switch (rootElement.GetProperty("t").GetString()) { case "tex": look.OnTexture(rootElement.GetProperty("block").GetString(), rootElement.GetProperty("w").GetInt32(), rootElement.GetProperty("h").GetInt32(), (rootElement.GetProperty("rgba").ValueKind == JsonValueKind.String) ? rootElement.GetProperty("rgba").GetString() : null); break; case "sound": sounds.OnSound(rootElement); break; case "blockinfo": blocks.OnInfo(rootElement); PreloadSounds(rootElement.GetProperty("block").GetString()); break; case "mined": { if (rootElement.TryGetProperty("cell", out var value)) { Mined(rootElement, (value[0].GetInt32(), value[1].GetInt32(), value[2].GetInt32())); } break; } } } private void PreloadSounds(string block) { Blocks.Info info = blocks.InfoFor(block); sounds.Preload(info.Hit); sounds.Preload(info.Break); } private void Mined(JsonElement m, (int, int, int) key) { //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) JsonElement value = m.GetProperty("block"); string text = value.GetString(); if (m.TryGetProperty("sound", out value)) { bool num = blocks.InfoFor(text).Hit == null; blocks.OnInfo(m); if (num) { PreloadSounds(text); } } value = m.GetProperty("broken"); bool boolean = value.GetBoolean(); Struck value2; Struck value3; Struck struck = ((!boolean) ? (pending.TryGetValue(key, out value2) ? value2 : null) : (pending.Remove(key, out value3) ? value3 : null)); if (struck == null) { return; } Blocks.Info info = blocks.InfoFor(text); Box box = BoxOf(struck.Cell); string key2 = text + "|particle"; if (!boolean) { sounds.Play(info.Hit, U.V3(struck.Point), (info.Volume + 1f) / 8f, info.Pitch * 0.5f); particles.Crack(key2, struck.Point, struck.Normal, 6); if (!m.TryGetProperty("unbreakable", out value)) { cracks.Show(struck.Cell, in box, struck.Point, struck.Normal, m.GetProperty("progress").GetSingle()); } } else { cracks.Hide(struck.Cell); sounds.Play(info.Break, U.V3(box.Center), (info.Volume + 1f) / 2f, info.Pitch * 0.8f); particles.Destroy(key2, in box); Dig(struck.Cell, struck.Layer, text); } } private void Dig(Cell cell, int layer, string block) { if (dug.Add(cell)) { Box cell2 = BoxOf(cell); for (int i = 0; i < 6; i++) { walls.Remove(cell.Step(i), Walls.Opposite(i)); } Box region = new Box(cell2.Min - new Vector3(3f), cell2.Max + new Vector3(3f)); carver.Prefetch(in region); Carver.CellCut cellCut = carver.Carve(in cell2); Unfinished unfinished = new Unfinished { Cell = cell, Layer = layer, Block = block, Cut = cellCut, Region = region }; if (cellCut.Done && carver.Ready(in region)) { Sides(unfinished); } else { this.unfinished.Add(unfinished); } } } private void Sides(Unfinished u) { Cell cell = u.Cell; Box cell2 = BoxOf(cell); TriangleField field = carver.Field(in u.Region); int num = 0; int num2 = 0; int num3 = 0; List<string> list = new List<string>(); List<string> list2 = new List<string>(); for (int i = 0; i < 6; i++) { Cell cell3 = cell.Step(i); if (dug.Contains(cell3)) { continue; } bool[,] array = Walls.Sample(in cell2, i, (Vector3 q) => field.Classify(q, 3f) <= 0); if (i != 2) { num2 += SolidBelowLevel(in cell2, i, array); } int num4 = 0; bool[,] array2 = array; foreach (bool flag in array2) { num4 += (flag ? 1 : 0); } if (num4 == 0) { list.Add(Walls.Names[i]); continue; } if (num4 < 256) { list2.Add(Walls.Names[i]); } int covered; bool[,] draw = Uncovered(field, in cell2, i, array, out covered); num3 += covered; string value; string text = (revealed.TryGetValue(cell3, out value) ? value : u.Block); if (covered < num4) { revealed[cell3] = text; } try { walls.Build(cell, in cell2, i, array, draw, text + "|" + Walls.Names[Walls.Opposite(i)], u.Layer); num++; } catch (Exception ex) { log.Error($"side {Walls.Names[i]} of {cell}: {ex.Message}"); } } log.Msg($"dug {cell} ({u.Block}): {num} block side(s){((list2.Count > 0) ? (" (" + string.Join(" ", list2) + " partly)") : "")}, open: {((list.Count > 0) ? string.Join(" ", list) : "none")} ({field.Count} level triangles around{((num2 > 0) ? $", {num2} sample(s) over the void under the level" : "")}{((num3 > 0) ? $", {num3} sample(s) still the level's own surface" : "")})"); } private static bool[,] Uncovered(TriangleField field, in Box box, int face, bool[,] mask, out int covered) { (Vector3 n, Vector3 u, Vector3 v) tuple = Walls.Axes(face); Vector3 item = tuple.n; Vector3 item2 = tuple.u; Vector3 item3 = tuple.v; Vector3 vector = Walls.Origin(in box, face); float x = box.Size.X; float num = 0.005f; bool[,] array = new bool[16, 16]; covered = 0; for (int i = 0; i < 16; i++) { for (int j = 0; j < 16; j++) { array[i, j] = mask[i, j]; if (mask[i, j]) { Vector3 vector2 = vector + item2 * (((float)i + 0.5f) / 16f * x) + item3 * (((float)j + 0.5f) / 16f * x); if (field.Cast(vector2 - item * num, face, num + 0.01f * x, out var _, out var front, out var normal) && front && Vector3.Dot(normal, -item) > 0.9f) { array[i, j] = false; covered++; } } } } return array; } private static int SolidBelowLevel(in Box box, int face, bool[,] mask) { float x = box.Size.X; int num = 0; if (face == 3) { if (BelowLevel(box.Center - Vector3.UnitY * (0.55f * x))) { for (int i = 0; i < 16; i++) { for (int j = 0; j < 16; j++) { num += ((!mask[i, j]) ? 1 : 0); mask[i, j] = true; } } } return num; } (Vector3 n, Vector3 u, Vector3 v) tuple = Walls.Axes(face); Vector3 item = tuple.n; Vector3 item2 = tuple.u; Vector3 item3 = tuple.v; Vector3 vector = Walls.Origin(in box, face); for (int k = 0; k < 16 && BelowLevel(vector + item2 * (0.5f * x) + item3 * (((float)k + 0.5f) / 16f * x) + item * (0.05f * x)); k++) { for (int l = 0; l < 16; l++) { num += ((!mask[l, k]) ? 1 : 0); mask[l, k] = true; } } return num; } private static bool BelowLevel(Vector3 q) { //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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_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_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) Vector3 val = U.V3(q); Vector3 val2 = U.V3(-Vector3.UnitY); RaycastHit val3 = default(RaycastHit); if (!Physics.Raycast(val, val2, ref val3, 500f, -1, (QueryTriggerInteraction)1)) { return true; } if ((Object)(object)((RaycastHit)(ref val3)).collider != (Object)null && (Object)(object)((RaycastHit)(ref val3)).collider.attachedRigidbody == (Object)null) { return false; } foreach (RaycastHit item in (Il2CppArrayBase<RaycastHit>)(object)Physics.RaycastAll(val, val2, 500f, -1, (QueryTriggerInteraction)1)) { RaycastHit current = item; if ((Object)(object)((RaycastHit)(ref current)).collider != (Object)null && (Object)(object)((RaycastHit)(ref current)).collider.attachedRigidbody == (Object)null) { return false; } } return true; } } internal sealed class Cracks { private const float Heal = 5f; private readonly BlockLook look; private readonly Dictionary<Cell, (GameObject go, MeshRenderer r, int stage, float last)> active = new Dictionary<Cell, (GameObject, MeshRenderer, int, float)>(); public Cracks(BlockLook look) { this.look = look; } public void Reset() { foreach (var value in active.Values) { if ((Object)(object)value.go != (Object)null) { Object.Destroy((Object)(object)value.go); } } active.Clear(); } public void Show(Cell cell, in Box box, Vector3 point, Vector3 normal, float progress) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown int num = Math.Clamp((int)(progress * 10f), 0, 9); Material val = look.Crack(num); if ((Object)(object)val == (Object)null) { return; } if (active.TryGetValue(cell, out (GameObject, MeshRenderer, int, float) value) && (Object)(object)value.Item1 != (Object)null) { if (value.Item3 != num) { ((Renderer)value.Item2).sharedMaterial = val; } active[cell] = (value.Item1, value.Item2, num, Time.unscaledTime); return; } Mesh val2 = Overlay(in box, point, normal); if (!((Object)(object)val2 == (Object)null)) { GameObject val3 = new GameObject("Bonecraft crack"); val3.AddComponent<MeshFilter>().sharedMesh = val2; MeshRenderer val4 = val3.AddComponent<MeshRenderer>(); ((Renderer)val4).sharedMaterial = val; ((Renderer)val4).shadowCastingMode = (ShadowCastingMode)0; active[cell] = (val3, val4, num, Time.unscaledTime); } } public void Hide(Cell cell) { if (active.Remove(cell, out (GameObject, MeshRenderer, int, float) value) && (Object)(object)value.Item1 != (Object)null) { Object.Destroy((Object)(object)value.Item1); } } public void Update() { List<Cell> list = null; foreach (var (item, tuple2) in active) { if (Time.unscaledTime - tuple2.Item4 > 5f) { (list ?? (list = new List<Cell>())).Add(item); } } if (list == null) { return; } foreach (Cell item2 in list) { Hide(item2); } } private static Mesh Overlay(in Box box, Vector3 point, Vector3 normal) { //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Expected O, but got Unknown normal = Vector3.Normalize(normal); Vector3 vector = Vector3.Abs(normal); int num = ((!(vector.X >= vector.Y) || !(vector.X >= vector.Z)) ? ((vector.Y >= vector.Z) ? 1 : 2) : 0); Vector3 vector2 = ((num == 1) ? Vector3.UnitX : Vector3.UnitY); Vector3 vector3 = Vector3.Normalize(Vector3.Cross(normal, vector2)); Vector3 vector4 = Vector3.Cross(normal, vector3); float num2 = box.Size.Length() * 2f; List<Vector3> list = Clip.ClipToBox(new List<Vector3> { point + (vector3 + vector4) * num2, point + (vector3 - vector4) * num2, point + (-vector3 - vector4) * num2, point + (-vector3 + vector4) * num2 }, in box); if (list.Count < 3) { return null; } float x = box.Size.X; Il2CppStructArray<Vector3> val = new Il2CppStructArray<Vector3>((long)list.Count); Il2CppStructArray<Vector2> val2 = new Il2CppStructArray<Vector2>((long)list.Count); Il2CppStructArray<Vector3> val3 = new Il2CppStructArray<Vector3>((long)list.Count); for (int i = 0; i < list.Count; i++) { Vector3 vector5 = list[i]; Vector3 vector6 = (vector5 - box.Min) / x; Vector2 v = num switch { 1 => new Vector2(vector6.X, vector6.Z), 0 => new Vector2(vector6.Z, vector6.Y), _ => new Vector2(vector6.X, vector6.Y), }; ((Il2CppArrayBase<Vector3>)(object)val)[i] = U.V3(vector5 + normal * 0.003f); ((Il2CppArrayBase<Vector2>)(object)val2)[i] = U.V2(v); ((Il2CppArrayBase<Vector3>)(object)val3)[i] = U.V3(normal); } List<int> list2 = new List<int>(); bool flag = Vector3.Dot(Vector3.Cross(list[1] - list[0], list[2] - list[0]), normal) < 0f; for (int j = 1; j + 1 < list.Count; j++) { list2.AddRange(flag ? new int[3] { 0, j + 1, j } : new int[3] { 0, j, j + 1 }); } Mesh val4 = new Mesh { name = "Bonecraft crack", vertices = val, uv = val2, normals = val3, triangles = new Il2CppStructArray<int>(list2.ToArray()) }; val4.RecalculateBounds(); return val4; } } internal sealed class Particles { private struct P { public Vector3 Pos; public Vector3 Prev; public Vector3 Vel; public int Age; public int Life; public float Half; public Vector2 Uv; public bool Ground; } private sealed class Group { public readonly List<P> List = new List<P>(); public GameObject Go; public Mesh Mesh; } private const float Tick = 0.05f; private const int MaxPerGroup = 600; private readonly BlockLook look; private readonly Dictionary<string, Group> groups = new Dictionary<string, Group>(); private readonly Random random = new Random(); private float pending; private static float S => BonecraftMod.Settings.BlockSize.Value; public Particles(BlockLook look) { this.look = look; } public void Reset() { foreach (Group value in groups.Values) { if ((Object)(object)value.Go != (Object)null) { Object.Destroy((Object)(object)value.Go); } } groups.Clear(); } private float R() { return (float)random.NextDouble(); } private P Make(Vector3 pos, Vector3 dir) { Vector3 vector = new Vector3(dir.X + (R() * 2f - 1f) * 0.4f, dir.Y + (R() * 2f - 1f) * 0.4f, dir.Z + (R() * 2f - 1f) * 0.4f); float num = (R() + R() + 1f) * 0.15f; float num2 = Math.Max(1E-05f, vector.Length()); vector = vector / num2 * num * 0.4f; vector.Y += 0.1f; return new P { Pos = pos, Prev = pos, Vel = vector, Life = (int)(4f / (R() * 0.9f + 0.1f)), Half = 0.1f * (R() * 0.5f + 0.5f), Uv = new Vector2(R() * 3f / 4f, R() * 3f / 4f) }; } public void Destroy(string key, in Box box) { Group g = GroupFor(key); float x = box.Size.X; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { for (int k = 0; k < 4; k++) { float num = ((float)i + 0.5f) / 4f; float num2 = ((float)j + 0.5f) / 4f; float num3 = ((float)k + 0.5f) / 4f; P p = Make(box.Min + new Vector3(num, num2, num3) * x, new Vector3(num - 0.5f, num2 - 0.5f, num3 - 0.5f)); Add(g, p); } } } } public void Crack(string key, Vector3 point, Vector3 normal, int count) { Group g = GroupFor(key); Vector3 vector = Vector3.Normalize(normal); Vector3 vector2 = ((MathF.Abs(vector.Y) > 0.9f) ? Vector3.UnitX : Vector3.UnitY); Vector3 vector3 = Vector3.Normalize(Vector3.Cross(vector, vector2)); Vector3 vector4 = Vector3.Cross(vector, vector3); for (int i = 0; i < count; i++) { Vector3 pos = point + (vector3 * (R() - 0.5f) + vector4 * (R() - 0.5f)) * 0.6f * S + vector * 0.1f * S; P p = Make(pos, Vector3.Zero); p.Vel = new Vector3(p.Vel.X * 0.2f, (p.Vel.Y - 0.1f) * 0.2f + 0.1f, p.Vel.Z * 0.2f); p.Half *= 0.6f; Add(g, p); } } private static void Add(Group g, P p) { if (g.List.Count < 600) { g.List.Add(p); } } private Group GroupFor(string key) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_003d: 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_0052: Expected O, but got Unknown if (!groups.TryGetValue(key, out var value) || (Object)(object)value.Go == (Object)null) { value = new Group { Go = new GameObject("Bonecraft particles " + key), Mesh = new Mesh { name = "Bonecraft particles" } }; value.Mesh.MarkDynamic(); value.Go.AddComponent<MeshFilter>().sharedMesh = value.Mesh; MeshRenderer obj = value.Go.AddComponent<MeshRenderer>(); ((Renderer)obj).sharedMaterial = look.Particle(key); ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0; groups[key] = value; } return value; } public void Update(float dt) { pending = Math.Min(pending + dt, 0.25f); while (pending >= 0.05f) { pending -= 0.05f; foreach (Group value in groups.Values) { for (int num = value.List.Count - 1; num >= 0; num--) { P p = value.List[num]; if (p.Age++ >= p.Life) { value.List.RemoveAt(num); } else { p.Prev = p.Pos; p.Vel.Y -= 0.04f; Move(ref p); p.Vel *= 0.98f; if (p.Ground) { p.Vel.X *= 0.7f; p.Vel.Z *= 0.7f; } value.List[num] = p; } } } } } private static void Move(ref P p) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) Vector3 vector = p.Vel * S; float num = vector.Length(); if (num < 1E-06f) { return; } Vector3 v = vector / num; RaycastHit val = default(RaycastHit); if (Physics.Raycast(U.V3(p.Pos), U.V3(v), ref val, num + 0.01f, -1, (QueryTriggerInteraction)1) && (Object)(object)((RaycastHit)(ref val)).collider.attachedRigidbody == (Object)null) { Vector3 vector2 = U.N3(((RaycastHit)(ref val)).normal); p.Pos = U.N3(((RaycastHit)(ref val)).point) + vector2 * 0.01f; float num2 = Vector3.Dot(p.Vel, vector2); if (num2 < 0f) { p.Vel -= vector2 * num2; } p.Ground = vector2.Y > 0.5f; } else { p.Pos += vector; p.Ground = false; } } public void Render() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) Transform head = Player.Head; if ((Object)(object)head == (Object)null) { return; } Vector3 vector = U.N3(head.right); Vector3 vector2 = U.N3(head.up); Vector3 v = -U.N3(head.forward); float amount = pending / 0.05f; foreach (Group value in groups.Values) { if ((Object)(object)value.Go == (Object)null) { continue; } int count = value.List.Count; value.Mesh.Clear(); if (count == 0) { continue; } Il2CppStructArray<Vector3> val = new Il2CppStructArray<Vector3>((long)(count * 4)); Il2CppStructArray<Vector2> val2 = new Il2CppStructArray<Vector2>((long)(count * 4)); Il2CppStructArray<Vector3> val3 = new Il2CppStructArray<Vector3>((long)(count * 4)); int[] array = new int[count * 6]; for (int i = 0; i < count; i++) { P p = value.List[i]; Vector3 vector3 = Vector3.Lerp(p.Prev, p.Pos, amount); float num = p.Half * S; Vector3 vector4 = vector * num; Vector3 vector5 = vector2 * num; int num2 = i * 4; ((Il2CppArrayBase<Vector3>)(object)val)[num2] = U.V3(vector3 - vector4 - vector5); ((Il2CppArrayBase<Vector3>)(object)val)[num2 + 1] = U.V3(vector3 - vector4 + vector5); ((Il2CppArrayBase<Vector3>)(object)val)[num2 + 2] = U.V3(vector3 + vector4 + vector5); ((Il2CppArrayBase<Vector3>)(object)val)[num2 + 3] = U.V3(vector3 + vector4 - vector5); float x = p.Uv.X; float y = p.Uv.Y; float num3 = 0.25f; ((Il2CppArrayBase<Vector2>)(object)val2)[num2] = U.V2(new Vector2(x, y)); ((Il2CppArrayBase<Vector2>)(object)val2)[num2 + 1] = U.V2(new Vector2(x, y + num3)); ((Il2CppArrayBase<Vector2>)(object)val2)[num2 + 2] = U.V2(new Vector2(x + num3, y + num3)); ((Il2CppArrayBase<Vector2>)(object)val2)[num2 + 3] = U.V2(new Vector2(x + num3, y)); for (int j = 0; j < 4; j++) { ((Il2CppArrayBase<Vector3>)(object)val3)[num2 + j] = U.V3(v); } int num4 = i * 6; array[num4] = num2; array[num4 + 1] = num2 + 1; array[num4 + 2] = num2 + 2; array[num4 + 3] = num2; array[num4 + 4] = num2 + 2; array[num4 + 5] = num2 + 3; } value.Mesh.vertices = val; value.Mesh.uv = val2; value.Mesh.normals = val3; value.Mesh.triangles = new Il2CppStructArray<int>(array); value.Mesh.RecalculateBounds(); } } } internal static class GpuRead { public sealed class Job { public IntPtr Buffer; public byte[] Data; public string Error; public volatile bool Done; } private struct BufferDesc { public uint ByteWidth; public uint Usage; public uint BindFlags; public uint CpuAccessFlags; public uint MiscFlags; public uint StructureByteStride; } private struct Mapped { public IntPtr Data; public uint RowPitch; public uint DepthPitch; } private const int Release = 2; private const int GetDevice = 3; private const int BufferGetDesc = 10; private const int CreateBuffer = 3; private const int GetImmediateContext = 40; private const int Map = 14; private const int Unmap = 15; private const int CopyResource = 47; private const uint UsageStaging = 3u; private const uint CpuAccessRead = 131072u; private const uint MapRead = 1u; private static readonly ConcurrentQueue<Job> queue = new ConcurrentQueue<Job>(); private static readonly Dictionary<IntPtr, (Job job, float at)> recent = new Dictionary<IntPtr, (Job, float)>(); private unsafe static readonly IntPtr callback = (IntPtr)(delegate*<int, void>)(&OnRenderThread); private static bool issued; public static bool Supported => (int)SystemInfo.graphicsDeviceType == 2; public static Job Request(IntPtr d3dBuffer) { Job job = new Job { Buffer = d3dBuffer }; if (d3dBuffer == IntPtr.Zero) { job.Error = "no GPU buffer"; job.Done = true; return job; } if (recent.TryGetValue(d3dBuffer, out (Job, float) value) && Time.unscaledTime - value.Item2 < 5f && value.Item1.Error == null) { return value.Item1; } recent[d3dBuffer] = (job, Time.unscaledTime); queue.Enqueue(job); issued = false; return job; } public static void Pump() { if (!issued && !queue.IsEmpty) { issued = true; GL.IssuePluginEvent(callback, 0); } } [UnmanagedCallersOnly] private static void OnRenderThread(int eventId) { issued = false; Job result; while (queue.TryDequeue(out result)) { try { result.Data = Copy(result.Buffer); } catch (Exception ex) { result.Error = ex.Message; } result.Done = true; } } private unsafe static void* Slot(IntPtr com, int index) { return *(void**)((nint)(*(IntPtr*)(void*)com) + (nint)index * (nint)sizeof(void*)); } private unsafe static byte[] Copy(IntPtr buffer) { BufferDesc bufferDesc = default(BufferDesc); ((delegate* unmanaged[Stdcall]<IntPtr, BufferDesc*, void>)Slot(buffer, 10))(buffer, &bufferDesc); IntPtr intPtr = default(IntPtr); ((delegate* unmanaged[Stdcall]<IntPtr, IntPtr*, void>)Slot(buffer, 3))(buffer, &intPtr); IntPtr intPtr2 = default(IntPtr); ((delegate* unmanaged[Stdcall]<IntPtr, IntPtr*, void>)Slot(intPtr, 40))(intPtr, &intPtr2); IntPtr zero = IntPtr.Zero; try { BufferDesc bufferDesc2 = new BufferDesc { ByteWidth = bufferDesc.ByteWidth, Usage = 3u, CpuAccessFlags = 131072u }; int num = ((delegate* unmanaged[Stdcall]<IntPtr, BufferDesc*, void*, IntPtr*, int>)Slot(intPtr, 3))(intPtr, &bufferDesc2, null, &zero); if (num < 0) { throw new InvalidOperationException($"CreateBuffer failed (0x{num:x8})"); } ((delegate* unmanaged[Stdcall]<IntPtr, IntPtr, IntPtr, void>)Slot(intPtr2, 47))(intPtr2, zero, buffer); Mapped mapped = default(Mapped); num = ((delegate* unmanaged[Stdcall]<IntPtr, IntPtr, uint, uint, uint, Mapped*, int>)Slot(intPtr2, 14))(intPtr2, zero, 0u, 1u, 0u, &mapped); if (num < 0) { throw new InvalidOperationException($"Map failed (0x{num:x8})"); } byte[] array = new byte[bufferDesc.ByteWidth]; Marshal.Copy(mapped.Data, array, 0, array.Length); ((delegate* unmanaged[Stdcall]<IntPtr, IntPtr, uint, void>)Slot(intPtr2, 15))(intPtr2, zero, 0u); return array; } finally { if (zero != IntPtr.Zero) { ((delegate* unmanaged[Stdcall]<IntPtr, uint>)Slot(zero, 2))(zero); } ((delegate* unmanaged[Stdcall]<IntPtr, uint>)Slot(intPtr2, 2))(intPtr2); ((delegate* unmanaged[Stdcall]<IntPtr, uint>)Slot(intPtr, 2))(intPtr); } } } internal static class Json { public static string Obj(params object[] keyValues) { StringBuilder stringBuilder = new StringBuilder("{"); for (int i = 0; i + 1 < keyValues.Length; i += 2) { if (i > 0) { stringBuilder.Append(','); } Str(stringBuilder, (string)keyValues[i]); stringBuilder.Append(':'); Value(stringBuilder, keyValues[i + 1]); } return stringBuilder.Append('}').ToString(); } private static void Value(StringBuilder sb, object v) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) if (v != null) { if (!(v is string s)) { if (!(v is bool flag)) { if (!(v is float f)) { if (!(v is int[] values)) { if (v is Vector3 val) { sb.Append('['); Num(sb, val.x); sb.Append(','); Num(sb, val.y); sb.Append(','); Num(sb, val.z); sb.Append(']'); } else { sb.Append(Convert.ToString(v, CultureInfo.InvariantCulture)); } } else { sb.Append('[').Append(string.Join(",", values)).Append(']'); } } else { Num(sb, f); } } else { sb.Append(flag ? "true" : "false"); } } else { Str(sb, s); } } else { sb.Append("null"); } } private static void Num(StringBuilder sb, float f) { sb.Append(float.IsFinite(f) ? f.ToString("0.####", CultureInfo.InvariantCulture) : "0"); } private static void Str(StringBuilder sb, string s) { sb.Append('"'); foreach (char c in s) { if (c != '"') { if (c == '\\') { sb.Append("\\\\"); } else if (c < ' ') { StringBuilder stringBuilder = sb.Append("\\u"); int num = c; stringBuilder.Append(num.ToString("x4")); } else { sb.Append(c); } } else { sb.Append("\\\""); } } sb.Append('"'); } } internal sealed class Link : IDisposable { private readonly Uri uri; private readonly Instance log; private readonly CancellationTokenSource stop = new CancellationTokenSource(); private readonly BlockingCollection<string> outbox = new BlockingCollection<string>(new ConcurrentQueue<string>(), 256); private readonly ConcurrentQueue<string> inbox = new ConcurrentQueue<string>(); private readonly ConcurrentQueue<Action> mainThread = new ConcurrentQueue<Action>(); private volatile ClientWebSocket socket; public bool IsOpen { get { ClientWebSocket clientWebSocket = socket; if (clientWebSocket == null) { return false; } return clientWebSocket.State == WebSocketState.Open; } } public event Action Connected; public Link(string url, Instance log) { uri = new Uri(url); this.log = log; } public void Start() { Task.Run((Func<Task?>)Run); } public void Send(string json) { if (IsOpen) { outbox.TryAdd(json); } } public IEnumerable<string> Drain() { Action result; while (mainThread.TryDequeue(out result)) { result(); } string result2; while (inbox.TryDequeue(out result2)) { yield return result2; } } private async Task Run() { bool announced = false; while (!stop.IsCancellationRequested) { using ClientWebSocket ws = new ClientWebSocket(); try { await ws.ConnectAsync(uri, stop.Token); socket = ws; announced = false; log.Msg($"connected to Minecraft at {uri}"); mainThread.Enqueue(delegate { this.Connected?.Invoke(); }); Task reader = Read(ws); while (ws.State == WebSocketState.Open && !reader.IsCompleted) { if (outbox.TryTake(out var item, 100, stop.Token)) { await ws.SendAsync(Encoding.UTF8.GetBytes(item), WebSocketMessageType.Text, endOfMessage: true, stop.Token); } } log.Warning("lost the connection to Minecraft"); } catch (OperationCanceledException) { break; } catch (Exception ex2) { if (!announced) { announced = true; log.Msg($"waiting for Minecraft at {uri} ({ex2.GetType().Name})"); } } finally { socket = null; string item2; while (outbox.TryTake(out item2)) { } } try { await Task.Delay(2000, stop.Token); } catch (OperationCanceledException) { break; } } } private async Task Read(ClientWebSocket ws) { byte[] buffer = new byte[16384]; StringBuilder text = new StringBuilder(); try { while (ws.State == WebSocketState.Open) { WebSocketReceiveResult webSocketReceiveResult = await ws.ReceiveAsync(buffer, stop.Token); if (webSocketReceiveResult.MessageType == WebSocketMessageType.Close) { break; } text.Append(Encoding.UTF8.GetString(buffer, 0, webSocketReceiveResult.Count)); if (webSocketReceiveResult.EndOfMessage) { inbox.Enqueue(text.ToString()); text.Clear(); } } } catch (Exception) { } } public void Dispose() { stop.Cancel(); } } internal static class Materials { private static readonly (string surface, string block)[] Surfaces = new(string, string)[21] { ("redbrick", "minecraft:bricks"), ("red brick", "minecraft:bricks"), ("concrete", "minecraft:light_gray_concrete"), ("crystalline", "minecraft:amethyst_block"), ("glass", "minecraft:glass"), ("pure metal", "minecraft:iron_block"), ("metal", "minecraft:iron_block"), ("hydraulic", "minecraft:iron_block"), ("wood", "minecraft:oak_planks"), ("dirt", "minecraft:dirt"), ("plant", "minecraft:moss_block"), ("cloth", "minecraft:white_wool"), ("cardboard", "minecraft:brown_wool"), ("paper", "minecraft:white_wool"), ("polymer", "minecraft:white_concrete"), ("bioluminescent", "minecraft:shroomlight"), ("void", "minecraft:black_concrete"), ("bone", "minecraft:bone_block"), ("blood", "minecraft:redstone_block"), ("melon", "minecraft:melon"), ("zapper", "minecraft:redstone_block") }; private static readonly (string word, string block)[] Refinements = new(string, string)[27] { ("grass", "minecraft:grass_block"), ("lawn", "minecraft:grass_block"), ("sandstone", "minecraft:sandstone"), ("sand", "minecraft:sand"), ("gravel", "minecraft:gravel"), ("snow", "minecraft:snow_block"), ("mud", "minecraft:mud"), ("brick", "minecraft:bricks"), ("cobble", "minecraft:cobblestone"), ("marble", "minecraft:quartz_block"), ("tile", "minecraft:smooth_quartz"), ("asphalt", "minecraft:gray_concrete"), ("road", "minecraft:gray_concrete"), ("rock", "minecraft:stone"), ("cliff", "minecraft:stone"), ("stone", "minecraft:stone"), ("plaster", "minecraft:white_concrete"), ("drywall", "minecraft:white_concrete"), ("rust", "minecraft:oxidized_copper"), ("copper", "minecraft:copper_block"), ("gold", "minecraft:gold_block"), ("bark", "minecraft:oak_log"), ("trunk", "minecraft:oak_log"), ("log", "minecraft:oak_log"), ("darkwood", "minecraft:dark_oak_planks"), ("carpet", "minecraft:red_wool"), ("lava", "minecraft:magma_block") }; private static bool Refines(string surfaceBlock, string refined) { switch (surfaceBlock) { case "minecraft:dirt": { bool result; switch (refined) { case "minecraft:grass_block": case "minecraft:sand": case "minecraft:gravel": case "minecraft:snow_block": case "minecraft:mud": case "minecraft:stone": result = true; break; default: result = false; break; } return result; } case "minecraft:light_gray_concrete": { bool result; switch (refined) { case "minecraft:gray_concrete": case "minecraft:smooth_quartz": case "minecraft:bricks": case "minecraft:cobblestone": case "minecraft:quartz_block": case "minecraft:stone": case "minecraft:white_concrete": case "minecraft:sandstone": case "minecraft:snow_block": result = true; break; default: result = false; break; } return result; } case "minecraft:iron_block": { bool result; switch (refined) { case "minecraft:oxidized_copper": case "minecraft:copper_block": case "minecraft:gold_block": result = true; break; default: result = false; break; } return result; } case "minecraft:oak_planks": return (refined == "minecraft:oak_log" || refined == "minecraft:dark_oak_planks") ? true : false; case "minecraft:white_wool": return refined == "minecraft:red_wool"; default: return false; } } public static string BlockFor(Collider collider, Renderer surface) { string text = Match(Names(collider, surface), Refinements); string text2 = SurfaceName(collider); if (text2 != null) { string text3 = Match(text2, Surfaces); if (text3 != null) { if (text == null || !Refines(text3, text)) { return text3; } return text; } } return text ?? BlockLook.Guess(collider, surface); } public static string SurfaceName(Collider c) { try { ImpactProperties val = ((Component)c).GetComponent<ImpactProperties>(); if ((Object)(object)val == (Object)null && (Object)(object)c.attachedRigidbody == (Object)null) { val = ((Component)c).GetComponentInParent<ImpactProperties>(); } SurfaceData val2 = (((Object)(object)val == (Object)null) ? null : (val.surfaceData ?? val._cachedSurfaceData)); return ((Object)(object)val2 == (Object)null) ? null : ((Object)val2).name.ToLowerInvariant(); } catch { return null; } } private static string Names(Collider c, Renderer r) { string text = ((Object)((Component)c).gameObject).name + " " + (((Object)(object)c.sharedMaterial != (Object)null) ? ((Object)c.sharedMaterial).name : ""); if ((Object)(object)r != (Object)null) { text = text + " " + ((Object)((Component)r).gameObject).name; foreach (Material item in (Il2CppArrayBase<Material>)(object)r.sharedMaterials) { if ((Object)(object)item != (Object)null) { text = text + " " + ((Object)item).name; } } } return text.ToLowerInvariant(); } private static string Match(stri