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 FriendPatches v1.0.4
FriendPatches.dll
Decompiled 2 years agousing 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; } } }