Please disclose if your mod was created primarily 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 ValheimClientLogger v1.0.2
plugins/ValheimClientLogger.dll
Decompiled 4 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using ValheimClientLogger.Utils; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("ValheimClientLogger")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Valheim Client Logger")] [assembly: AssemblyTitle("ValheimClientLogger")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 ValheimClientLogger { [BepInPlugin("com.paim.valheimlogger.client", "Valheim Client Logger", "1.0.0")] public class ValheimClientLogger : BaseUnityPlugin { public const string PluginGUID = "com.paim.valheimlogger.client"; public const string PluginName = "Valheim Client Logger"; public const string PluginVersion = "1.0.0"; public const string ServerPluginGUID = "com.paim.valheimlogger"; private readonly Harmony _harmony = new Harmony("com.paim.valheimlogger.client"); public static ConfigEntry<bool> EnableDebugLogs; public static ConfigEntry<string> ServerName; public static ManualLogSource StaticLogger { get; private set; } private void Awake() { StaticLogger = ((BaseUnityPlugin)this).Logger; LoadConfiguration(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Valheim Client Logger v1.0.0 is loading..."); try { _harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"All Harmony patches applied successfully"); IEnumerable<MethodBase> patchedMethods = _harmony.GetPatchedMethods(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"=== PATCHED METHODS ==="); foreach (MethodBase item in patchedMethods) { ((BaseUnityPlugin)this).Logger.LogInfo((object)(" Patched: " + item.DeclaringType?.Name + "." + item.Name)); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"=== END PATCHED METHODS ==="); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Failed to apply Harmony patches: " + ex.Message + "\n" + ex.StackTrace)); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Valheim Client Logger v1.0.0 loaded successfully!"); } private void LoadConfiguration() { ServerName = ((BaseUnityPlugin)this).Config.Bind<string>("Server", "Name", "Tios Doteiros", "Nome do servidor que aparecerá nos eventos enviados"); EnableDebugLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableDebugLogs", true, "Habilita logs de debug detalhados (útil para troubleshooting)"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Configuration loaded:"); ((BaseUnityPlugin)this).Logger.LogInfo((object)(" Server Name: " + ServerName.Value)); ((BaseUnityPlugin)this).Logger.LogInfo((object)$" Debug Logs: {EnableDebugLogs.Value}"); } public static void SendEventToServer(string eventType, Dictionary<string, object> eventData) { //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown try { if (ZRoutedRpc.instance == null) { ManualLogSource staticLogger = StaticLogger; if (staticLogger != null) { staticLogger.LogWarning((object)"ZRoutedRpc not ready, cannot send event"); } return; } if ((Object)(object)ZNet.instance == (Object)null) { ManualLogSource staticLogger2 = StaticLogger; if (staticLogger2 != null) { staticLogger2.LogWarning((object)"ZNet not ready, skipping event send"); } return; } if (ZNet.instance.IsServer() && !ZNet.instance.IsDedicated()) { ManualLogSource staticLogger3 = StaticLogger; if (staticLogger3 != null) { staticLogger3.LogDebug((object)"Running as local host, skipping event send to avoid loop"); } return; } string text = JsonHelper.Serialize(eventData); if (EnableDebugLogs.Value) { ManualLogSource staticLogger4 = StaticLogger; if (staticLogger4 != null) { staticLogger4.LogDebug((object)("[CLIENT] Sending event to server: " + eventType)); } ManualLogSource staticLogger5 = StaticLogger; if (staticLogger5 != null) { staticLogger5.LogDebug((object)("[CLIENT] Event data: " + text)); } } ZPackage val = new ZPackage(); val.Write(eventType); val.Write(text); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "com.paim.valheimlogger.LogEvent", new object[1] { val }); ManualLogSource staticLogger6 = StaticLogger; if (staticLogger6 != null) { staticLogger6.LogInfo((object)("[CLIENT] Event sent to server: " + eventType)); } } catch (Exception ex) { ManualLogSource staticLogger7 = StaticLogger; if (staticLogger7 != null) { staticLogger7.LogError((object)("Error sending event to server: " + ex.Message + "\n" + ex.StackTrace)); } } } private void OnDestroy() { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Valheim Client Logger is shutting down..."); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Valheim Client Logger shutdown complete"); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "ValheimClientLogger"; public const string PLUGIN_NAME = "Valheim Client Logger"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace ValheimClientLogger.Utils { public static class JsonHelper { public static string Serialize(Dictionary<string, object> dict) { if (dict == null) { return "null"; } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("{"); bool flag = true; foreach (KeyValuePair<string, object> item in dict) { if (!flag) { stringBuilder.Append(","); } stringBuilder.Append("\""); stringBuilder.Append(EscapeString(item.Key)); stringBuilder.Append("\":"); stringBuilder.Append(SerializeValue(item.Value)); flag = false; } stringBuilder.Append("}"); return stringBuilder.ToString(); } private static string SerializeValue(object value) { if (value == null) { return "null"; } if (value is string str) { return "\"" + EscapeString(str) + "\""; } if (value is bool) { if (!(bool)value) { return "false"; } return "true"; } if (value is int || value is long || value is float || value is double) { return value.ToString().Replace(",", "."); } if (value is Dictionary<string, object> dict) { return Serialize(dict); } return "\"" + EscapeString(value.ToString()) + "\""; } private static string EscapeString(string str) { if (string.IsNullOrEmpty(str)) { return ""; } return str.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n") .Replace("\r", "\\r") .Replace("\t", "\\t"); } } } namespace ValheimClientLogger.Patches { [HarmonyPatch(typeof(Character), "OnDeath")] public static class Patch_Character_OnDeath { [HarmonyPostfix] public static void Postfix(Character __instance) { //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__instance == (Object)null || __instance.IsPlayer()) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } object? obj = typeof(Character).GetField("m_lastHit", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance); HitData val = (HitData)((obj is HitData) ? obj : null); if (val == null) { return; } Character attacker = val.GetAttacker(); if ((Object)(object)attacker == (Object)null || !attacker.IsPlayer()) { return; } Player val2 = (Player)(object)((attacker is Player) ? attacker : null); if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 != (Object)(object)localPlayer)) { string text = ((Object)((Component)__instance).gameObject).name.Replace("(Clone)", "").Trim(); string hoverName = __instance.GetHoverName(); ManualLogSource staticLogger = ValheimClientLogger.StaticLogger; if (staticLogger != null) { staticLogger.LogInfo((object)("[CLIENT] Mob killed: " + text + " (" + hoverName + ") by " + val2.GetPlayerName())); } Dictionary<string, object> eventData = new Dictionary<string, object> { ["timestamp"] = DateTime.UtcNow.ToString("o"), ["serverName"] = ValheimClientLogger.ServerName.Value, ["eventType"] = "mob_kill", ["playerName"] = val2.GetPlayerName(), ["playerID"] = val2.GetPlayerID().ToString(), ["details"] = new Dictionary<string, object> { ["mobName"] = text, ["mobDisplayName"] = hoverName, ["mobLevel"] = __instance.GetLevel(), ["mobMaxHealth"] = __instance.GetMaxHealth(), ["position"] = new Dictionary<string, object> { ["x"] = ((Component)__instance).transform.position.x, ["y"] = ((Component)__instance).transform.position.y, ["z"] = ((Component)__instance).transform.position.z }, ["isBoss"] = __instance.IsBoss() } }; ValheimClientLogger.SendEventToServer("mob_kill", eventData); } } catch (Exception ex) { ManualLogSource staticLogger2 = ValheimClientLogger.StaticLogger; if (staticLogger2 != null) { staticLogger2.LogError((object)("Error in Patch_Character_OnDeath: " + ex.Message + "\n" + ex.StackTrace)); } } } } [HarmonyPatch(typeof(Humanoid), "Pickup")] public static class Patch_Humanoid_Pickup { [HarmonyPostfix] public static void Postfix(Humanoid __instance, GameObject go, bool __result) { } } [HarmonyPatch(typeof(Player), "OnSpawned")] public static class Patch_Player_Login { public static bool _hasLogged; [HarmonyPostfix] public static void Postfix(Player __instance) { //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) try { if (_hasLogged) { return; } if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { _hasLogged = true; ManualLogSource staticLogger = ValheimClientLogger.StaticLogger; if (staticLogger != null) { staticLogger.LogInfo((object)("[CLIENT] Player logged in: " + __instance.GetPlayerName())); } Dictionary<string, object> eventData = new Dictionary<string, object> { ["timestamp"] = DateTime.UtcNow.ToString("o"), ["serverName"] = ValheimClientLogger.ServerName.Value, ["eventType"] = "player_login", ["playerName"] = __instance.GetPlayerName(), ["playerID"] = __instance.GetPlayerID().ToString(), ["details"] = new Dictionary<string, object> { ["position"] = new Dictionary<string, object> { ["x"] = ((Component)__instance).transform.position.x, ["y"] = ((Component)__instance).transform.position.y, ["z"] = ((Component)__instance).transform.position.z } } }; ValheimClientLogger.SendEventToServer("player_login", eventData); } } catch (Exception ex) { ManualLogSource staticLogger2 = ValheimClientLogger.StaticLogger; if (staticLogger2 != null) { staticLogger2.LogError((object)("Error in Patch_Player_Login: " + ex.Message + "\n" + ex.StackTrace)); } } } } [HarmonyPatch(typeof(Game), "Logout")] public static class Patch_Player_Logout { [HarmonyPrefix] public static void Prefix() { //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) try { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { ManualLogSource staticLogger = ValheimClientLogger.StaticLogger; if (staticLogger != null) { staticLogger.LogInfo((object)("[CLIENT] Player logging out: " + localPlayer.GetPlayerName())); } Dictionary<string, object> eventData = new Dictionary<string, object> { ["timestamp"] = DateTime.UtcNow.ToString("o"), ["serverName"] = ValheimClientLogger.ServerName.Value, ["eventType"] = "player_logout", ["playerName"] = localPlayer.GetPlayerName(), ["playerID"] = localPlayer.GetPlayerID().ToString(), ["details"] = new Dictionary<string, object> { ["position"] = new Dictionary<string, object> { ["x"] = ((Component)localPlayer).transform.position.x, ["y"] = ((Component)localPlayer).transform.position.y, ["z"] = ((Component)localPlayer).transform.position.z }, ["playTime"] = Time.time } }; ValheimClientLogger.SendEventToServer("player_logout", eventData); Patch_Player_Login._hasLogged = false; Patch_Skills_RaiseSkill.ResetTracking(); Thread.Sleep(500); } } catch (Exception ex) { ManualLogSource staticLogger2 = ValheimClientLogger.StaticLogger; if (staticLogger2 != null) { staticLogger2.LogError((object)("Error in Patch_Player_Logout: " + ex.Message + "\n" + ex.StackTrace)); } } } } [HarmonyPatch(typeof(Skills), "RaiseSkill")] public static class Patch_Skills_RaiseSkill { private static Dictionary<SkillType, int> _lastLoggedLevel = new Dictionary<SkillType, int>(); public static void ResetTracking() { _lastLoggedLevel.Clear(); } [HarmonyPostfix] public static void Postfix(Skills __instance, SkillType skillType, float factor) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: 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) try { object? obj = typeof(Skills).GetField("m_player", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance); Player val = (Player)((obj is Player) ? obj : null); if ((Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)Player.m_localPlayer || !(typeof(Skills).GetField("m_skillData", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance) is Dictionary<SkillType, Skill> dictionary) || !dictionary.ContainsKey(skillType)) { return; } int num = (int)dictionary[skillType].m_level; if (!_lastLoggedLevel.ContainsKey(skillType) || _lastLoggedLevel[skillType] < num) { int num2 = (_lastLoggedLevel.ContainsKey(skillType) ? _lastLoggedLevel[skillType] : (num - 1)); _lastLoggedLevel[skillType] = num; ManualLogSource staticLogger = ValheimClientLogger.StaticLogger; if (staticLogger != null) { staticLogger.LogInfo((object)$"[CLIENT] Skill level up: {skillType} reached level {num} (was {num2})"); } Dictionary<string, object> eventData = new Dictionary<string, object> { ["timestamp"] = DateTime.UtcNow.ToString("o"), ["serverName"] = ValheimClientLogger.ServerName.Value, ["eventType"] = "skill_level_up", ["playerName"] = val.GetPlayerName(), ["playerID"] = val.GetPlayerID().ToString(), ["details"] = new Dictionary<string, object> { ["skillType"] = ((object)(SkillType)(ref skillType)).ToString(), ["newLevel"] = num, ["previousLevel"] = num2 } }; ValheimClientLogger.SendEventToServer("skill_raise", eventData); } } catch (Exception ex) { ManualLogSource staticLogger2 = ValheimClientLogger.StaticLogger; if (staticLogger2 != null) { staticLogger2.LogError((object)("Error in Patch_Skills_RaiseSkill: " + ex.Message + "\n" + ex.StackTrace)); } } } } }