using 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 BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GoblinCleanupMorePlayers.Patches; using HarmonyLib; using I2.Loc; using Microsoft.CodeAnalysis; using Steamworks; using TMPro; 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("GoblinCleanupMorePlayers")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+229564aa9c628763782faed15a74d94314182eaf")] [assembly: AssemblyProduct("More Players")] [assembly: AssemblyTitle("More Players")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [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 BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] [Embedded] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] [Embedded] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace Microsoft.CodeAnalysis { [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace GoblinCleanupMorePlayers { [BepInPlugin("GoblinCleanupMorePlayers", "More Players", "1.0.0")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Logger; internal static ConfigEntry ConfigMaxPlayers; internal static Harmony HarmonyInstance; public const int VanillaMaxPlayers = 4; public const string Id = "GoblinCleanupMorePlayers"; public static string Name => "More Players"; public static string Version => "1.0.0"; private void Awake() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown Logger = ((BaseUnityPlugin)this).Logger; HarmonyInstance = new Harmony("GoblinCleanupMorePlayers"); ConfigMaxPlayers = ((BaseUnityPlugin)this).Config.Bind("General", "MaxPlayers", 8, "Maximum number of players (including yourself). Steam lobbies support up to 250. Range: 1-250."); if (ConfigMaxPlayers.Value < 1) { ConfigMaxPlayers.Value = 1; } if (ConfigMaxPlayers.Value > 250) { ConfigMaxPlayers.Value = 250; } Logger.LogInfo((object)string.Format("Plugin {0} loaded! Max players set to {1}", "GoblinCleanupMorePlayers", ConfigMaxPlayers.Value)); HarmonyInstance.PatchAll(typeof(SteamLobbyPatches)); HarmonyInstance.PatchAll(typeof(MenuManagerPatches)); HarmonyInstance.PatchAll(typeof(DungeonManagerPatches)); HarmonyInstance.PatchAll(typeof(DungeonPlayersPatches)); HarmonyInstance.PatchAll(typeof(LobbiesListManagerPatches)); HarmonyInstance.PatchAll(typeof(RewardsManagerPatches)); Logger.LogInfo((object)"All patches applied"); } private void OnDestroy() { Harmony harmonyInstance = HarmonyInstance; if (harmonyInstance != null) { harmonyInstance.UnpatchSelf(); } Logger.LogInfo((object)"Plugin unloaded"); } } } namespace GoblinCleanupMorePlayers.Patches { public static class DungeonManagerPatches { [HarmonyPatch(typeof(DungeonManager), "UpdatePlayerKickout")] [HarmonyPrefix] private static bool FixKickoutBounds(DungeonManager __instance) { for (int i = 0; i < __instance.kickoutPlayer.Count; i++) { __instance.kickoutPlayer[i].SetActive(false); } List list = new List(); foreach (GoblinCharacterController player in DungeonPlayers.instance.players) { if (Object.op_Implicit((Object)(object)player) && (Object)(object)player != (Object)(object)GoblinCharacterController.localPlayer) { list.Add(player); } } for (int j = 0; j < list.Count; j++) { if (j < __instance.kickoutPlayer.Count) { __instance.kickoutPlayer[j].SetActive(true); } if (j < __instance.txtkickoutNames.Count) { ((TMP_Text)__instance.txtkickoutNames[j]).text = ((TMP_Text)list[j].playerName).text; } } return false; } } [HarmonyPatch] public static class DungeonPlayersPatches { [HarmonyPatch(typeof(DungeonPlayers), "GetPlayerDefaultSpawnPoint")] [HarmonyPrefix] private static bool AllSpawnAtHostRoom(ref Transform __result) { DungeonPlayers instance = DungeonPlayers.instance; if (instance.RoomsspawnPoints.Length == 0) { __result = instance.staffRoomSpawnPoint; } else { __result = instance.RoomsspawnPoints[0]; } return false; } [HarmonyPatch(typeof(DungeonPlayers), "OnStartClient")] [HarmonyPostfix] private static void InitSharedRoomState(DungeonPlayers __instance) { for (int i = 0; i < __instance.restoreColliders.Length; i++) { if ((Object)(object)__instance.restoreColliders[i] != (Object)null) { ((Component)__instance.restoreColliders[i]).gameObject.SetActive(false); } } for (int j = 1; j < __instance.RoomDoorObject.Length; j++) { if ((Object)(object)__instance.RoomDoorObject[j] != (Object)null) { __instance.RoomDoorObject[j].SetActive(true); } } if (__instance.RoomDoorObject.Length != 0 && (Object)(object)__instance.RoomDoorObject[0] != (Object)null) { __instance.RoomDoorObject[0].SetActive(false); } if (__instance.playerFrames.Length != 0 && (Object)(object)__instance.playerFrames[0] != (Object)null) { __instance.playerFrames[0].SetDisconnectData("Shared Room", __instance.noAvatarImage); } for (int k = 1; k < __instance.playerFrames.Length; k++) { if ((Object)(object)__instance.playerFrames[k] != (Object)null) { __instance.playerFrames[k].SetDisconnectData("Out of Order", __instance.noAvatarImage); } } } [HarmonyPatch(typeof(DungeonPlayers), "SetRoomData")] [HarmonyPrefix] private static bool SuppressSetRoomData() { return false; } [HarmonyPatch(typeof(DungeonPlayers), "EnableRoomDoor")] [HarmonyPrefix] private static bool SkipNonHostRoomManagement(int playerIndex) { return playerIndex == 0; } } public static class LobbiesListManagerPatches { [HarmonyPatch(typeof(LobbiesListManager), "UpdateLobbyEntry")] [HarmonyPostfix] private static void FixPlayerCountDisplay(LobbyDataEntry lobbyData, CSteamID lobbyID) { //IL_0000: 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) //IL_0028: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) string text = SteamMatchmaking.GetNumLobbyMembers(lobbyID) + "/" + SteamMatchmaking.GetLobbyMemberLimit(lobbyID); lobbyData.SetLobbyData(SteamMatchmaking.GetLobbyData(lobbyID, "isFull") == "False", SteamMatchmaking.GetLobbyData(lobbyID, "password"), text, SteamMatchmaking.GetLobbyData(lobbyID, "Level"), SteamMatchmaking.GetLobbyData(lobbyID, "GameVersion") == Application.version); } } public static class MenuManagerPatches { [HarmonyPatch(typeof(MenuManager), "OnClick_Host_Steam")] [HarmonyPrefix] private static void LogHostClick(MenuManager __instance) { Plugin.Logger.LogInfo((object)$"OnClick_Host_Steam: will use maxPlayers={Plugin.ConfigMaxPlayers.Value}"); } } public static class RewardsManagerPatches { private static T Field(object obj, string name) { return (T)AccessTools.Field(obj.GetType(), name).GetValue(obj); } private static void SetField(object obj, string name, object value) { AccessTools.Field(obj.GetType(), name).SetValue(obj, value); } [HarmonyPatch(typeof(RewardsManager), "ShowStats")] [HarmonyPrefix] private static bool FixShowStats(RewardsManager __instance, ref Dictionary stats, float extraExpMultiplier, float extraTicketsMultiplier) { //IL_0067: 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) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: 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_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Unknown result type (might be due to invalid IL or missing references) //IL_03df: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Unknown result type (might be due to invalid IL or missing references) //IL_03fc: Unknown result type (might be due to invalid IL or missing references) //IL_0419: Unknown result type (might be due to invalid IL or missing references) //IL_0443: Unknown result type (might be due to invalid IL or missing references) //IL_0564: Unknown result type (might be due to invalid IL or missing references) GameObject obj = Field(__instance, "panelHolder"); TextMeshProUGUI val = Field(__instance, "txtTime"); List list = Field>(__instance, "playerCards"); TextMeshProUGUI val2 = Field(__instance, "ticketsReward"); TextMeshProUGUI val3 = Field(__instance, "expReward"); obj.SetActive(true); if (DungeonManager.dungeonInstance.GetTime() <= 30f) { __instance.taskCount = 0; ((TMP_Text)val).color = Color.red; } else { ((TMP_Text)val).color = Color.white; } int num = Mathf.RoundToInt((float)__instance.taskCount * __instance.expMultiplier * extraExpMultiplier); int num2 = Mathf.RoundToInt((float)__instance.taskCount * __instance.ticketsMultiplier * extraTicketsMultiplier); SetField(__instance, "expRewardAmount", num); SetField(__instance, "ticketsRewardAmount", num2); ProgressionController.AddStackedTickets(num2); ProgressionController.Instance.AddExpToClaim(num); ((TMP_Text)val2).text = ProgressionController.Instance.GetTicketsToClaim().ToString(); ((TMP_Text)val3).text = ProgressionController.Instance.GetExpToClaim().ToString(); foreach (PlayerStatsCard item in list) { item.holder.SetActive(false); } List list2 = new List(); int num3 = -1; int num4 = 0; int num5 = 9999; int num6 = -1; int num7 = 0; int num8 = -1; int num9 = -1; int num10 = 0; foreach (KeyValuePair stat in stats) { if (DungeonPlayers.instance.IsPlayerInLobby(stat.Key)) { if (num10 >= list.Count) { break; } PlayerStatsCard val4 = list[num10]; val4.holder.SetActive(true); ((TMP_Text)val4.txtName).text = SteamFriends.GetFriendPersonaName(stat.Key); ((TMP_Text)val4.txtDeaths).text = stat.Value.deads.ToString(); ((TMP_Text)val4.txtRestorables).text = stat.Value.restorableObjects.ToString(); ((TMP_Text)val4.txtBlood).text = stat.Value.bloodstains.ToString(); ((TMP_Text)val4.txtOrganic).text = stat.Value.organicRemains.ToString(); ((TMP_Text)val4.txtTraps).text = stat.Value.traps.ToString(); ((TMP_Text)val4.txtMana).text = stat.Value.manaObjects.ToString(); ((TMP_Text)val4.txtGoldenChests).text = stat.Value.chestsFilled.ToString(); ((TMP_Text)val4.txtMonsters).text = stat.Value.monsters.ToString(); int num11 = stat.Value.bloodstains + stat.Value.organicRemains * 2 + stat.Value.restorableObjects * 3 + stat.Value.traps * 4 + stat.Value.manaObjects * 3 + stat.Value.chestsFilled * 5 + stat.Value.monsters * 10 - stat.Value.deads; if (num11 > num4) { num4 = num11; num3 = num10; } else if (num11 < num5) { num5 = num11; num6 = num10; } else if (stat.Value.deads > num7) { num7 = stat.Value.deads; num8 = num10; } else { num9 = num10; } list2.Add(stat.Key); SetNomination(__instance, "lazy", val4.txtTitle); num10++; } } if (num10 <= 1) { SetNomination(__instance, "single", list[0].txtTitle); return false; } if (num3 != -1) { SetNomination(__instance, "MVP", list[num3].txtTitle); } if (num6 != -1) { SetNomination(__instance, "lazy", list[num6].txtTitle); } if (num8 != -1) { SetNomination(__instance, "death", list[num8].txtTitle); } if (num9 != -1 && stats.Count >= 4) { PlayerStats val5 = stats[list2[num9]]; int restorableObjects = val5.restorableObjects; int num12 = 0; if (val5.bloodstains > restorableObjects) { restorableObjects = val5.bloodstains; num12 = 1; } else if (val5.organicRemains > restorableObjects) { restorableObjects = val5.organicRemains; num12 = 2; } else if (val5.traps > restorableObjects) { restorableObjects = val5.traps; num12 = 3; } else if (val5.manaObjects > restorableObjects) { restorableObjects = val5.manaObjects; num12 = 4; } else if (val5.chestsFilled > restorableObjects) { restorableObjects = val5.chestsFilled; num12 = 5; } else if (val5.monsters > restorableObjects) { restorableObjects = val5.monsters; num12 = 6; } SetNomination(__instance, num12 switch { 0 => "objects", 1 => "blood", 2 => "organic", 3 => "traps", 4 => "mana", 5 => "chests", 6 => "monsters", _ => "objects", }, list[num9].txtTitle); } return false; } private static void SetNomination(RewardsManager instance, string find, TextMeshProUGUI txtTitle) { //IL_0015: 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) //IL_001b: 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) //IL_003f: Unknown result type (might be due to invalid IL or missing references) foreach (Nominations item in Field>(instance, "nominations")) { if (item.id.ToUpper().Trim() == find.ToUpper().Trim()) { ((TMP_Text)txtTitle).text = LocalizedString.op_Implicit(item.localizatedTitle); break; } } } } public static class SteamLobbyPatches { [HarmonyPatch(typeof(SteamLobby), "HostLobby")] [HarmonyPrefix] private static void OverrideMaxPlayers(ref int maxPlayers, ref ELobbyType lobbyType) { Plugin.Logger.LogInfo((object)$"HostLobby: overriding maxPlayers {maxPlayers} -> {Plugin.ConfigMaxPlayers.Value}"); maxPlayers = Plugin.ConfigMaxPlayers.Value; } [HarmonyPatch(typeof(SteamLobby), "OnLobbyCreated")] [HarmonyPostfix] private static void FixLobbyCreatedMaxPlayers(SteamLobby __instance) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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) if (__instance.CurrentLobbyID != 0L) { FieldInfo field = typeof(SteamLobby).GetField("maxPlayers", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { int num = (int)field.GetValue(__instance); field.SetValue(__instance, Plugin.ConfigMaxPlayers.Value); Plugin.Logger.LogInfo((object)$"OnLobbyCreated: fixed maxPlayers {num} -> {Plugin.ConfigMaxPlayers.Value}"); } CSteamID val = new CSteamID(__instance.CurrentLobbyID); int value = Plugin.ConfigMaxPlayers.Value; SteamMatchmaking.SetLobbyMemberLimit(val, value); int numLobbyMembers = SteamMatchmaking.GetNumLobbyMembers(val); SteamMatchmaking.SetLobbyData(val, "players", numLobbyMembers + " / " + value); SteamMatchmaking.SetLobbyData(val, "isFull", (numLobbyMembers >= value).ToString()); Plugin.Logger.LogInfo((object)$"OnLobbyCreated: SetLobbyMemberLimit -> {value}, players={numLobbyMembers}/{value}"); } } } }