Decompiled source of FriendPatches v1.0.4

FriendPatches.dll

Decompiled 8 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FriendPatches.Callbacks;
using FriendPatches.Core;
using FriendPatches.Patches;
using FriendPatches.Tools;
using GameNetcodeStuff;
using HarmonyLib;
using Steamworks;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("FriendPatches")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("FriendPatches")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("955504ed-4fb7-496c-856e-f65e5b63ca4b")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace FriendPatches.Tools
{
	public static class PatchHelper
	{
		public static HarmonyMethod Method(Expression<Action> action, bool debug = false)
		{
			//IL_000f: 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_0020: Expected O, but got Unknown
			return new HarmonyMethod(SymbolExtensions.GetMethodInfo(action), -1, (string[])null, (string[])null, (bool?)debug)
			{
				priority = 10000
			};
		}

		public static HarmonyMethod Method<A>(Expression<Action<A>> action, bool debug = false)
		{
			//IL_000f: 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_0020: Expected O, but got Unknown
			return new HarmonyMethod(SymbolExtensions.GetMethodInfo<A>(action), -1, (string[])null, (string[])null, (bool?)debug)
			{
				priority = 10000
			};
		}

		public static HarmonyMethod Method<A, B>(Expression<Action<A, B>> action, bool debug = false)
		{
			//IL_000f: 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_0020: Expected O, but got Unknown
			return new HarmonyMethod(SymbolExtensions.GetMethodInfo((LambdaExpression)action), -1, (string[])null, (string[])null, (bool?)debug)
			{
				priority = 10000
			};
		}
	}
	public static class Reflection
	{
		public static Type Type(string type)
		{
			return AccessTools.TypeByName(type);
		}

		public static List<ConstructorInfo> Constructors(string type)
		{
			return AccessTools.GetDeclaredConstructors(Type(type), (bool?)null);
		}

		public static List<ConstructorInfo> Constructors(Type type)
		{
			return AccessTools.GetDeclaredConstructors(type, (bool?)null);
		}

		public static MethodBase Method(string type, string method, Type[] args = null, bool declared = true)
		{
			if (declared)
			{
				return AccessTools.DeclaredMethod(Type(type), method, args, (Type[])null);
			}
			return AccessTools.Method(Type(type), method, args, (Type[])null);
		}

		public static MethodBase Method(Type type, string method, Type[] args = null, bool declared = true)
		{
			if (declared)
			{
				return AccessTools.DeclaredMethod(type, method, args, (Type[])null);
			}
			return AccessTools.Method(type, method, args, (Type[])null);
		}

		public static FieldInfo Field(string type, string field, bool declared = true)
		{
			if (declared)
			{
				return AccessTools.DeclaredField(Type(type), field);
			}
			return AccessTools.Field(Type(type), field);
		}

		public static FieldInfo Field(Type type, string field, bool declared = true)
		{
			if (declared)
			{
				return AccessTools.DeclaredField(type, field);
			}
			return AccessTools.Field(type, field);
		}

		public static PropertyInfo Property(string type, string property, bool declared = true)
		{
			if (declared)
			{
				return AccessTools.DeclaredProperty(Type(type), property);
			}
			return AccessTools.Property(Type(type), property);
		}

		public static PropertyInfo Property(Type type, string property, bool declared = true)
		{
			if (declared)
			{
				return AccessTools.DeclaredProperty(type, property);
			}
			return AccessTools.Property(type, property);
		}
	}
}
namespace FriendPatches.Patches
{
	public static class GameNetworkManager_Patches
	{
		public static void Apply(Harmony harmony)
		{
			if (FriendPatchesSettings.SetPlayedWithOnSteam)
			{
				harmony.Patch(Reflection.Method(typeof(GameNetworkManager), "SteamMatchmaking_OnLobbyMemberJoined"), (HarmonyMethod)null, (HarmonyMethod)null, PatchHelper.Method(() => PlayerJoined(null, null)), (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}

		public static void HandleFriendJoin(List<SteamId> steamIdsInLobby, SteamId id)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			if (steamIdsInLobby == null || steamIdsInLobby.Contains(id))
			{
				return;
			}
			steamIdsInLobby.Add(id);
			if ((Object)(object)StartOfRound.Instance != (Object)null && StartOfRound.Instance.localPlayerController.playerSteamId == SteamId.op_Implicit(id))
			{
				foreach (SteamId otherId in steamIdsInLobby)
				{
					if (SteamId.op_Implicit(otherId) != SteamId.op_Implicit(id))
					{
						Task.Run(delegate
						{
							//IL_0001: Unknown result type (might be due to invalid IL or missing references)
							SteamFriends.SetPlayedWith(otherId);
						});
					}
				}
			}
			Task.Run(delegate
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				SteamFriends.SetPlayedWith(id);
			});
		}

		private static IEnumerable<CodeInstruction> PlayerJoined(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Expected O, but got Unknown
			CodeMatcher val = new CodeMatcher(instructions, generator);
			val.MatchForward(true, (CodeMatch[])(object)new CodeMatch[6]
			{
				new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction i) => i.opcode == OpCodes.Ldfld && ((FieldInfo)i.operand).Name == "steamIdsInLobby"), (string)null),
				new CodeMatch((OpCode?)OpCodes.Ldloc_1, (object)null, (string)null),
				new CodeMatch((OpCode?)OpCodes.Ldloc_3, (object)null, (string)null),
				new CodeMatch((OpCode?)OpCodes.Ldelema, (object)null, (string)null),
				new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction i) => i.opcode == OpCodes.Ldfld && ((FieldInfo)i.operand).Name == "Id" && ((FieldInfo)i.operand).DeclaringType == typeof(Friend)), (string)null),
				new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction i) => i.opcode == OpCodes.Callvirt && ((MethodInfo)i.operand).Name == "Add" && ((MethodInfo)i.operand).DeclaringType.Name.StartsWith("List")), (string)null)
			});
			if (!val.ReportFailure(MethodBase.GetCurrentMethod(), (Action<string>)FriendPatchesPlugin.Log.LogFatal))
			{
				val.SetInstruction(new CodeInstruction(OpCodes.Call, (object)Reflection.Method(typeof(GameNetworkManager_Patches), "HandleFriendJoin")));
			}
			return val.InstructionEnumeration();
		}
	}
}
namespace FriendPatches.Core
{
	public static class FriendPatchesInfo
	{
		public const string GUID = "lauriichan.friendpatches";

