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 DeathRecap v1.0.6
plugins/DeathRecap.dll
Decompiled 3 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Splatform; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("DeathRecap")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("DeathRecap")] [assembly: AssemblyTitle("DeathRecap")] [assembly: AssemblyVersion("1.0.0.0")] namespace DeathRecap; [BepInPlugin("anwo.DeathRecap", "DeathRecap", "1.0.6")] public class DeathRecapPlugin : BaseUnityPlugin { internal sealed class HitEntry { public float Time; public string Source; public float Raw; public float Taken; public float HealthAfter; public float MaxHealth; public DamageTypes Types; public bool HasTypes; } internal sealed class Recap { public DateTime When; public List<HitEntry> Hits = new List<HitEntry>(); public List<KeyValuePair<string, float>> ByAttacker = new List<KeyValuePair<string, float>>(); public List<KeyValuePair<string, float>> ByType = new List<KeyValuePair<string, float>>(); public float DeathTime; } public const string Guid = "anwo.DeathRecap"; public const string Name = "DeathRecap"; public const string Version = "1.0.6"; internal static DeathRecapPlugin Instance; internal static ConfigEntry<KeyboardShortcut> RecapKey; internal static ConfigEntry<bool> ShowOnDeath; internal static ConfigEntry<bool> KeepOpenAfterRespawn; internal static ConfigEntry<float> HistorySeconds; internal static ConfigEntry<int> MaxLines; internal static ConfigEntry<float> Scale; internal static ConfigEntry<bool> ShowGraves; internal static ConfigEntry<bool> AnnounceDeaths; internal static ManualLogSource Log; private readonly List<HitEntry> _history = new List<HitEntry>(); private Recap _recap; private bool _show; private bool _deathPending; private Player _deadPlayer; private Rect _window = new Rect(60f, 80f, 660f, 560f); private Vector2 _scroll; private Harmony _harmony; private GUIStyle _bold; private GUIStyle _rich; internal static HitData PendingHit; internal static float PendingRaw; internal static DamageTypes PendingTypes; private void Awake() { //IL_002b: 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_00b7: Expected O, but got Unknown //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Expected O, but got Unknown //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Expected O, but got Unknown //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Expected O, but got Unknown //IL_01ce: Unknown result type (might be due to invalid IL or missing references) Instance = this; Log = ((BaseUnityPlugin)this).Logger; RecapKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("1 - General", "Recap key", new KeyboardShortcut((KeyCode)279, Array.Empty<KeyCode>()), "Opens or closes the recap of your last death."); ShowOnDeath = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Show on death", true, "Open the recap automatically when you die."); KeepOpenAfterRespawn = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Keep open after respawn", false, "Keep the recap open after you respawn. When off, it closes as soon as you are back."); HistorySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Recap", "Seconds of history", 30f, new ConfigDescription("How many seconds before your death the recap covers.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 300f), Array.Empty<object>())); MaxLines = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Recap", "Max hits listed", 25, new ConfigDescription("How many individual hits the recap lists.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 200), Array.Empty<object>())); Scale = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Look", "Scale", 1f, new ConfigDescription("Size of the recap window.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.6f, 2.5f), Array.Empty<object>())); ShowGraves = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Graves", "Show graves of other players", true, "Marks other players' graves on your map with a skull, until they have taken their things back. Needs DeathRecap on the host (or the dedicated server) too, which keeps track of the graves."); AnnounceDeaths = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Graves", "Announce deaths", true, "Says on screen and in the chat when another player dies, and in which biome. Only while Show graves of other players is on."); ((BaseUnityPlugin)this).Config.Save(); _harmony = new Harmony("anwo.DeathRecap"); _harmony.PatchAll(typeof(DamagePatches)); _harmony.PatchAll(typeof(GravePatches)); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} {1} loaded. Recap key: {2}", "DeathRecap", "1.0.6", RecapKey.Value)); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } internal void Record(Character victim, HitData hit, float healthBefore) { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) try { float health = victim.GetHealth(); float num = Mathf.Max(0f, healthBefore - health); float totalDamage = hit.GetTotalDamage(); if (!(num < 0.05f) || !(totalDamage < 0.1f)) { HitEntry hitEntry = new HitEntry { Time = Time.time, Source = DescribeSource(hit), Taken = num, HealthAfter = health, MaxHealth = victim.GetMaxHealth() }; if (PendingHit == hit) { hitEntry.Raw = PendingRaw; hitEntry.Types = PendingTypes; hitEntry.HasTypes = true; } else { hitEntry.Raw = totalDamage; hitEntry.Types = hit.m_damage; hitEntry.HasTypes = true; } PendingHit = null; _history.Add(hitEntry); float cutoff = Time.time - HistorySeconds.Value; _history.RemoveAll((HitEntry h) => h.Time < cutoff); if (_history.Count > 500) { _history.RemoveRange(0, _history.Count - 500); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogDebug((object)("Record failed: " + ex.Message)); } } internal void OnLocalDeath(Player player) { _deathPending = true; _deadPlayer = player; } private static string DescribeSource(HitData hit) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Invalid comparison between Unknown and I4 //IL_007c: 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: Invalid comparison between Unknown and I4 //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Invalid comparison between Unknown and I4 //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Invalid comparison between Unknown and I4 //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Invalid comparison between Unknown and I4 //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Invalid comparison between Unknown and I4 string text = HitTypeName(hit.m_hitType); Character val = null; try { val = hit.GetAttacker(); } catch { } if ((Object)(object)val != (Object)null) { Player val2 = (Player)(object)((val is Player) ? val : null); string text2; if (val2 != null) { text2 = val2.GetPlayerName(); } else { text2 = val.GetHoverName(); int num = val.GetLevel() - 1; if (num > 0) { text2 = text2 + " " + new string('★', Mathf.Min(num, 10)); } } if ((Object)(object)val == (Object)(object)Player.m_localPlayer) { if ((int)hit.m_hitType == 0 || (int)hit.m_hitType == 14 || (int)hit.m_hitType == 2 || (int)hit.m_hitType == 1) { return "Yourself"; } return text + " (caused by you)"; } if ((int)hit.m_hitType != 5 && (int)hit.m_hitType != 7 && (int)hit.m_hitType != 6) { return text2; } return text2 + " (" + text.ToLowerInvariant() + ")"; } return text; } private static string HitTypeName(HitType t) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected I4, but got Unknown return (t - 1) switch { 2 => "Fall damage", 3 => "Drowning", 4 => "Burning", 5 => "Freezing", 6 => "Poison", 7 => "Water", 8 => "Smoke", 9 => "Edge of the world", 10 => "Hit by an object", 13 => "Yourself", 14 => "Falling building piece", 15 => "Turret", 16 => "Boat", 18 => "Catapult", 19 => "Cinder fire", 20 => "Boiling sea", 21 => "Lava", 12 => "Falling tree", 17 => "Falling icicle", 11 => "Cart", 22 => "Obliterator", 23 => "Drawbridge", 0 => "An enemy", 1 => "Another player", _ => "Unknown attacker", }; } private void BuildRecap() { Recap recap = new Recap { When = DateTime.Now, DeathTime = Time.time }; float cutoff = recap.DeathTime - HistorySeconds.Value; List<HitEntry> list = _history.Where((HitEntry h) => h.Time >= cutoff).ToList(); list.Reverse(); recap.Hits = list; recap.ByAttacker = (from h in list group h by h.Source into g select new KeyValuePair<string, float>(g.Key, g.Sum((HitEntry h) => h.Taken)) into kv orderby kv.Value descending select kv).ToList(); Dictionary<string, float> dictionary = new Dictionary<string, float>(); foreach (HitEntry item in list) { if (item.HasTypes) { Add(dictionary, "Blunt", item.Types.m_blunt); Add(dictionary, "Slash", item.Types.m_slash); Add(dictionary, "Pierce", item.Types.m_pierce); Add(dictionary, "Fire", item.Types.m_fire); Add(dictionary, "Frost", item.Types.m_frost); Add(dictionary, "Lightning", item.Types.m_lightning); Add(dictionary, "Poison", item.Types.m_poison); Add(dictionary, "Spirit", item.Types.m_spirit); Add(dictionary, "Other", item.Types.m_damage); } } recap.ByType = (from kv in dictionary where kv.Value > 0.05f orderby kv.Value descending select kv).ToList(); _recap = recap; _history.Clear(); } private static void Add(Dictionary<string, float> d, string k, float v) { if (!(v <= 0f)) { d.TryGetValue(k, out var value); d[k] = value + v; } } private void Update() { //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) Graves.Tick(); try { if (_deathPending) { _deathPending = false; BuildRecap(); if (ShowOnDeath.Value) { _show = true; } } if (!IsTyping()) { KeyboardShortcut value = RecapKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { if (_recap == null) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, "No death recorded yet this session", 0, (Sprite)null, false); } } else { _show = !_show; } } } if (_show && !KeepOpenAfterRespawn.Value && (Object)(object)_deadPlayer != (Object)null) { Player localPlayer2 = Player.m_localPlayer; if ((Object)(object)localPlayer2 != (Object)null && (Object)(object)localPlayer2 != (Object)(object)_deadPlayer && !((Character)localPlayer2).IsDead()) { _show = false; _deadPlayer = null; } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogDebug((object)("Update failed: " + ex.Message)); } } private static bool IsTyping() { try { if (Console.IsVisible() || TextInput.IsVisible() || Menu.IsVisible() || Minimap.InTextInput()) { return true; } Chat instance = Chat.instance; return (Object)(object)instance != (Object)null && instance.HasFocus(); } catch { return false; } } private void OnGUI() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) if (!_show || _recap == null) { return; } try { Matrix4x4 matrix = GUI.matrix; float value = Scale.Value; GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(value, value, 1f)); GUISkin skin = GUI.skin; GUI.skin = PanelSkin.Get(); _window = GUILayout.Window(384679, _window, new WindowFunction(DrawWindow), "What killed you", GUI.skin.window, Array.Empty<GUILayoutOption>()); GUI.skin = skin; GUI.matrix = matrix; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogDebug((object)("OnGUI failed: " + ex.Message)); } } private void DrawWindow(int id) { GUISkin skin = GUI.skin; GUI.skin = PanelSkin.Get(); try { DrawWindowContent(); } finally { GUI.skin = skin; } } private void DrawWindowContent() { //IL_001a: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_03e6: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) Recap recap = _recap; if (_bold == null) { _bold = new GUIStyle(GUI.skin.label) { fontStyle = (FontStyle)1, richText = true }; _rich = new GUIStyle(GUI.skin.label) { richText = true, wordWrap = true }; } GUIStyle bold = _bold; GUIStyle rich = _rich; if (recap.Hits.Count == 0) { GUILayout.Label("No damage was recorded before this death (for example, it came from a console command or a mod).", rich, Array.Empty<GUILayoutOption>()); } else { HitEntry hitEntry = recap.Hits[0]; GUILayout.Label($"Killing blow: <color=#ff6b5a>{Esc(hitEntry.Source)}</color> for {hitEntry.Taken:0} damage", bold, Array.Empty<GUILayoutOption>()); float num = recap.DeathTime - recap.Hits[recap.Hits.Count - 1].Time; float num2 = recap.Hits.Sum((HitEntry h) => h.Taken); GUILayout.Label(string.Format("{0} {1}, {2:0} damage taken in the last {3:0.0} s before death", recap.Hits.Count, (recap.Hits.Count == 1) ? "hit" : "hits", num2, num), rich, Array.Empty<GUILayoutOption>()); GUILayout.Space(6f); GUILayout.Label("Damage by attacker", bold, Array.Empty<GUILayoutOption>()); foreach (KeyValuePair<string, float> item in recap.ByAttacker.Take(8)) { GUILayout.Label($" {Esc(item.Key)}: {item.Value:0} ({((num2 > 0f) ? (item.Value / num2 * 100f) : 0f):0}%)", rich, Array.Empty<GUILayoutOption>()); } if (recap.ByType.Count > 0) { GUILayout.Space(6f); GUILayout.Label("Damage by type (before armour and resistances)", bold, Array.Empty<GUILayoutOption>()); GUILayout.Label(" " + string.Join(", ", recap.ByType.Select((KeyValuePair<string, float> kv) => $"{kv.Key} {kv.Value:0}")), rich, Array.Empty<GUILayoutOption>()); } GUILayout.Space(6f); GUILayout.Label("Hits, newest first", bold, Array.Empty<GUILayoutOption>()); _scroll = GUILayout.BeginScrollView(_scroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(200f) }); foreach (HitEntry item2 in recap.Hits.Take(MaxLines.Value)) { float num3 = recap.DeathTime - item2.Time; string text = ((item2.Raw > 0.5f && item2.Taken < item2.Raw * 0.35f) ? " (mostly blocked or resisted)" : ""); GUILayout.Label($" -{num3:0.0} s {Esc(item2.Source)}: lost {item2.Taken:0} of {item2.Raw:0}{text}, health left {Mathf.Max(0f, item2.HealthAfter):0}/{item2.MaxHealth:0}", rich, Array.Empty<GUILayoutOption>()); } GUILayout.EndScrollView(); } GUILayout.Space(6f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label($"{RecapKey.Value} closes this and opens it again later.", rich, Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Close", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) })) { _show = false; } GUILayout.EndHorizontal(); GUI.DragWindow(); } private static string Esc(string s) { return (s ?? "").Replace("<", "‹").Replace(">", "›"); } } internal static class DamagePatches { [HarmonyPrefix] [HarmonyPatch(typeof(Character), "RPC_Damage")] private static void RpcDamagePrefix(Character __instance, HitData hit) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) try { if (hit != null && !((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { DeathRecapPlugin.PendingHit = hit; DeathRecapPlugin.PendingRaw = hit.GetTotalDamage(); DeathRecapPlugin.PendingTypes = hit.m_damage; } } catch { } } [HarmonyPrefix] [HarmonyPatch(typeof(Character), "ApplyDamage")] private static void ApplyDamagePrefix(Character __instance, out float __state) { __state = -1f; try { if ((Object)(object)__instance != (Object)null && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && !__instance.IsDead()) { __state = __instance.GetHealth(); } } catch { } } [HarmonyPostfix] [HarmonyPatch(typeof(Character), "ApplyDamage")] private static void ApplyDamagePostfix(Character __instance, HitData hit, float __state) { if (!(__state < 0f) && hit != null) { DeathRecapPlugin.Instance?.Record(__instance, hit, __state); } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "OnDeath")] private static void OnDeathPostfix(Player __instance) { try { if ((Object)(object)__instance != (Object)null && (Object)(object)__instance == (Object)(object)Player.m_localPlayer) { DeathRecapPlugin.Instance?.OnLocalDeath(__instance); } } catch { } } } internal static class Graves { internal sealed class Grave { public ZDOID Id; public Vector3 Pos; public string Name; public long Owner; } private sealed class Shown { public Grave Grave; public PinData Pin; } private const string RpcList = "anwo_dr_graves"; private const string RpcRequest = "anwo_dr_graves_req"; private const string TombstonePrefab = "Player_tombstone"; private const float RescanPause = 20f; private const int ScanEvery = 4; private static readonly List<ZDO> s_found = new List<ZDO>(); private static int s_scanIndex; private static float s_nextScan; private static string s_signature = ""; private static List<Grave> s_current = new List<Grave>(); private static bool s_scanned; private static readonly Dictionary<ZDOID, Shown> s_shown = new Dictionary<ZDOID, Shown>(); private static List<Grave> s_pending; private static bool s_registered; private static bool s_requested; private static bool s_firstList = true; private static float s_nextPinCheck; private static bool s_failureLogged; private static readonly FieldRef<Minimap, List<PinData>> MapPins = MakeMapPins(); private static FieldRef<Minimap, List<PinData>> MakeMapPins() { try { return AccessTools.FieldRefAccess<Minimap, List<PinData>>("m_pins"); } catch { return null; } } internal static void Register() { s_found.Clear(); s_scanIndex = 0; s_nextScan = 0f; s_signature = ""; s_current = new List<Grave>(); s_scanned = false; s_shown.Clear(); s_pending = null; s_requested = false; s_firstList = true; s_registered = false; if (ZRoutedRpc.instance != null) { ZRoutedRpc.instance.Register<ZPackage>("anwo_dr_graves", (Action<long, ZPackage>)OnList); ZRoutedRpc.instance.Register("anwo_dr_graves_req", (Action<long>)OnRequest); s_registered = true; } } internal static void Tick() { if (!s_registered) { return; } try { if (!((Object)(object)ZNet.instance == (Object)null) && ZRoutedRpc.instance != null) { if (ZNet.instance.IsServer()) { HostTick(); } ClientTick(); } } catch (Exception ex) { if (!s_failureLogged) { s_failureLogged = true; ManualLogSource log = DeathRecapPlugin.Log; if (log != null) { log.LogWarning((object)("Shared graves failed (reported once): " + ex)); } } } } private static void HostTick() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) if (Time.time < s_nextScan || ZDOMan.instance == null || Time.frameCount % 4 != 0 || !ZDOMan.instance.GetAllZDOsWithPrefabIterative("Player_tombstone", s_found, ref s_scanIndex)) { return; } List<Grave> list = new List<Grave>(); foreach (ZDO item in s_found) { if (item != null && item.IsValid()) { list.Add(new Grave { Id = item.m_uid, Pos = item.GetPosition(), Name = item.GetString(ZDOVars.s_ownerName, ""), Owner = item.GetLong(ZDOVars.s_owner, 0L) }); } } s_found.Clear(); s_scanIndex = 0; s_nextScan = Time.time + 20f; list.Sort((Grave a, Grave b) => ((ZDOID)(ref a.Id)).CompareTo(b.Id)); StringBuilder stringBuilder = new StringBuilder(); foreach (Grave item2 in list) { stringBuilder.Append(item2.Id).Append('@').Append(Mathf.RoundToInt(item2.Pos.x / 4f)) .Append(',') .Append(Mathf.RoundToInt(item2.Pos.z / 4f)) .Append(';'); } string text = stringBuilder.ToString(); bool num = !s_scanned || text != s_signature; s_signature = text; s_current = list; s_scanned = true; if (num) { Send(0L, list); } } private static void OnRequest(long sender) { if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && s_scanned) { Send(sender, s_current); } } private static void Send(long target, List<Grave> graves) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); val.Write(1); val.Write(graves.Count); foreach (Grave grafe in graves) { val.Write(grafe.Id); val.Write(grafe.Pos); val.Write(grafe.Name ?? ""); val.Write(grafe.Owner); } ZRoutedRpc.instance.InvokeRoutedRPC(target, "anwo_dr_graves", new object[1] { val }); } private static void OnList(long sender, ZPackage pkg) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) try { if (pkg.ReadInt() == 1) { int num = pkg.ReadInt(); List<Grave> list = new List<Grave>(Mathf.Clamp(num, 0, 1000)); for (int i = 0; i < num; i++) { list.Add(new Grave { Id = pkg.ReadZDOID(), Pos = pkg.ReadVector3(), Name = pkg.ReadString(), Owner = pkg.ReadLong() }); } s_pending = list; } } catch (Exception ex) { ManualLogSource log = DeathRecapPlugin.Log; if (log != null) { log.LogDebug((object)("Reading the grave list failed: " + ex.Message)); } } } private static void ClientTick() { Player localPlayer = Player.m_localPlayer; if (!s_requested && (Object)(object)localPlayer != (Object)null) { s_requested = true; ZRoutedRpc.instance.InvokeRoutedRPC("anwo_dr_graves_req", Array.Empty<object>()); } Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null) { return; } if (!DeathRecapPlugin.ShowGraves.Value) { if (s_shown.Count > 0) { RemoveAll(instance); } return; } if (s_pending != null && (Object)(object)localPlayer != (Object)null) { List<Grave> list = s_pending; s_pending = null; Apply(instance, list); } if (Time.time >= s_nextPinCheck) { s_nextPinCheck = Time.time + 5f; KeepPins(instance); } } private static void Apply(Minimap map, List<Grave> list) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) long num = (((Object)(object)Game.instance != (Object)null && Game.instance.GetPlayerProfile() != null) ? Game.instance.GetPlayerProfile().GetPlayerID() : 0); HashSet<ZDOID> keep = new HashSet<ZDOID>(); foreach (Grave item in list) { if (num != 0L && item.Owner == num) { continue; } keep.Add(item.Id); if (s_shown.TryGetValue(item.Id, out var value)) { value.Grave = item; if (value.Pin != null) { value.Pin.m_pos = item.Pos; } continue; } s_shown[item.Id] = new Shown { Grave = item, Pin = AddPin(map, item) }; if (!s_firstList && DeathRecapPlugin.AnnounceDeaths.Value) { Announce(item); } } foreach (ZDOID item2 in s_shown.Keys.Where((ZDOID k) => !keep.Contains(k)).ToList()) { Shown shown = s_shown[item2]; if (shown.Pin != null) { map.RemovePin(shown.Pin); } s_shown.Remove(item2); } s_firstList = false; } private static PinData AddPin(Minimap map, Grave g) { //IL_0002: 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_001a: Unknown result type (might be due to invalid IL or missing references) return map.AddPin(g.Pos, (PinType)4, Label(g), false, false, 0L, default(PlatformUserID)); } private static string Label(Grave g) { if (!string.IsNullOrEmpty(g.Name)) { return g.Name + "'s grave"; } return "Grave"; } private static void KeepPins(Minimap map) { if (MapPins == null || s_shown.Count == 0) { return; } List<PinData> list = MapPins.Invoke(map); if (list == null) { return; } foreach (Shown value in s_shown.Values) { if (value.Pin == null || !list.Contains(value.Pin)) { value.Pin = AddPin(map, value.Grave); } } } private static void RemoveAll(Minimap map) { foreach (Shown value in s_shown.Values) { if (value.Pin != null) { map.RemovePin(value.Pin); } } s_shown.Clear(); s_firstList = true; s_requested = false; } private unsafe static void Announce(Grave g) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Invalid comparison between Unknown and I4 //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Invalid comparison between Unknown and I4 string text = (string.IsNullOrEmpty(g.Name) ? "Someone" : g.Name); string text2 = ""; try { if (WorldGenerator.instance != null && Localization.instance != null) { Biome biome = WorldGenerator.instance.GetBiome(g.Pos); string text3 = Localization.instance.Localize("$biome_" + ((object)(*(Biome*)(&biome))/*cast due to .constrained prefix*/).ToString().ToLowerInvariant()); if ((int)biome == 256) { text2 = " at sea"; } else if ((int)biome == 4) { text2 = " in the mountains"; } else if (!string.IsNullOrEmpty(text3) && !text3.StartsWith("[")) { text2 = " in the " + text3; } } } catch { } string text4 = text + " died" + text2 + ". Their grave is marked on your map."; MessageHud instance = MessageHud.instance; if (instance != null) { instance.ShowMessage((MessageType)1, text4, 0, (Sprite)null, false, false); } Chat instance2 = Chat.instance; if (instance2 != null) { ((Terminal)instance2).AddString("<color=#e07070>" + text4 + "</color>"); } } } internal static class GravePatches { [HarmonyPostfix] [HarmonyPatch(typeof(Game), "Start")] private static void GameStart() { try { Graves.Register(); } catch (Exception ex) { ManualLogSource log = DeathRecapPlugin.Log; if (log != null) { log.LogWarning((object)("Registering shared graves failed: " + ex.Message)); } } } } internal static class PanelSkin { private static GUISkin s_skin; internal static GUISkin Get() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: 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_00b8: Expected O, but got Unknown //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Expected O, but got Unknown //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Expected O, but got Unknown //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Expected O, but got Unknown //IL_016b: Expected O, but got Unknown //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Expected O, but got Unknown //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Expected O, but got Unknown //IL_0286: Expected O, but got Unknown //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Expected O, but got Unknown //IL_0323: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)s_skin != (Object)null) { return s_skin; } GUISkin val = Object.Instantiate<GUISkin>(GUI.skin); ((Object)val).hideFlags = (HideFlags)61; Color color = default(Color); ((Color)(ref color))..ctor(0.95f, 0.93f, 0.88f); Color val2 = default(Color); ((Color)(ref val2))..ctor(0.93f, 0.78f, 0.45f); Color frame = default(Color); ((Color)(ref frame))..ctor(0.62f, 0.48f, 0.26f); val.window = new GUIStyle(val.window); SetAll(val.window, Tex(new Color(0.09f, 0.08f, 0.07f, 0.97f), frame), val2); val.window.border = new RectOffset(3, 3, 3, 3); val.window.padding = new RectOffset(14, 14, 38, 14); val.window.contentOffset = new Vector2(0f, -30f); val.window.fontSize = 20; val.window.fontStyle = (FontStyle)1; val.window.alignment = (TextAnchor)1; val.label = new GUIStyle(val.label) { fontSize = 16 }; SetText(val.label, color); val.button = new GUIStyle(val.button) { fontSize = 15, padding = new RectOffset(8, 8, 5, 5), border = new RectOffset(2, 2, 2, 2) }; Texture2D background = Tex(new Color(0.22f, 0.19f, 0.15f, 1f), frame); SetAll(val.button, background, color); val.button.hover.background = Tex(new Color(0.32f, 0.27f, 0.2f, 1f), val2); val.button.active.background = Tex(new Color(0.15f, 0.13f, 0.1f, 1f), val2); Texture2D background2 = Tex(new Color(0.5f, 0.37f, 0.16f, 1f), val2); val.button.onNormal.background = background2; val.button.onHover.background = background2; val.button.onActive.background = background2; val.textField = new GUIStyle(val.textField) { fontSize = 16, padding = new RectOffset(6, 6, 5, 5), border = new RectOffset(2, 2, 2, 2) }; SetAll(val.textField, Tex(new Color(0.03f, 0.03f, 0.03f, 1f), frame), Color.white); val.textField.focused.background = Tex(new Color(0.03f, 0.03f, 0.03f, 1f), val2); val.textField.onFocused.background = val.textField.focused.background; val.toggle = new GUIStyle(val.toggle) { fontSize = 15 }; SetText(val.toggle, color); s_skin = val; return val; } private static void SetText(GUIStyle style, Color color) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) style.normal.textColor = color; style.hover.textColor = color; style.active.textColor = color; style.focused.textColor = color; style.onNormal.textColor = color; style.onHover.textColor = color; style.onActive.textColor = color; style.onFocused.textColor = color; } private static void SetAll(GUIStyle style, Texture2D background, Color color) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) style.normal.background = background; style.hover.background = background; style.active.background = background; style.focused.background = background; style.onNormal.background = background; style.onHover.background = background; style.onActive.background = background; style.onFocused.background = background; SetText(style, color); } private static Texture2D Tex(Color fill, Color frame) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Expected O, but got Unknown //IL_0049: 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_0046: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(8, 8, (TextureFormat)4, false); ((Object)val).hideFlags = (HideFlags)61; ((Texture)val).filterMode = (FilterMode)0; ((Texture)val).wrapMode = (TextureWrapMode)1; Color[] array = (Color[])(object)new Color[64]; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { array[i * 8 + j] = ((j < 2 || i < 2 || j >= 6 || i >= 6) ? frame : fill); } } val.SetPixels(array); val.Apply(); return val; } }