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 Player Activity v1.2.1
PlayerActivity.dll
Decompiled 7 months agousing System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; 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.Threading; using BepInEx; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Player Activity")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Player Activity")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("1de6cf76-b53d-47ab-b3b1-de02fa27f1a7")] [assembly: AssemblyFileVersion("1.2.1")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.1.0")] [module: UnverifiableCode] internal class Log { private static Log _instance; private ManualLogSource _source; public static Log CreateInstance(ManualLogSource source) { _instance = new Log { _source = source }; return _instance; } private Log() { } public static void Info(object msg) { _instance._source.LogInfo((object)FormatMessage(msg)); } public static void Message(object msg) { _instance._source.LogMessage((object)FormatMessage(msg)); } public static void Debug(object msg) { _instance._source.LogDebug((object)FormatMessage(msg)); } public static void Warning(object msg) { _instance._source.LogWarning((object)FormatMessage(msg)); } public static void Error(object msg) { _instance._source.LogError((object)FormatMessage(msg)); } public static void Fatal(object msg) { _instance._source.LogFatal((object)FormatMessage(msg)); } private static string FormatMessage(object msg) { return $"[{DateTime.UtcNow}] {msg}"; } } internal static class ThreadingUtil { private class DisposableThread : IDisposable { private Thread _thread; internal DisposableThread(Thread thread) { _thread = thread; } public void Dispose() { _thread.Abort(); } } private class MainThreadDispatcher : MonoBehaviour { private static MainThreadDispatcher _instance; private ConcurrentQueue<Action> _queue = new ConcurrentQueue<Action>(); private ConcurrentQueue<IEnumerator> _coroutinesQueue = new ConcurrentQueue<IEnumerator>(); public static MainThreadDispatcher GetInstante() { //IL_0025: 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_0030: Expected O, but got Unknown if ((Object)(object)_instance == (Object)null) { GameObject val = new GameObject("MainThreadDispatcher", new Type[1] { typeof(MainThreadDispatcher) }); Object.DontDestroyOnLoad((Object)val); _instance = val.GetComponent<MainThreadDispatcher>(); } return _instance; } public void AddAction(Action action) { _queue.Enqueue(action); } public void AddCoroutine(IEnumerator coroutine) { _coroutinesQueue.Enqueue(coroutine); } private void Update() { Action result; while (_queue.Count > 0 && _queue.TryDequeue(out result)) { result?.Invoke(); } IEnumerator result2; while (_coroutinesQueue.Count > 0 && _coroutinesQueue.TryDequeue(out result2)) { ((MonoBehaviour)this).StartCoroutine(result2); } } } [CompilerGenerated] private sealed class <DelayedActionCoroutine>d__6 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public float delay; public Action action; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayedActionCoroutine>d__6(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(delay); <>1__state = 1; return true; case 1: <>1__state = -1; action?.Invoke(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } internal static IDisposable RunPeriodical(Action action, int periodMilliseconds) { return new Timer(delegate { action?.Invoke(); }, null, 0, periodMilliseconds); } internal static IDisposable RunPeriodicalInSingleThread(Action action, int periodMilliseconds) { Thread thread = new Thread((ParameterizedThreadStart)delegate { while (true) { action?.Invoke(); Thread.Sleep(periodMilliseconds); } }); thread.Start(); return new DisposableThread(thread); } internal static void RunInMainThread(Action action) { MainThreadDispatcher.GetInstante().AddAction(action); } internal static void RunCoroutine(IEnumerator coroutine) { MainThreadDispatcher.GetInstante().AddCoroutine(coroutine); } internal static void RunDelayed(float delay, Action action) { MainThreadDispatcher.GetInstante().AddCoroutine(DelayedActionCoroutine(delay, action)); } internal static IDisposable RunThread(Action action) { Thread thread = new Thread(action.Invoke); thread.Start(); return new DisposableThread(thread); } [IteratorStateMachine(typeof(<DelayedActionCoroutine>d__6))] internal static IEnumerator DelayedActionCoroutine(float delay, Action action) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DelayedActionCoroutine>d__6(0) { delay = delay, action = action }; } } namespace PlayerActivity { public static class ActivityEvents { public const string Interact = "Interact"; public const string Dodge = "Dodge"; public const string Spawned = "Spawned"; public const string Place = "Place"; public const string Teleport = "Teleport"; public const string Craft = "Craft"; public const string MoveAll = "MoveAll"; public const string Move = "Move"; public const string StackAll = "StackAll"; public const string RepairItem = "Repair item"; public const string RepairBuilding = "Repair building"; public const string Command = "Command"; public const string CommandRemote = "Command remote"; public const string Remove = "Remove"; public const string Grave = "Grave"; public const string Damaged = "Damaged"; public const string Dead = "Dead"; public const string Equip = "Equip"; public const string Unequip = "Unequip"; public const string Drop = "Drop"; public const string Pickup = "Pickup"; public const string Damage = "Damage"; public const string Consume = "Consume"; public const string Use = "Use"; public const string Text = "Text"; public const string Ping = "Ping"; public const string Inventory = "Inventory"; public const string TrinketActivated = "TrinketActivated"; } public static class ActivityLog { public static void AddLogWithPosition(string eventName, string parameters, Component component) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) AddLogWithPosition(eventName, parameters, (Vector3)(((Object)(object)component != (Object)null) ? component.transform.position : default(Vector3))); } public static void AddLogWithPosition(string eventName, string parameters, GameObject gameObject) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) AddLogWithPosition(eventName, parameters, (Vector3)(((Object)(object)gameObject != (Object)null) ? gameObject.transform.position : default(Vector3))); } public static void AddLogWithPlayerPosition(string eventName, string parameters) { AddLogWithPosition(eventName, parameters, (Component)(object)Player.m_localPlayer); } public static void AddLogWithPosition(string eventName, string parameters, Vector3 position) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) LogData logData = default(LogData); logData.eventName = eventName; logData.time = ZNet.instance.GetTimeSeconds(); logData.parameters = parameters; logData.position = position; LogData logData2 = logData; Log.Debug(logData2); ZRoutedRpc.instance.InvokeRoutedRPC("RPC_PlayerActivityLog", new object[1] { logData2 }); } } internal class ActivityStorageService : MonoBehaviour { public const string LogRpc = "RPC_PlayerActivityLog"; private IDisposable _writerThread; private ConcurrentDictionary<string, ConcurrentQueue<string>> _logsToWrite = new ConcurrentDictionary<string, ConcurrentQueue<string>>(); internal static ActivityStorageService Instance { get; private set; } private void Start() { Instance = this; ZRoutedRpc.instance.Register<LogData>("RPC_PlayerActivityLog", (Action<long, LogData>)OnPlayerLogsReceived); _writerThread = ThreadingUtil.RunPeriodicalInSingleThread(WriteQueuedLogsToDisk, 500); Log.Info("Storage initialized"); } private void OnDestroy() { _writerThread?.Dispose(); } private void OnPlayerLogsReceived(long uid, LogData logData) { ZNetPeer peer = ZNet.instance.GetPeer(uid); string steamId = ((peer != null) ? peer.m_socket.GetHostName() : null) ?? "local"; AppendPlayerLogs(steamId, logData); } internal void AppendPlayerLogs(string steamId, LogData logData) { string key = Path.Combine(Utils.GetSaveDataPath((FileSource)1), "Player Activity", GetCurrentDateFolderPath(), steamId + ".log"); if (!_logsToWrite.TryGetValue(key, out var value)) { _logsToWrite.AddOrUpdate(key, new ConcurrentQueue<string>(), (string path, ConcurrentQueue<string> q2) => _logsToWrite[path]); value = _logsToWrite[key]; } string item = FormatLogToDisk(logData); value.Enqueue(item); } private void WriteQueuedLogsToDisk() { foreach (KeyValuePair<string, ConcurrentQueue<string>> item in _logsToWrite) { if (item.Value.IsEmpty) { continue; } string directoryName = Path.GetDirectoryName(item.Key); if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } using StreamWriter streamWriter = File.AppendText(item.Key); string result; while (item.Value.TryDequeue(out result)) { streamWriter.WriteLine(result); } } } private string FormatLogToDisk(LogData logData) { return string.Format("[{0}] {1}", CalculateRelativeDate(ZNet.instance.GetTimeSeconds(), logData.time).ToString("G", CultureInfo.InvariantCulture), logData); } private static DateTime CalculateRelativeDate(double currentWorldTime, double lastWorldTime) { DateTime utcNow = DateTime.UtcNow; double value = currentWorldTime - lastWorldTime; return utcNow.Subtract(TimeSpan.FromSeconds(value)); } private static string GetCurrentDateFolderPath() { return DateTime.UtcNow.ToString("yyyy_MM_dd", CultureInfo.InvariantCulture); } } public static class ItemDataUtil { private static readonly StringBuilder _builder = new StringBuilder(); private static readonly StringBuilder _itemDataBuilder = new StringBuilder(); public static string ToPresentableString(this ItemData item) { return item.ToPresentableString(item.m_stack); } public static string ToPresentableString(this ItemData item, int count) { GameObject dropPrefab = item.m_dropPrefab; string arg = ((dropPrefab != null) ? ((Object)dropPrefab).name : null) ?? item.m_shared.m_name; _itemDataBuilder.Clear(); _itemDataBuilder.AppendFormat("{0} x{1} quality:{2}", arg, count, item.m_quality); if (item.m_crafterID != 0L) { _itemDataBuilder.AppendFormat(" crafter:{0}({1})", item.m_crafterName, item.m_crafterID); } if (item.m_customData.Count > 0) { _itemDataBuilder.AppendFormat(" data:{0}", ToPresentableFormat(item.m_customData)); } return _itemDataBuilder.ToString(); } private static string ToPresentableFormat(Dictionary<string, string> customData) { _builder.Clear(); bool flag = false; foreach (KeyValuePair<string, string> customDatum in customData) { if (flag) { _builder.Append(", "); } _builder.AppendFormat("[{0}]:[{1}]", customDatum.Key, customDatum.Value); flag = true; } return _builder.ToString(); } } public struct LogData : ISerializableParameter { public double time; public Vector3 position; public string eventName; public string parameters; public void Deserialize(ref ZPackage pkg) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) time = pkg.ReadDouble(); position = pkg.ReadVector3(); eventName = pkg.ReadString(); parameters = pkg.ReadString(); } public void Serialize(ref ZPackage pkg) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) pkg.Write(time); pkg.Write(position); pkg.Write(eventName); pkg.Write(parameters); } public override string ToString() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return $"{position} {eventName} {parameters}"; } } internal class PlayerLogger : MonoBehaviour { private Player _player; private void Start() { if (!ZNet.instance.IsDedicated()) { _player = ((Component)this).GetComponent<Player>(); ((MonoBehaviour)this).InvokeRepeating("AddPeriodicallyLogs", 60f, 60f); ((MonoBehaviour)this).InvokeRepeating("AddInventoryLog", 1f, 600f); Log.Info("Player logger created"); } } private void AddPeriodicallyLogs() { if (!((Character)_player).IsDead()) { float num = default(float); float num2 = default(float); int num3 = default(int); float num4 = default(float); float num5 = default(float); ZNet.instance.GetNetStats(ref num, ref num2, ref num3, ref num4, ref num5); ActivityLog.AddLogWithPosition("Ping", num3.ToString(), (Component)(object)_player); } } private void AddInventoryLog() { if (!((Character)_player).IsDead()) { ActivityLog.AddLogWithPosition("Inventory", "\n" + ActivityLoggerUtil.GetContainerData(((Humanoid)_player).GetInventory()), (Component)(object)_player); } } } public static class ActivityLoggerUtil { private static StringBuilder _builder = new StringBuilder(); public static bool CheckIsLocalPlayer(Character character) { return (Object)(object)character == (Object)(object)Player.m_localPlayer; } public static string GetContainerData(Container container) { return GetContainerData(container.GetInventory()); } public static string GetContainerData(Inventory inventory) { return GetContainerData((IEnumerable<ItemData>)inventory.GetAllItems()); } public static string GetContainerData(IEnumerable<ItemData> itemsList) { _builder.Clear(); foreach (ItemData items in itemsList) { _builder.AppendLine(items.ToPresentableString()); } return _builder.ToString().TrimEnd(Array.Empty<char>()); } public static string GetDamageLog(HitData hit) { //IL_000c: 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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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_0056: 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) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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) //IL_00bc: 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) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_0100: 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_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0166: 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_0178: Unknown result type (might be due to invalid IL or missing references) _builder.Clear(); DamageTypes damage = hit.m_damage; if (damage.m_damage > 0f) { AppendDamageToBuilder("damage", damage.m_damage, _builder); } if (damage.m_blunt > 0f) { AppendDamageToBuilder("blunt", damage.m_blunt, _builder); } if (damage.m_slash > 0f) { AppendDamageToBuilder("slash", damage.m_slash, _builder); } if (damage.m_pierce > 0f) { AppendDamageToBuilder("pierce", damage.m_pierce, _builder); } if (damage.m_fire > 0f) { AppendDamageToBuilder("fire", damage.m_fire, _builder); } if (damage.m_frost > 0f) { AppendDamageToBuilder("frost", damage.m_frost, _builder); } if (damage.m_lightning > 0f) { AppendDamageToBuilder("light", damage.m_lightning, _builder); } if (damage.m_poison > 0f) { AppendDamageToBuilder("poison", damage.m_poison, _builder); } if (damage.m_spirit > 0f) { AppendDamageToBuilder("spirit", damage.m_spirit, _builder); } if (damage.m_chop > 0f) { AppendDamageToBuilder("chop", damage.m_chop, _builder); } if (damage.m_pickaxe > 0f) { AppendDamageToBuilder("pickaxe", damage.m_pickaxe, _builder); } AppendDamageToBuilder("total", ((DamageTypes)(ref damage)).GetTotalDamage(), _builder); return _builder.ToString(); } private static void AppendDamageToBuilder(string name, float damage, StringBuilder builder) { builder.AppendFormat("{0}:{1:0.0} ", name, damage); } public static string FormatParameters(string parameters, Vector3 position) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return $"{position.ToPresentableString()} {parameters}"; } public static string GetPlayerData(this Player player) { if ((Object)(object)player == (Object)null) { return string.Empty; } return $"{player.GetPlayerName()}({player.GetPlayerID()})"; } public static string ToPresentableString(this Vector3 position) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) return $"({position.x:0.0} {position.y:0.0} {position.z:0.0})"; } } [BepInPlugin("org.tristan.playeractivity", "Player Activity", "1.2.1")] internal class Plugin : BaseUnityPlugin { [HarmonyPatch] private class InitializationPatch { [HarmonyPostfix] [HarmonyPatch(typeof(Game), "Start")] private static void Game_Start(Game __instance) { if (ZNet.instance.IsServer()) { ((Component)__instance).gameObject.AddComponent<ActivityStorageService>(); } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "SetLocalPlayer")] private static void Player_SetLocalPlayer(Player __instance) { ((Component)__instance).gameObject.AddComponent<PlayerLogger>(); } } private const string Guid = "org.tristan.playeractivity"; public const string Name = "Player Activity"; public const string Version = "1.2.1"; private void Awake() { Log.CreateInstance(((BaseUnityPlugin)this).Logger); Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "org.tristan.playeractivity"); } } } namespace PlayerActivity.ActivityPatches { [HarmonyPatch] internal class CraftPatches { private static bool _isCrafting; [HarmonyPriority(int.MinValue)] [HarmonyPrefix] [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] private static void InventoryGui_DoCrafting_Prefix(InventoryGui __instance) { _isCrafting = true; } [HarmonyPriority(int.MaxValue)] [HarmonyPostfix] [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] private static void InventoryGui_DoCrafting_Postfix(InventoryGui __instance) { _isCrafting = false; } [HarmonyPriority(int.MaxValue)] [HarmonyFinalizer] [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(string), typeof(int), typeof(int), typeof(int), typeof(long), typeof(string), typeof(Vector2i), typeof(bool) })] private static void Inventory_AddItem_Postfix(ref ItemData __result) { if (__result != null && _isCrafting) { ActivityLog.AddLogWithPlayerPosition("Craft", __result.ToPresentableString()); } } } [HarmonyPatch] internal class CreateTombStonePatch { [HarmonyPostfix] [HarmonyPatch(typeof(TombStone), "Setup")] private static void TombStone_Setup(TombStone __instance) { Player localPlayer = Player.m_localPlayer; Container component = ((Component)__instance).GetComponent<Container>(); ActivityLog.AddLogWithPosition("Grave", "items:\n" + ActivityLoggerUtil.GetContainerData(component.GetInventory()) + "\nplayer:\n" + ActivityLoggerUtil.GetContainerData(((Humanoid)localPlayer).GetInventory()), (Component)(object)__instance); } } [HarmonyPatch] internal class ServerPatches { [HarmonyPostfix] [HarmonyPatch(typeof(ZNet), "SendPeerInfo")] private static void ZNet_SendPeerInfo(ZNet __instance, ZRpc rpc) { //IL_001b: 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) if (__instance.IsServer()) { AppendServerLog(rpc.m_socket.GetHostName(), "Connected"); } } [HarmonyPrefix] [HarmonyPatch(typeof(ZNet), "Disconnect")] private static void ZNet_Disconnect(ZNet __instance, ZNetPeer peer) { //IL_001b: 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_0028: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (__instance.IsServer()) { string hostName = peer.m_rpc.m_socket.GetHostName(); if (peer.m_characterID != default(ZDOID)) { AppendServerLog(hostName, "Disconnected", peer.GetRefPos()); } else { AppendServerLog(hostName, "Disconnected"); } } } private static void AppendServerLog(string steamId, string eventName, Vector3 position = default(Vector3)) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) LogData logData = default(LogData); logData.eventName = eventName; logData.position = position; logData.time = ZNet.instance.GetTimeSeconds(); LogData logData2 = logData; ActivityStorageService.Instance.AppendPlayerLogs(steamId, logData2); } } [HarmonyPatch(typeof(Player))] internal class DodgePatches { private static bool _inDodge; [HarmonyPrefix] [HarmonyPatch("UpdateDodge")] private static void Player_UpdateDodge_Prefix(Player __instance) { if (ActivityLoggerUtil.CheckIsLocalPlayer((Character)(object)__instance)) { _inDodge = ((Character)__instance).InDodge(); } } [HarmonyPostfix] [HarmonyPatch("UpdateDodge")] private static void Player_UpdateDodge_Postfix(Player __instance) { if (ActivityLoggerUtil.CheckIsLocalPlayer((Character)(object)__instance)) { if (!_inDodge && ((Character)__instance).InDodge()) { ActivityLog.AddLogWithPlayerPosition("Dodge", ""); } _inDodge = ((Character)__instance).InDodge(); } } } [HarmonyPatch] internal class PickupPatches { [HarmonyPostfix] [HarmonyPatch(typeof(Humanoid), "Pickup")] private static void Humanoid_Pickup(Humanoid __instance, GameObject go, ref bool __result) { ItemDrop val = default(ItemDrop); if (ActivityLoggerUtil.CheckIsLocalPlayer((Character)(object)__instance) && __result && go.TryGetComponent<ItemDrop>(ref val)) { ActivityLog.AddLogWithPosition("Pickup", val.m_itemData.ToPresentableString(), (Component)(object)val); } } } [HarmonyPatch] internal class RepairBuildingPatches { [HarmonyPatch(typeof(Player), "Repair")] private class PlayerRepairPatches { private static void Prefix() { _repairing = true; } private static void Postfix() { _repairing = false; } } private static bool _repairing; [HarmonyPostfix] [HarmonyPatch(typeof(WearNTear), "Repair")] private static void InventoryGui_CanRepair(WearNTear __instance, ref bool __result) { if (_repairing && __result) { ActivityLog.AddLogWithPosition("Repair building", Utils.GetPrefabName(((Component)__instance).gameObject), (Component)(object)__instance); } } } [HarmonyPatch] internal class RepairItemPatches { [HarmonyPatch(typeof(InventoryGui), "RepairOneItem")] private class RepairOneItemPatches { private static void Prefix() { _repairing = true; } private static void Postfix() { _repairing = false; } } private static bool _repairing; [HarmonyPostfix] [HarmonyPatch(typeof(InventoryGui), "CanRepair")] private static void InventoryGui_CanRepair(ItemData item, ref bool __result) { if (__result && _repairing) { ActivityLog.AddLogWithPlayerPosition("Repair item", item.ToPresentableString()); } } } [HarmonyPatch] internal class TerminalPatches { [HarmonyPrefix] [HarmonyPatch(typeof(ConsoleCommand), "RunAction")] private static void ConsoleCommand_RunAction(ConsoleCommand __instance, ConsoleEventArgs args) { if (!ZNet.instance.IsDedicated()) { ActivityLog.AddLogWithPlayerPosition("Command", args.FullLine); } } [HarmonyPrefix] [HarmonyPatch(typeof(ZNet), "RemoteCommand")] private static void ZNet_RemoteCommand(string command) { if (!ZNet.instance.IsDedicated()) { ActivityLog.AddLogWithPlayerPosition("Command remote", command); } } } [HarmonyPatch(typeof(Player), "AddAdrenaline")] internal class TrinketActivationPatch { private static bool _hasEffectBefore; public static void Prefix(Player __instance) { ItemData activeTrinket = GetActiveTrinket(__instance); _hasEffectBefore = activeTrinket != null && HasStatusEffect(__instance, activeTrinket); } public static void Postfix(Player __instance) { if (!_hasEffectBefore) { ItemData activeTrinket = GetActiveTrinket(__instance); bool flag = activeTrinket != null && HasStatusEffect(__instance, activeTrinket); if (!_hasEffectBefore && flag) { ActivityLog.AddLogWithPosition("TrinketActivated", activeTrinket.ToPresentableString(), (Component)(object)__instance); } } } private static ItemData GetActiveTrinket(Player player) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 foreach (ItemData allItem in ((Humanoid)player).GetInventory().GetAllItems()) { if (allItem != null && (int)allItem.m_shared.m_itemType == 24 && (Object)(object)allItem.m_shared.m_fullAdrenalineSE != (Object)null && allItem.m_shared.m_maxAdrenaline > 0f) { return allItem; } } return null; } private static bool HasStatusEffect(Player player, ItemData trinket) { return ((Character)player).GetSEMan().HaveStatusEffect(trinket.m_shared.m_fullAdrenalineSE.NameHash()); } } [HarmonyPatch(typeof(Character))] internal class DamagePatches { [HarmonyFinalizer] [HarmonyPatch("ApplyDamage")] private static void Character_ApplyDamage(Character __instance, HitData hit) { if (ActivityLoggerUtil.CheckIsLocalPlayer(__instance)) { string text; if (!hit.HaveAttacker()) { text = "none"; } else { Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); text = ((val == null) ? Utils.GetPrefabName(((Component)hit.GetAttacker()).gameObject) : val.GetPlayerData()); } float health = __instance.GetHealth(); ActivityLog.AddLogWithPosition("Damaged", $"by:{text} health:{health:0.0} {ActivityLoggerUtil.GetDamageLog(hit)}", (Component)(object)__instance); if (!(__instance.GetHealth() > 0f)) { ActivityLog.AddLogWithPosition("Dead", "by:" + text, (Component)(object)__instance); } } } } [HarmonyPatch(typeof(Humanoid))] internal class HumanoidPatches { [HarmonyFinalizer] [HarmonyPatch("EquipItem")] private static void Humanoid_EquipItem(Humanoid __instance, ItemData item, ref bool __result) { if (item != null && __result && ActivityLoggerUtil.CheckIsLocalPlayer((Character)(object)__instance) && item.IsEquipable()) { ActivityLog.AddLogWithPosition("Equip", item.ToPresentableString(), (Component)(object)__instance); } } [HarmonyPrefix] [HarmonyPatch("UnequipItem")] private static void Humanoid_UnequipItem(Humanoid __instance, ItemData item) { if (item != null && ActivityLoggerUtil.CheckIsLocalPlayer((Character)(object)__instance) && item.IsEquipable() && item.m_equipped) { ActivityLog.AddLogWithPosition("Unequip", item.ToPresentableString(), (Component)(object)__instance); } } [HarmonyPostfix] [HarmonyPatch("DropItem")] private static void Humanoid_DropItem(Humanoid __instance, Inventory inventory, ItemData item, int amount, ref bool __result) { if (__result && ActivityLoggerUtil.CheckIsLocalPlayer((Character)(object)__instance)) { ActivityLog.AddLogWithPosition("Drop", "from:" + inventory.GetName() + " " + item.ToPresentableString(amount), (Component)(object)__instance); } } } [HarmonyPatch] internal class InventoryPatches { [HarmonyPatch] private class StackAllPatch { private static Inventory _stackFromInventory; private static readonly HashSet<ItemData> _movedItems = new HashSet<ItemData>(); [HarmonyPrefix] [HarmonyPatch(typeof(Inventory), "StackAll")] private static void Inventory_StackAll_Prefix(Inventory __instance, Inventory fromInventory) { _movedItems.Clear(); _stackFromInventory = fromInventory; } [HarmonyPostfix] [HarmonyPatch(typeof(Inventory), "StackAll")] private static void Inventory_StackAll_Postfix(Inventory __instance, Inventory fromInventory, ref int __result) { _stackFromInventory = null; if (__instance != fromInventory && __result != 0) { ActivityLog.AddLogWithPlayerPosition("StackAll", "from:" + fromInventory.GetName() + " to:" + __instance.GetName() + "\n" + ActivityLoggerUtil.GetContainerData((IEnumerable<ItemData>)_movedItems)); } } [HarmonyPostfix] [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(ItemData) })] private static void Inventory_RemoveItem(Inventory __instance, ItemData item) { if (__instance == _stackFromInventory) { _movedItems.Add(item); } } } [HarmonyPrefix] [HarmonyPatch(typeof(Inventory), "MoveAll")] private static void Inventory_MoveAll(Inventory __instance, Inventory fromInventory) { ActivityLog.AddLogWithPlayerPosition("MoveAll", "from:" + fromInventory.GetName() + " to:" + __instance.GetName() + "\n" + ActivityLoggerUtil.GetContainerData(fromInventory)); } [HarmonyPrefix] [HarmonyPatch(typeof(Inventory), "MoveItemToThis", new Type[] { typeof(Inventory), typeof(ItemData) })] private static void Inventory_MoveItemToThis(Inventory __instance, Inventory fromInventory, ItemData item) { ActivityLog.AddLogWithPlayerPosition("Move", "from:" + fromInventory.GetName() + " to:" + __instance.GetName() + " " + item.ToPresentableString()); } [HarmonyPrefix] [HarmonyPatch(typeof(Inventory), "MoveItemToThis", new Type[] { typeof(Inventory), typeof(ItemData), typeof(int), typeof(int), typeof(int) })] private static void Inventory_MoveItemToThisWithAmount(Inventory __instance, Inventory fromInventory, ItemData item, int amount) { if (__instance != fromInventory || item.m_stack != amount) { ActivityLog.AddLogWithPlayerPosition("Move", "from:" + fromInventory.GetName() + " to:" + __instance.GetName() + " " + item.ToPresentableString(amount)); } } } [HarmonyPatch] internal class PlayerDealsDamagePatches { [HarmonyPostfix] [HarmonyPatch(typeof(Character), "Damage")] private static void Character_Damage(Character __instance, HitData hit) { if (IsLocalPlayerHit(hit)) { Player val = (Player)(object)((__instance is Player) ? __instance : null); string text = ((val != null) ? val.GetPlayerData() : $"{Utils.GetPrefabName(((Component)__instance).gameObject)} lvl:{__instance.GetLevel()} tamed:{__instance.IsTamed()}"); ActivityLog.AddLogWithPosition("Damage", "target:" + text + " " + ActivityLoggerUtil.GetDamageLog(hit), (Component)(object)__instance); } } [HarmonyPostfix] [HarmonyPatch(typeof(Destructible), "Damage")] private static void Destructible_Damage(Destructible __instance, HitData hit, bool __runOriginal) { if (__runOriginal) { TryLogStructureDamage((Component)(object)__instance, hit); } } [HarmonyPostfix] [HarmonyPatch(typeof(HitArea), "Damage")] private static void HitArea_Damage(HitArea __instance, HitData hit, bool __runOriginal) { if (__runOriginal) { TryLogStructureDamage((Component)(object)__instance, hit); } } [HarmonyPostfix] [HarmonyPatch(typeof(MineRock), "Damage")] private static void MineRock_Damage(MineRock __instance, HitData hit, bool __runOriginal) { if (__runOriginal) { TryLogStructureDamage((Component)(object)__instance, hit); } } [HarmonyPostfix] [HarmonyPatch(typeof(MineRock5), "Damage")] private static void MineRock5_Damage(MineRock5 __instance, HitData hit, bool __runOriginal) { if (__runOriginal) { TryLogStructureDamage((Component)(object)__instance, hit); } } [HarmonyPostfix] [HarmonyPatch(typeof(Raven), "Damage")] private static void Raven_Damage(Raven __instance, HitData hit, bool __runOriginal) { if (__runOriginal) { TryLogStructureDamage((Component)(object)__instance, hit); } } [HarmonyPostfix] [HarmonyPatch(typeof(WearNTear), "Damage")] private static void WearNTear_Damage(WearNTear __instance, HitData hit, bool __runOriginal) { if (__runOriginal) { TryLogStructureDamage((Component)(object)__instance, hit); } } [HarmonyPostfix] [HarmonyPatch(typeof(TreeBase), "Damage")] private static void TreeBase_Damage(TreeBase __instance, HitData hit, bool __runOriginal) { if (__runOriginal) { TryLogStructureDamage((Component)(object)__instance, hit); } } [HarmonyPostfix] [HarmonyPatch(typeof(TreeLog), "Damage")] private static void TreeLog_Damage(TreeLog __instance, HitData hit, bool __runOriginal) { if (__runOriginal) { TryLogStructureDamage((Component)(object)__instance, hit); } } private static void TryLogStructureDamage(Component target, HitData hit) { if (IsLocalPlayerHit(hit)) { ActivityLog.AddLogWithPosition("Damage", "target:" + Utils.GetPrefabName(target.gameObject) + " " + ActivityLoggerUtil.GetDamageLog(hit), target); } } private static bool IsLocalPlayerHit(HitData hit) { if (hit.HaveAttacker()) { return ActivityLoggerUtil.CheckIsLocalPlayer(hit.GetAttacker()); } return false; } } [HarmonyPatch] public class PlayerInteractionPatches { [HarmonyPostfix] [HarmonyPatch(typeof(PrivateArea), "Interact")] private static void PrivateArea_Interact(PrivateArea __instance, ref bool __result, Humanoid human) { TryLogInteraction((Component)(object)__instance, __result, human, $"{__instance.GetCreatorName()} active:{__instance.IsEnabled()}"); } [HarmonyPostfix] [HarmonyPatch(typeof(WayStone), "Interact")] [HarmonyPatch(typeof(Vegvisir), "Interact")] [HarmonyPatch(typeof(Vagon), "Interact")] [HarmonyPatch(typeof(Trader), "Interact")] [HarmonyPatch(typeof(TombStone), "Interact")] [HarmonyPatch(typeof(ToggleSwitch), "Interact")] [HarmonyPatch(typeof(Teleport), "Interact")] [HarmonyPatch(typeof(Switch), "Interact")] [HarmonyPatch(typeof(Sign), "Interact")] [HarmonyPatch(typeof(ShipControlls), "Interact")] [HarmonyPatch(typeof(RuneStone), "Interact")] [HarmonyPatch(typeof(Raven), "Interact")] [HarmonyPatch(typeof(PickableItem), "Interact")] [HarmonyPatch(typeof(Pickable), "Interact")] [HarmonyPatch(typeof(Ladder), "Interact")] [HarmonyPatch(typeof(Beehive), "Interact")] [HarmonyPatch(typeof(Container), "Interact")] [HarmonyPatch(typeof(Door), "Interact")] [HarmonyPatch(typeof(Fish), "Interact")] [HarmonyPatch(typeof(RopeAttachment), "Interact")] [HarmonyPatch(typeof(SapCollector), "Interact")] [HarmonyPatch(typeof(Trap), "Interact")] [HarmonyPatch(typeof(Turret), "Interact")] [HarmonyPatch(typeof(ItemDrop), "Interact")] [HarmonyPatch(typeof(Sadle), "Interact")] private static void InteractableWithCharacter_Interact(Component __instance, Humanoid character, ref bool __result) { TryLogInteraction(__instance, __result, character); } [HarmonyPostfix] [HarmonyPatch(typeof(Feast), "Interact")] [HarmonyPatch(typeof(TeleportWorld), "Interact")] [HarmonyPatch(typeof(Bed), "Interact")] [HarmonyPatch(typeof(Chair), "Interact")] [HarmonyPatch(typeof(Barber), "Interact")] private static void InteractableWithHuman_Interact(Component __instance, Humanoid human, ref bool __result) { TryLogInteraction(__instance, __result, human); } [HarmonyPostfix] [HarmonyPatch(typeof(ArcheryTarget), "Interact")] [HarmonyPatch(typeof(Tameable), "Interact")] [HarmonyPatch(typeof(OfferingBowl), "Interact")] [HarmonyPatch(typeof(CookingStation), "Interact")] [HarmonyPatch(typeof(CraftingStation), "Interact")] [HarmonyPatch(typeof(Fermenter), "Interact")] [HarmonyPatch(typeof(Fireplace), "Interact")] [HarmonyPatch(typeof(ItemStand), "Interact")] [HarmonyPatch(typeof(Pet), "Interact")] [HarmonyPatch(typeof(ShieldGenerator), "Interact")] [HarmonyPatch(typeof(Petable), "Interact")] private static void InteractableWithUser_Interact(Component __instance, Humanoid user, ref bool __result) { TryLogInteraction(__instance, __result, user); } private static void TryLogInteraction(Component obj, bool result, Humanoid human, string info = null) { if (ActivityLoggerUtil.CheckIsLocalPlayer((Character)(object)human)) { string arg = (string.IsNullOrEmpty(info) ? string.Empty : $"info:{info}"); ActivityLog.AddLogWithPosition("Interact", $"{Utils.GetPrefabName(obj.gameObject)} result:{result} {arg}", obj); } } } [HarmonyPatch(typeof(Player))] public class PlayerPatches { [HarmonyPostfix] [HarmonyPatch("OnSpawned")] private static void Player_OnSpawned(Player __instance) { if (ActivityLoggerUtil.CheckIsLocalPlayer((Character)(object)__instance)) { ActivityLog.AddLogWithPlayerPosition("Spawned", __instance.GetPlayerData()); } } [HarmonyPostfix] [HarmonyPatch("PlacePiece")] private static void Player_PlacePiece(Player __instance, Piece piece) { if (ActivityLoggerUtil.CheckIsLocalPlayer((Character)(object)__instance)) { ActivityLog.AddLogWithPosition("Place", Utils.GetPrefabName(((Component)piece).gameObject), __instance.m_placementGhost); } } [HarmonyPostfix] [HarmonyPatch("TeleportTo")] private static void Player_TeleportTo(Player __instance, Vector3 pos, bool distantTeleport, ref bool __result) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (__result && ActivityLoggerUtil.CheckIsLocalPlayer((Character)(object)__instance)) { ActivityLog.AddLogWithPosition("Teleport", $"distant:{distantTeleport} to:{pos.ToPresentableString()}", (Component)(object)__instance); } } } [HarmonyPatch(typeof(Player))] public class PlayerRemovePiecePatches { private class RemovedPieceData { public string name; public Vector3 positon; } private static bool _removingPiece; private static RemovedPieceData _piece; [HarmonyPrefix] [HarmonyPatch("RemovePiece")] private static void Player_RemovePiece_Prefix(Player __instance) { _removingPiece = ActivityLoggerUtil.CheckIsLocalPlayer((Character)(object)__instance); } [HarmonyPostfix] [HarmonyPatch("CheckCanRemovePiece")] private static void Player_RemovePiece_Prefix(Player __instance, Piece piece, ref bool __result) { //IL_0031: 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) if (__result && _removingPiece && ActivityLoggerUtil.CheckIsLocalPlayer((Character)(object)__instance)) { _piece = new RemovedPieceData { name = Utils.GetPrefabName(((Component)piece).gameObject), positon = ((Component)piece).transform.position }; } } [HarmonyPostfix] [HarmonyPatch("RemovePiece")] private static void Player_RemovePiece_Postfix(Player __instance, ref bool __result) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (__result && _piece != null && ActivityLoggerUtil.CheckIsLocalPlayer((Character)(object)__instance)) { ActivityLog.AddLogWithPosition("Remove", _piece.name, _piece.positon); _piece = null; } } } [HarmonyPatch] public class PlayerUseItemPatches { [HarmonyPostfix] [HarmonyPatch(typeof(Player), "ConsumeItem")] private static void Humanoid_UseItem(Player __instance, Inventory inventory, ItemData item) { if (ActivityLoggerUtil.CheckIsLocalPlayer((Character)(object)__instance)) { ActivityLog.AddLogWithPosition("Consume", item.ToPresentableString() + " inventory:" + ((inventory != null) ? inventory.GetName() : null), (Component)(object)__instance); } } [HarmonyPostfix] [HarmonyPatch(typeof(CookingStation), "UseItem")] private static void CookingStation_UseItem(CookingStation __instance, Humanoid user, ItemData item, ref bool __result) { TryLogUsingItem((Component)(object)__instance, user, item, __result); } [HarmonyPostfix] [HarmonyPatch(typeof(Fireplace), "UseItem")] private static void Fireplace_UseItem(Fireplace __instance, Humanoid user, ItemData item, ref bool __result) { TryLogUsingItem((Component)(object)__instance, user, item, __result); } [HarmonyPostfix] [HarmonyPatch(typeof(Fermenter), "UseItem")] private static void Fermenter_UseItem(Fermenter __instance, Humanoid user, ItemData item, ref bool __result) { TryLogUsingItem((Component)(object)__instance, user, item, __result); } [HarmonyPostfix] [HarmonyPatch(typeof(ItemStand), "UseItem")] private static void ItemStand_UseItem(ItemStand __instance, Humanoid user, ItemData item, ref bool __result) { TryLogUsingItem((Component)(object)__instance, user, item, __result); } [HarmonyPostfix] [HarmonyPatch(typeof(OfferingBowl), "UseItem")] private static void OfferingBowl_UseItem(OfferingBowl __instance, Humanoid user, ItemData item, ref bool __result) { TryLogUsingItem((Component)(object)__instance, user, item, __result); } [HarmonyPostfix] [HarmonyPatch(typeof(Switch), "UseItem")] private static void Switch_UseItem(Switch __instance, Humanoid user, ItemData item, ref bool __result) { TryLogUsingItem((Component)(object)__instance, user, item, __result); } [HarmonyFinalizer] [HarmonyPatch(typeof(PrivateArea), "UseItem")] private static void PrivateArea_UseItem(PrivateArea __instance, Humanoid user, ItemData item, ref bool __result) { TryLogUsingItem((Component)(object)__instance, user, item, __result); } private static void TryLogUsingItem(Component obj, Humanoid humanoid, ItemData item, bool result) { if (result && ActivityLoggerUtil.CheckIsLocalPlayer((Character)(object)humanoid)) { ActivityLog.AddLogWithPosition("Use", "target:" + Utils.GetPrefabName(obj.gameObject) + " item:" + item.ToPresentableString(), obj); } } } [HarmonyPatch] public class SettingTextPatches { [HarmonyPostfix] [HarmonyPatch(typeof(Tameable), "SetText")] private static void Tameable_SetText(Tameable __instance, string text) { if (__instance.m_nview.IsValid()) { AddSetTextLog((Component)(object)__instance, text); } } [HarmonyPostfix] [HarmonyPatch(typeof(Sign), "SetText")] private static void Sign_SetText(Sign __instance, string text) { if (__instance.m_nview.IsValid() && string.Equals(__instance.GetText(), text)) { AddSetTextLog((Component)(object)__instance, text); } } [HarmonyPostfix] [HarmonyPatch(typeof(TeleportWorld), "SetText")] private static void TeleportWorld_SetText(TeleportWorld __instance, string text) { if (__instance.m_nview.IsValid()) { AddSetTextLog((Component)(object)__instance, text); } } private static void AddSetTextLog(Component obj, string text) { ActivityLog.AddLogWithPosition("Text", "target:" + Utils.GetPrefabName(obj.gameObject) + " text:" + text, obj); } } }