		public const string PrintName = "FriendPatches";

		public const string Version = "1.0.4";
	}
	public static class FriendPatchesSettings
	{
		public static bool SetPlayedWithOnSteam { get; private set; }

		public static bool UsernameFix { get; private set; }

		internal static void SetupConfig(ConfigFile cfg)
		{
			UsernameFix = cfg.Bind<bool>("General", "Enable the username fix patches", true, "Enables patches that listen to Steam callbacks for username changes and updates the player names accordingly.").Value;
			SetPlayedWithOnSteam = cfg.Bind<bool>("Steam", "Enable PlayedWith patches", true, "Enables patches that add players that joined your lobby to the 'Played With' list on Steam.").Value;
		}
	}
	[BepInPlugin("lauriichan.friendpatches", "FriendPatches", "1.0.4")]
	internal class FriendPatchesPlugin : BaseUnityPlugin
	{
		private Harmony harmony;

		public static ManualLogSource Log { get; private set; }

		public void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			FriendPatchesSettings.SetupConfig(((BaseUnityPlugin)this).Config);
			SetupCallbacks();
			SetupPatches();
		}

		private void SetupPatches()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			if (harmony == null)
			{
				harmony = new Harmony("lauriichan.friendpatches");
				GameNetworkManager_Patches.Apply(harmony);
			}
		}

		private void SetupCallbacks()
		{
			SteamFriendsCallback.Apply();
		}

		public void OnDestroy()
		{
			if (harmony != null)
			{
				harmony.UnpatchSelf();
				harmony = null;
			}
			ShutdownCallbacks();
		}

		private void ShutdownCallbacks()
		{
			SteamFriendsCallback.Unapply();
		}
	}
}
namespace FriendPatches.Callbacks
{
	public static class SteamFriendsCallback
	{
		private static bool applied;

		public static void Apply()
		{
			if (FriendPatchesSettings.UsernameFix)
			{
				applied = true;
				SteamFriends.OnPersonaStateChange += PersonaChanged;
			}
		}

		public static void Unapply()
		{
			if (applied)
			{
				applied = false;
				SteamFriends.OnPersonaStateChange -= PersonaChanged;
			}
		}

		private static void PersonaChanged(Friend friend)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			if (!GameNetworkManager.Instance.currentLobby.HasValue || (Object)(object)StartOfRound.Instance == (Object)null)
			{
				return;
			}
			SteamId friendId = friend.Id;
			if (GameNetworkManager.Instance.steamIdsInLobby.Contains(friendId))
			{
				Task.Run(delegate
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					DoNameUpdate(friendId, ((Friend)(ref friend)).Name, ((Friend)(ref friend)).IsMe);
				});
			}
		}

		private static void DoNameUpdate(SteamId friendId, string friendName, bool isMe)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			StartOfRound instance = StartOfRound.Instance;
			FriendPatchesPlugin.Log.LogInfo((object)$"Updating friend ({friendId}): {friendName}");
			PlayerControllerB val = instance.allPlayerScripts[instance.thisClientPlayerId];
			ulong num = SteamId.op_Implicit(friendId);
			for (int i = 0; i < instance.allPlayerScripts.Length; i++)
			{
				PlayerControllerB val2 = instance.allPlayerScripts[i];
				if ((Object)(object)val2 == (Object)null || !val2.isPlayerControlled || val2.playerSteamId != num)
				{
					continue;
				}
				val2.playerUsername = friendName;
				if ((Object)(object)val2.usernameBillboardText != (Object)null)
				{
					((TMP_Text)val2.usernameBillboardText).text = friendName;
				}
				string name = friendName;
				int numberOfDuplicateNamesInLobby = instance.GetNumberOfDuplicateNamesInLobby(val);
				if (numberOfDuplicateNamesInLobby > 0)
				{
					name = $"{friendName}{numberOfDuplicateNamesInLobby}";
				}
				if ((Object)(object)val.quickMenuManager != (Object)null)
				{
					PlayerListSlot val3 = val.quickMenuManager.playerListSlots[i];
					if (val3 != null)
					{
						val3.playerSteamId = SteamId.op_Implicit(friendId);
						((TMP_Text)val3.usernameHeader).text = friendName;
						if ((Object)(object)GameNetworkManager.Instance.localPlayerController != (Object)null)
						{
							val3.volumeSliderContainer.SetActive(!isMe);
						}
					}
				}
				if ((Object)(object)instance.mapScreen == (Object)null)
				{
					TransformAndName val4 = instance.mapScreen.radarTargets[i];
					if (val4 != null)
					{
						val4.name = name;
					}
				}
				break;
			}
		}

		private static int GetNumberOfDuplicateNamesInLobby(this StartOfRound round, PlayerControllerB self)
		{
			int num = 0;
			for (int i = 0; i < round.allPlayerScripts.Length; i++)
			{
				PlayerControllerB val = round.allPlayerScripts[i];
				if ((Object)(object)val != (Object)null && (val.isPlayerControlled || val.isPlayerDead) && !((Object)(object)val == (Object)(object)self) && val.playerUsername == self.playerUsername)
				{
					num++;
				}
			}
			for (int j = 0; j < round.allPlayerScripts.Length; j++)
			{
				PlayerControllerB val = round.allPlayerScripts[j];
				if ((Object)(object)val != (Object)null && (val.isPlayerControlled || val.isPlayerDead) && !((Object)(object)val == (Object)(object)self) && val.playerUsername == $"{val.playerUsername}{num}")
				{
					num++;
				}
			}
			return num;
		}
	}
}