using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using Bifrost.ConstEnum;
using BiggerLobby;
using BiggerLobby.Patches;
using HarmonyLib;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using ReluProtocol.Enum;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyTitle("BiggerLobby")]
[assembly: AssemblyProduct("BiggerLobby")]
[assembly: AssemblyCompany("dsh")]
[assembly: HarmonyDontPatchAll]
[assembly: MelonInfo(typeof(Core), "BiggerLobby", "0.1.0", "dsh", null)]
[assembly: MelonGame("ReLUGames", "MIMESIS")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
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;
}
}
}
namespace BiggerLobby
{
public sealed class Core : MelonMod
{
internal static Core Instance { get; private set; }
public override void OnInitializeMelon()
{
Instance = this;
ModPreferences.Initialize();
if (!ModPreferences.Enabled)
{
MelonLogger.Msg("BiggerLobby 已在配置中禁用,跳过补丁。");
return;
}
ApplyPatches();
MelonLogger.Msg($"[BiggerLobby] 配置:MaxPlayers={ModPreferences.MaxPlayers}, MenuColumns={ModPreferences.MenuColumns}, " + $"ResultColumns={ModPreferences.ResultColumns}, ResultTopOffset={ModPreferences.ResultTopOffset}, DebugPlaceholders={ModPreferences.DebugPlaceholders}");
MelonLogger.Msg($"[BiggerLobby] 人数上限 {ModPreferences.MaxPlayers},界面最多 {Math.Min(ModPreferences.MaxPlayers, 16)} 行。");
if (ModPreferences.ResultColumns <= 4 && ModPreferences.MaxPlayers > 8)
{
MelonLogger.Msg("[BiggerLobby] 提示:ResultColumns=4 时结算界面会排成 4×4;想要 8×2 请把配置改成 ResultColumns = 8 后重启。");
}
}
private void ApplyPatches()
{
int num = 0;
Type[] types = typeof(Core).Assembly.GetTypes();
foreach (Type type in types)
{
if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: true).Any())
{
try
{
((MelonBase)this).HarmonyInstance.PatchAll(type);
num++;
}
catch (Exception arg)
{
MelonLogger.Error($"补丁类 {type.Name} 应用失败:{arg}");
}
}
}
MelonLogger.Msg($"Harmony 补丁完成:{num} 个补丁类,{((MelonBase)this).HarmonyInstance.GetPatchedMethods().Count()} 个方法。");
}
public override void OnUpdate()
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
if (ModPreferences.DebugPlaceholders)
{
Keyboard current = Keyboard.current;
if (current != null && ((ButtonControl)current[ModPreferences.DebugResultKey]).wasPressedThisFrame)
{
DebugTools.ShowFakeSurvivalResult();
}
}
}
public override void OnDeinitializeMelon()
{
try
{
((MelonBase)this).HarmonyInstance.UnpatchSelf();
}
catch (Exception ex)
{
MelonLogger.Warning("卸载补丁时出错:" + ex.Message);
}
}
}
internal static class DebugTools
{
private static object? _uiPrefabs;
private static MethodInfo? _showDialog;
internal static void ShowFakeSurvivalResult()
{
try
{
Hub s = Hub.s;
if ((Object)(object)s == (Object)null || (Object)(object)Hub.Main == (Object)null)
{
MelonLogger.Msg("[BiggerLobby] 当前不在游戏中,无法打开结算界面。");
return;
}
object obj = AccessTools.Property(typeof(Hub), "tableman")?.GetValue(s);
if (obj == null)
{
MelonLogger.Warning("[BiggerLobby] 找不到 TableManager。");
return;
}
if (_uiPrefabs == null)
{
_uiPrefabs = AccessTools.Field(obj.GetType(), "uiprefabs")?.GetValue(obj);
}
if (_uiPrefabs == null)
{
MelonLogger.Warning("[BiggerLobby] 找不到 MMUIPrefabTable。");
return;
}
if ((object)_showDialog == null)
{
_showDialog = AccessTools.Method(_uiPrefabs.GetType(), "ShowTimerDialog", new Type[3]
{
typeof(string),
typeof(float),
typeof(object[])
}, (Type[])null);
}
if (_showDialog == null)
{
MelonLogger.Warning("[BiggerLobby] 找不到 ShowTimerDialog。");
return;
}
object[] array = SurvivalResultPatch.BuildDebugParameters(Mathf.Min(ModPreferences.MaxPlayers, 16));
if (array == null)
{
MelonLogger.Warning("[BiggerLobby] 结算界面调试参数构造失败。");
return;
}
_showDialog.Invoke(_uiPrefabs, new object[3] { "SurvivalResult", 0f, array });
MelonLogger.Msg("[BiggerLobby] 已打开 16 人结算界面(调试占位数据)。");
}
catch (Exception ex)
{
MelonLogger.Warning("[BiggerLobby] 打开调试结算界面失败:" + (ex.InnerException?.Message ?? ex.Message));
}
}
}
internal static class ModPreferences
{
private const string CategoryId = "BiggerLobby";
private const string CategoryDisplayName = "BiggerLobby";
private static MelonPreferences_Category? _category;
private static MelonPreferences_Entry<bool>? _enabled;
private static MelonPreferences_Entry<bool>? _verbose;
private static MelonPreferences_Entry<int>? _maxPlayers;
private static MelonPreferences_Entry<bool>? _debugPlaceholders;
private static MelonPreferences_Entry<string>? _debugResultKey;
private static MelonPreferences_Entry<bool>? _showSlotLabel;
private static MelonPreferences_Entry<bool>? _showSteamId;
private static MelonPreferences_Entry<int>? _menuColumns;
private static MelonPreferences_Entry<float>? _menuScale;
private static MelonPreferences_Entry<int>? _resultColumns;
private static MelonPreferences_Entry<float>? _resultScale;
private static MelonPreferences_Entry<float>? _resultTopOffset;
private static MelonPreferences_Entry<int>? _spectatorColumns;
private static MelonPreferences_Entry<float>? _spectatorScale;
private static MelonPreferences_Entry<float>? _spectatorOffsetX;
private static MelonPreferences_Entry<float>? _spectatorOffsetY;
private static MelonPreferences_Entry<bool>? _spectatorFillByColumn;
private static MelonPreferences_Entry<bool>? _showFullSpectatorName;
internal static bool Enabled => Entry(ref _enabled).Value;
internal static bool Verbose => Entry(ref _verbose).Value;
internal static int MaxPlayers => Mathf.Clamp(Entry(ref _maxPlayers).Value, 2, 32);
internal static bool DebugPlaceholders => Entry(ref _debugPlaceholders).Value;
internal static Key DebugResultKey
{
get
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
if (!Enum.TryParse<Key>(Entry(ref _debugResultKey).Value, ignoreCase: true, out Key result))
{
return (Key)103;
}
return result;
}
}
internal static bool ShowSlotLabel => Entry(ref _showSlotLabel).Value;
internal static bool ShowSteamId => Entry(ref _showSteamId).Value;
internal static int MenuColumns => Mathf.Clamp(Entry(ref _menuColumns).Value, 1, 4);
internal static float MenuScale => Mathf.Clamp(Entry(ref _menuScale).Value, 0f, 2f);
internal static int ResultColumns => Mathf.Clamp(Entry(ref _resultColumns).Value, 1, 8);
internal static float ResultScale => Mathf.Clamp(Entry(ref _resultScale).Value, 0f, 2f);
internal static float ResultTopOffset => Mathf.Clamp(Entry(ref _resultTopOffset).Value, -2000f, 2000f);
internal static int SpectatorColumns => Mathf.Clamp(Entry(ref _spectatorColumns).Value, 1, 8);
internal static float SpectatorScale => Mathf.Clamp(Entry(ref _spectatorScale).Value, 0f, 2f);
internal static float SpectatorOffsetX => Mathf.Clamp(Entry(ref _spectatorOffsetX).Value, -2000f, 2000f);
internal static float SpectatorOffsetY => Mathf.Clamp(Entry(ref _spectatorOffsetY).Value, -2000f, 2000f);
internal static bool SpectatorFillByColumn => Entry(ref _spectatorFillByColumn).Value;
internal static bool ShowFullSpectatorName => Entry(ref _showFullSpectatorName).Value;
internal static void Initialize()
{
if (_category == null)
{
_category = MelonPreferences.CreateCategory("BiggerLobby", "BiggerLobby");
_enabled = CreateEntry("Enabled", defaultValue: true, "Enabled", "Enable BiggerLobby. When disabled, no patches are applied.");
_verbose = CreateEntry("Verbose", defaultValue: false, "Verbose logging", "Log extra diagnostics to the MelonLoader console.");
_maxPlayers = CreateEntry("MaxPlayers", 20, "Max players", "Lobby / session player limit (2 - 32). The UI shows at most 16.");
_debugPlaceholders = CreateEntry("DebugPlaceholders", defaultValue: false, "Debug: fill UI with placeholders", "Fill every UI slot with fake players so you can check alignment and scaling while playing alone.");
_debugResultKey = CreateEntry("DebugResultKey", "F10", "Debug: result screen hotkey", "Key that opens the survival result screen with 16 placeholder players (only when DebugPlaceholders = true).");
_showSlotLabel = CreateEntry("ShowSlotLabel", defaultValue: true, "Show slot number", "Draw the slot number (and optionally the SteamID) on each player row.");
_showSteamId = CreateEntry("ShowSteamId", defaultValue: false, "Show SteamID", "Show the player's SteamID under the slot number.");
_menuColumns = CreateEntry("MenuColumns", 2, "Player list columns", "How many columns the in-game menu player list is laid out in (1 - 4).");
_menuScale = CreateEntry("MenuScale", 0f, "Player list scale (0 = auto)", "Row scale of the menu player list. 0 = fit the list area automatically.");
_resultColumns = CreateEntry("ResultColumns", 8, "Result screen columns", "How many columns the survival result screen is laid out in (1 - 8).");
_spectatorColumns = CreateEntry("SpectatorColumns", 2, "Spectator list columns", "Columns of the spectator player list (1 - 8). 16 players with 2 = 2 x 8.");
_spectatorScale = CreateEntry("SpectatorScale", 0f, "Spectator list scale (0 = auto)", "Row scale of the spectator list. 0 = fit the list area automatically.");
_spectatorOffsetX = CreateEntry("SpectatorOffsetX", 0f, "Spectator list offset X", "Horizontal offset of the spectator list in pixels.");
_spectatorOffsetY = CreateEntry("SpectatorOffsetY", 0f, "Spectator list offset Y", "Vertical offset of the spectator list in pixels (positive = lower).");
_spectatorFillByColumn = CreateEntry("SpectatorFillByColumn", defaultValue: true, "Spectator list fill by column", "Fill the first column top-to-bottom before the second column.");
_showFullSpectatorName = CreateEntry("ShowFullSpectatorName", defaultValue: true, "Show full spectated name", "Expand the centered spectated-player name so long names are not truncated.");
_resultTopOffset = CreateEntry("ResultTopOffset", -50f, "Result top offset (pixels)", "Pixels added to the auto-aligned top edge (positive = lower, negative = higher). 0 aligns with the vanilla 4-column position.");
_resultScale = CreateEntry("ResultScale", 0f, "Result screen scale (0 = auto)", "Column scale of the result screen. 0 = fit the screen area automatically.");
}
}
internal static void Log(string message)
{
if (Verbose)
{
MelonLogger.Msg(message);
}
}
private static MelonPreferences_Entry<T> Entry<T>(ref MelonPreferences_Entry<T>? field)
{
if (field == null)
{
throw new InvalidOperationException("ModPreferences.Initialize() must run before preferences are read.");
}
return field;
}
private static MelonPreferences_Entry<T> CreateEntry<T>(string identifier, T defaultValue, string displayName, string? description = null)
{
if (_category == null)
{
throw new InvalidOperationException("Preference category not initialized.");
}
return _category.CreateEntry<T>(identifier, defaultValue, displayName, description, false, false, (ValueValidator)null, (string)null);
}
}
internal static class UiUtil
{
internal static void DisableLayoutGroups(RectTransform area)
{
LayoutGroup[] components = ((Component)area).GetComponents<LayoutGroup>();
for (int i = 0; i < components.Length; i++)
{
((Behaviour)components[i]).enabled = false;
}
ContentSizeFitter[] components2 = ((Component)area).GetComponents<ContentSizeFitter>();
for (int i = 0; i < components2.Length; i++)
{
((Behaviour)components2[i]).enabled = false;
}
}
internal static void RestoreLayout(RectTransform area)
{
LayoutGroup[] components = ((Component)area).GetComponents<LayoutGroup>();
for (int i = 0; i < components.Length; i++)
{
((Behaviour)components[i]).enabled = true;
}
ContentSizeFitter[] components2 = ((Component)area).GetComponents<ContentSizeFitter>();
for (int i = 0; i < components2.Length; i++)
{
((Behaviour)components2[i]).enabled = true;
}
UiGridLayout component = ((Component)area).GetComponent<UiGridLayout>();
if ((Object)(object)component != (Object)null)
{
((Behaviour)component).enabled = false;
}
LayoutRebuilder.ForceRebuildLayoutImmediate(area);
}
internal static void LayoutGrid(IReadOnlyList<RectTransform?> items, int visible, RectTransform area, Vector2 areaSize, Vector2 natural, int columns, float scaleOverride, float topOffset = 0f, float offsetX = 0f, bool byColumn = false)
{
//IL_002d: 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_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
//IL_0171: Unknown result type (might be due to invalid IL or missing references)
//IL_0187: Unknown result type (might be due to invalid IL or missing references)
//IL_019d: Unknown result type (might be due to invalid IL or missing references)
//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
//IL_01da: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)area == (Object)null || items.Count == 0)
{
return;
}
int num = Mathf.Clamp(columns, 1, 8);
int num2 = Mathf.Max(1, Mathf.CeilToInt((float)visible / (float)num));
float x = areaSize.x;
float y = areaSize.y;
if (x < 1f || y < 1f)
{
return;
}
float num3 = Mathf.Clamp(topOffset, (0f - y) * 0.5f, y * 0.9f);
float num4 = Mathf.Max(1f, y - num3);
float num5 = ((scaleOverride > 0f) ? scaleOverride : Mathf.Min(new float[3]
{
1f,
x / ((float)num * natural.x),
num4 / ((float)num2 * natural.y)
}));
num5 = Mathf.Clamp(num5, 0.05f, 2f);
float num6 = natural.x * num5;
float num7 = natural.y * num5;
float num8 = (x - (float)num * num6) * 0.5f + offsetX;
for (int i = 0; i < items.Count; i++)
{
RectTransform val = items[i];
if ((Object)(object)val == (Object)null)
{
continue;
}
bool flag = i < visible;
if (((Component)val).gameObject.activeSelf != flag)
{
((Component)val).gameObject.SetActive(flag);
}
if (flag)
{
int num9;
int num10;
if (byColumn)
{
num9 = i / num2;
num10 = i % num2;
}
else
{
num9 = i % num;
num10 = i / num;
}
if (num9 >= num)
{
num9 = num - 1;
}
val.anchorMin = new Vector2(0f, 1f);
val.anchorMax = new Vector2(0f, 1f);
val.pivot = new Vector2(0f, 1f);
val.sizeDelta = natural;
((Transform)val).localScale = new Vector3(num5, num5, 1f);
val.anchoredPosition = new Vector2(num8 + (float)num9 * num6, 0f - (float)num10 * num7 - num3);
}
}
}
internal static TMP_Text CreateLabel(Transform parent, TMP_FontAsset? font, string name, float fontSize)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
val.transform.SetParent(parent, false);
TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
if ((Object)(object)font != (Object)null)
{
((TMP_Text)val2).font = font;
}
((TMP_Text)val2).fontSize = fontSize;
((TMP_Text)val2).alignment = (TextAlignmentOptions)260;
((Graphic)val2).raycastTarget = false;
((TMP_Text)val2).textWrappingMode = (TextWrappingModes)0;
((TMP_Text)val2).overflowMode = (TextOverflowModes)0;
RectTransform val3 = (RectTransform)val.transform;
val3.anchorMin = new Vector2(1f, 1f);
val3.anchorMax = new Vector2(1f, 1f);
val3.pivot = new Vector2(1f, 1f);
val3.anchoredPosition = new Vector2(-8f, -6f);
val3.sizeDelta = new Vector2(460f, 26f);
return (TMP_Text)(object)val2;
}
}
internal sealed class UiGridLayout : MonoBehaviour
{
private RectTransform _area;
private RectTransform? _fallback;
private List<RectTransform?> _items = new List<RectTransform>();
private int _visible;
private Vector2 _natural;
private int _columns;
private float _scale;
private float _topOffset;
private float _offsetX;
private bool _byColumn;
private int _frames;
internal static void Schedule(RectTransform area, List<RectTransform?> items, int visible, Vector2 natural, int columns, float scale, RectTransform? fallback = null, float topOffset = 0f, float offsetX = 0f, bool byColumn = false)
{
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)area == (Object)null) && items.Count != 0)
{
UiGridLayout uiGridLayout = ((Component)area).GetComponent<UiGridLayout>();
if ((Object)(object)uiGridLayout == (Object)null)
{
uiGridLayout = ((Component)area).gameObject.AddComponent<UiGridLayout>();
}
uiGridLayout._area = area;
uiGridLayout._fallback = fallback;
uiGridLayout._items = items;
uiGridLayout._visible = visible;
uiGridLayout._natural = natural;
uiGridLayout._columns = columns;
uiGridLayout._scale = scale;
uiGridLayout._topOffset = topOffset;
uiGridLayout._offsetX = offsetX;
uiGridLayout._byColumn = byColumn;
uiGridLayout._frames = 0;
((Behaviour)uiGridLayout).enabled = true;
}
}
private void LateUpdate()
{
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: 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_018a: Unknown result type (might be due to invalid IL or missing references)
//IL_018c: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: 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)
//IL_00de: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_area == (Object)null || !((Component)_area).gameObject.activeInHierarchy)
{
return;
}
_frames++;
if (_frames <= 2)
{
Canvas.ForceUpdateCanvases();
return;
}
if (_frames == 3)
{
UiUtil.DisableLayoutGroups(_area);
}
Rect rect = _area.rect;
Vector2 size = ((Rect)(ref rect)).size;
string text = "area";
if (size.x < 1f || size.y < 1f)
{
if ((Object)(object)_fallback != (Object)null)
{
rect = _fallback.rect;
if (((Rect)(ref rect)).width >= 1f)
{
rect = _fallback.rect;
if (((Rect)(ref rect)).height >= 1f)
{
rect = _fallback.rect;
size = ((Rect)(ref rect)).size;
text = "fallback:" + ((Object)_fallback).name;
goto IL_0110;
}
}
}
((Vector2)(ref size))..ctor((float)Screen.width, (float)Screen.height);
text = "screen";
}
goto IL_0110;
IL_0110:
if (_frames == 3)
{
MelonLogger.Msg($"[BiggerLobby] 网格排布 area='{((Object)_area).name}' size={size} (来源 {text}), items={_items.Count}, visible={_visible}, cols={_columns}");
}
UiUtil.LayoutGrid(_items, _visible, _area, size, _natural, _columns, _scale, _topOffset, _offsetX, _byColumn);
}
}
}
namespace BiggerLobby.Patches
{
[HarmonyPatch(typeof(UIPrefab_InGameMenu_new))]
internal static class InGameMenuPatch
{
internal const int UiSlots = 16;
private static readonly Color PlaceholderColor = new Color(1f, 1f, 1f, 0.35f);
private static readonly FieldInfo? PlayerItemsField = AccessTools.Field(typeof(UIPrefab_InGameMenu_new), "playerItems");
private static readonly FieldInfo? PlayerInfosField = AccessTools.Field(typeof(UIPrefab_InGameMenu_new), "playerInfos");
private static readonly MethodInfo? SpeakMethod = AccessTools.Method(typeof(UIPrefab_InGameMenu_new), "OnClickSpeakButton", (Type[])null, (Type[])null);
private static readonly MethodInfo? KickMethod = AccessTools.Method(typeof(UIPrefab_InGameMenu_new), "OpenKickPlayerPopup", (Type[])null, (Type[])null);
private static readonly Dictionary<UIPrefab_InGameMenuPlayerInfo, TMP_Text> SlotLabels = new Dictionary<UIPrefab_InGameMenuPlayerInfo, TMP_Text>();
private static readonly Dictionary<TMP_Text, Color> OriginalColors = new Dictionary<TMP_Text, Color>();
private static FieldInfo? _steamIdField;
private static Type? _steamIdType;
[HarmonyPostfix]
[HarmonyPatch("Awake")]
private static void AwakePostfix(UIPrefab_InGameMenu_new __instance)
{
try
{
ExpandRows(__instance);
}
catch (Exception arg)
{
MelonLogger.Error($"[BiggerLobby] 扩展玩家列表失败:{arg}");
}
}
[HarmonyPostfix]
[HarmonyPatch("SetRemoteVolumeController_v2")]
private static void RefreshPostfix(UIPrefab_InGameMenu_new __instance)
{
try
{
Refresh(__instance);
}
catch (Exception arg)
{
MelonLogger.Error($"[BiggerLobby] 刷新玩家列表失败:{arg}");
}
}
private static void ExpandRows(UIPrefab_InGameMenu_new menu)
{
UIPrefab_InGameMenuPlayerInfo[] items = GetItems(menu);
if (items == null || items.Length == 0 || items.Length >= 16)
{
return;
}
UIPrefab_InGameMenuPlayerInfo val = items[^1];
if ((Object)(object)val == (Object)null || PlayerItemsField == null)
{
return;
}
Transform parent = ((Component)val).transform.parent;
List<UIPrefab_InGameMenuPlayerInfo> list = new List<UIPrefab_InGameMenuPlayerInfo>(items);
while (list.Count < 16)
{
int index = list.Count;
GameObject obj = Object.Instantiate<GameObject>(((Component)val).gameObject, parent);
((Object)obj).name = "PlayerList" + (index + 1);
obj.SetActive(true);
UIPrefab_InGameMenuPlayerInfo component = obj.GetComponent<UIPrefab_InGameMenuPlayerInfo>();
if ((Object)(object)component == (Object)null)
{
break;
}
component.SetIsLocalPlayer(false);
component.OnUI_Button_Icon_volume = delegate
{
InvokeMenu(menu, SpeakMethod, index);
};
component.OnUI_Button_IconBox_kick = delegate
{
InvokeMenu(menu, KickMethod, index);
};
list.Add(component);
}
PlayerItemsField.SetValue(menu, list.ToArray());
ModPreferences.Log($"[BiggerLobby] 玩家列表行数:{items.Length} -> {list.Count}");
}
private static void Refresh(UIPrefab_InGameMenu_new menu)
{
UIPrefab_InGameMenuPlayerInfo[] items = GetItems(menu);
if (items == null || items.Length == 0)
{
return;
}
IList infos = GetInfos(menu);
int num = Mathf.Min(infos?.Count ?? 0, items.Length);
int num2 = Mathf.Min(ModPreferences.MaxPlayers, 16);
bool debugPlaceholders = ModPreferences.DebugPlaceholders;
int visible = Mathf.Min(debugPlaceholders ? num2 : num, items.Length);
for (int i = 0; i < items.Length; i++)
{
UIPrefab_InGameMenuPlayerInfo val = items[i];
if (!((Object)(object)val == (Object)null))
{
if (i < num)
{
RestoreRow(val);
UpdateSlotLabel(val, i, GetSteamId(infos, i), placeholder: false);
}
else if (debugPlaceholders && i < num2)
{
MakePlaceholder(val, i);
UpdateSlotLabel(val, i, string.Empty, placeholder: true);
}
else
{
((Component)val).gameObject.SetActive(false);
SetLabelVisible(val, visible: false);
}
}
}
ScheduleLayout(items, visible);
}
private static void RestoreRow(UIPrefab_InGameMenuPlayerInfo row)
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
TMP_Text uE_UI_Text = row.UE_UI_Text;
if ((Object)(object)uE_UI_Text != (Object)null && OriginalColors.TryGetValue(uE_UI_Text, out var value))
{
((Graphic)uE_UI_Text).color = value;
}
}
private static void MakePlaceholder(UIPrefab_InGameMenuPlayerInfo row, int index)
{
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
((Component)row).gameObject.SetActive(true);
TMP_Text uE_UI_Text = row.UE_UI_Text;
if ((Object)(object)uE_UI_Text != (Object)null)
{
if (!OriginalColors.ContainsKey(uE_UI_Text))
{
OriginalColors[uE_UI_Text] = ((Graphic)uE_UI_Text).color;
}
uE_UI_Text.text = $"PLAYER {index + 1:D2}";
((Graphic)uE_UI_Text).color = PlaceholderColor;
}
Button uE_UI_Button_IconBox_kick = row.UE_UI_Button_IconBox_kick;
if ((Object)(object)uE_UI_Button_IconBox_kick != (Object)null)
{
((Component)uE_UI_Button_IconBox_kick).gameObject.SetActive(false);
}
Button uE_UI_Button_Icon_volume = row.UE_UI_Button_Icon_volume;
if ((Object)(object)uE_UI_Button_Icon_volume != (Object)null)
{
((Component)uE_UI_Button_Icon_volume).gameObject.SetActive(true);
}
Slider uE_UI_Slider = row.UE_UI_Slider;
if ((Object)(object)uE_UI_Slider != (Object)null)
{
((Component)uE_UI_Slider).gameObject.SetActive(true);
uE_UI_Slider.SetValueWithoutNotify(0.5f);
}
}
private static void UpdateSlotLabel(UIPrefab_InGameMenuPlayerInfo row, int index, string steamId, bool placeholder)
{
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
if (!SlotLabels.TryGetValue(row, out TMP_Text value) || (Object)(object)value == (Object)null)
{
TMP_Text uE_UI_Text = row.UE_UI_Text;
float fontSize = (((Object)(object)uE_UI_Text != (Object)null) ? Mathf.Max(12f, uE_UI_Text.fontSize * 0.55f) : 16f);
value = UiUtil.CreateLabel(((Component)row).transform, ((Object)(object)uE_UI_Text != (Object)null) ? uE_UI_Text.font : null, "BiggerLobbySlot", fontSize);
SlotLabels[row] = value;
}
string text = $"#{index + 1:D2}";
if (!placeholder && ModPreferences.ShowSteamId && !string.IsNullOrEmpty(steamId) && steamId != "0")
{
text = text + "\n" + steamId;
}
value.text = text;
((Graphic)value).color = (Color)(placeholder ? PlaceholderColor : new Color(1f, 1f, 1f, 0.8f));
((Component)value).gameObject.SetActive(ModPreferences.ShowSlotLabel);
}
private static void SetLabelVisible(UIPrefab_InGameMenuPlayerInfo row, bool visible)
{
if (SlotLabels.TryGetValue(row, out TMP_Text value) && (Object)(object)value != (Object)null)
{
((Component)value).gameObject.SetActive(visible && ModPreferences.ShowSlotLabel);
}
}
private static void ScheduleLayout(UIPrefab_InGameMenuPlayerInfo[] items, int visible)
{
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: 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_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
RectTransform val = (RectTransform)(((Object)(object)items[0] != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
RectTransform val2 = (RectTransform)(((Object)(object)val != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || visible <= 0)
{
return;
}
if (visible <= 4)
{
UiUtil.RestoreLayout(val2);
return;
}
Rect rect = val.rect;
Vector2 size = ((Rect)(ref rect)).size;
if (size.x < 1f || size.y < 1f)
{
((Vector2)(ref size))..ctor(720f, 92f);
}
List<RectTransform> items2 = ((IEnumerable<UIPrefab_InGameMenuPlayerInfo>)items).Select((Func<UIPrefab_InGameMenuPlayerInfo, RectTransform>)delegate(UIPrefab_InGameMenuPlayerInfo item)
{
if (!((Object)(object)item != (Object)null))
{
return (RectTransform)null;
}
Transform transform = ((Component)item).transform;
return (RectTransform)(object)((transform is RectTransform) ? transform : null);
}).ToList();
UiGridLayout.Schedule(val2, items2, visible, size, ModPreferences.MenuColumns, ModPreferences.MenuScale);
}
private static UIPrefab_InGameMenuPlayerInfo[]? GetItems(UIPrefab_InGameMenu_new menu)
{
return PlayerItemsField?.GetValue(menu) as UIPrefab_InGameMenuPlayerInfo[];
}
private static IList? GetInfos(UIPrefab_InGameMenu_new menu)
{
return PlayerInfosField?.GetValue(menu) as IList;
}
private static string GetSteamId(IList? infos, int index)
{
if (infos == null || index < 0 || index >= infos.Count)
{
return string.Empty;
}
object obj = infos[index];
if (obj == null)
{
return string.Empty;
}
Type type = obj.GetType();
if (_steamIdType != type)
{
_steamIdType = type;
_steamIdField = AccessTools.Field(type, "steamID");
}
return (_steamIdField?.GetValue(obj) as string) ?? string.Empty;
}
private static void InvokeMenu(object menu, MethodInfo? method, int index)
{
if (method == null)
{
return;
}
try
{
method.Invoke(menu, new object[1] { index });
}
catch (Exception ex)
{
MelonLogger.Warning("[BiggerLobby] 调用 " + method.Name + " 失败:" + (ex.InnerException?.Message ?? ex.Message));
}
}
}
[HarmonyPatch(typeof(SteamMatchmaking), "CreateLobby")]
internal static class CreateLobbyPatch
{
private static void Prefix(ref int cMaxMembers)
{
if (ModPreferences.Enabled)
{
cMaxMembers = ModPreferences.MaxPlayers;
MelonLogger.Msg($"[BiggerLobby] Steam 大厅人数上限 = {cMaxMembers}");
}
}
}
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
internal static class MaxPlayerCountPatch
{
private static readonly FieldInfo? MaxField = AccessTools.Field(typeof(DataConsts), "C_MaxPlayerCount");
private static void Postfix(DataConsts __instance)
{
if (!ModPreferences.Enabled || MaxField == null)
{
return;
}
try
{
MaxField.SetValue(__instance, ModPreferences.MaxPlayers);
MelonLogger.Msg($"[BiggerLobby] 游戏内人数上限 C_MaxPlayerCount = {MaxField.GetValue(__instance)}");
}
catch (Exception arg)
{
MelonLogger.Error($"[BiggerLobby] 写入 C_MaxPlayerCount 失败:{arg}");
}
}
}
[HarmonyPatch(typeof(UIPrefab_Spectator_PlayerListView), "Start")]
internal static class SpectatorListStartPatch
{
internal const int UiSlots = 16;
private static readonly FieldInfo? ItemsField = AccessTools.Field(typeof(UIPrefab_Spectator_PlayerListView), "playerListViewItems");
private static void Postfix(UIPrefab_Spectator_PlayerListView __instance)
{
if (!ModPreferences.Enabled)
{
return;
}
try
{
Expand(__instance);
}
catch (Exception arg)
{
MelonLogger.Error($"[BiggerLobby] 观战列表扩展失败:{arg}");
}
}
internal static UIPrefab_Spectator_PlayerListViewItem[]? GetItems(UIPrefab_Spectator_PlayerListView listView)
{
return ItemsField?.GetValue(listView) as UIPrefab_Spectator_PlayerListViewItem[];
}
private static void Expand(UIPrefab_Spectator_PlayerListView listView)
{
if (!(ItemsField?.GetValue(listView) is UIPrefab_Spectator_PlayerListViewItem[] array) || array.Length == 0 || array.Length >= 16)
{
return;
}
UIPrefab_Spectator_PlayerListViewItem val = array[^1];
if ((Object)(object)val == (Object)null)
{
return;
}
Transform parent = ((Component)val).transform.parent;
List<UIPrefab_Spectator_PlayerListViewItem> list = new List<UIPrefab_Spectator_PlayerListViewItem>(array);
while (list.Count < 16)
{
GameObject obj = Object.Instantiate<GameObject>(((Component)val).gameObject, parent);
((Object)obj).name = ((Object)((Component)val).gameObject).name + "_" + (list.Count + 1);
obj.SetActive(true);
UIPrefab_Spectator_PlayerListViewItem component = obj.GetComponent<UIPrefab_Spectator_PlayerListViewItem>();
if ((Object)(object)component == (Object)null)
{
MelonLogger.Warning("[BiggerLobby] 克隆观战列表项失败。");
break;
}
component.SetDead(false);
component.Clear();
list.Add(component);
}
ItemsField.SetValue(listView, list.ToArray());
MelonLogger.Msg($"[BiggerLobby] 观战列表行数:{array.Length} -> {list.Count}");
}
}
[HarmonyPatch(typeof(UIPrefab_Spectator_PlayerListView), "UpdatePlayerListView")]
internal static class SpectatorListUpdatePatch
{
private static void Postfix(UIPrefab_Spectator_PlayerListView __instance, object[] __args)
{
if (!ModPreferences.Enabled)
{
return;
}
try
{
UIPrefab_Spectator_PlayerListViewItem[] items = SpectatorListStartPatch.GetItems(__instance);
if (items == null || items.Length == 0)
{
return;
}
int num = 0;
if (__args != null && __args.Length != 0 && __args[0] is IList list)
{
num = list.Count;
}
int num2 = Mathf.Clamp(num, 0, items.Length);
if (ModPreferences.DebugPlaceholders)
{
for (int i = num; i < items.Length; i++)
{
UIPrefab_Spectator_PlayerListViewItem obj = items[i];
if (obj != null)
{
obj.SetName($"PLAYER {i + 1:D2}");
}
}
num2 = Mathf.Min(items.Length, Mathf.Min(ModPreferences.MaxPlayers, 16));
}
if (num2 > 0)
{
ScheduleLayout(items, num2);
}
}
catch (Exception arg)
{
MelonLogger.Error($"[BiggerLobby] 观战列表排布失败:{arg}");
}
}
private static void ScheduleLayout(UIPrefab_Spectator_PlayerListViewItem[] items, int visible)
{
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: 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_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
RectTransform val = (RectTransform)(((Object)(object)items[0] != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
RectTransform val2 = (RectTransform)(((Object)(object)val != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
{
return;
}
Rect rect = val.rect;
Vector2 size = ((Rect)(ref rect)).size;
if (size.x < 1f || size.y < 1f)
{
((Vector2)(ref size))..ctor(240f, 56f);
}
int columns = Mathf.Clamp(ModPreferences.SpectatorColumns, 1, 8);
List<RectTransform> items2 = ((IEnumerable<UIPrefab_Spectator_PlayerListViewItem>)items).Select((Func<UIPrefab_Spectator_PlayerListViewItem, RectTransform>)delegate(UIPrefab_Spectator_PlayerListViewItem item)
{
if (!((Object)(object)item != (Object)null))
{
return (RectTransform)null;
}
Transform transform = ((Component)item).transform;
return (RectTransform)(object)((transform is RectTransform) ? transform : null);
}).ToList();
UiGridLayout.Schedule(val2, items2, visible, size, columns, ModPreferences.SpectatorScale, val2, ModPreferences.SpectatorOffsetY, ModPreferences.SpectatorOffsetX, ModPreferences.SpectatorFillByColumn);
}
}
[HarmonyPatch(typeof(UIPrefab_Spectator), "SetSpectatedPlayerName")]
internal static class SpectatorNamePatch
{
private static void Postfix(UIPrefab_Spectator __instance)
{
if (!ModPreferences.Enabled || !ModPreferences.ShowFullSpectatorName)
{
return;
}
try
{
Fit(__instance);
}
catch (Exception ex)
{
MelonLogger.Warning("[BiggerLobby] 观战名字自适应失败:" + ex.Message);
}
}
private static void Fit(UIPrefab_Spectator spectator)
{
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
TMP_Text uE_UI_NameText = spectator.UE_UI_NameText;
if ((Object)(object)uE_UI_NameText == (Object)null)
{
return;
}
uE_UI_NameText.overflowMode = (TextOverflowModes)0;
uE_UI_NameText.textWrappingMode = (TextWrappingModes)0;
uE_UI_NameText.enableAutoSizing = false;
uE_UI_NameText.maxVisibleCharacters = 99999;
uE_UI_NameText.firstVisibleCharacter = 0;
RectTransform rectTransform = uE_UI_NameText.rectTransform;
float x = uE_UI_NameText.GetPreferredValues(uE_UI_NameText.text).x;
Rect rect = rectTransform.rect;
float width = ((Rect)(ref rect)).width;
if (x > width)
{
Canvas componentInParent = ((Component)uE_UI_NameText).GetComponentInParent<Canvas>();
float num = 1800f;
if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.rootCanvas != (Object)null)
{
rect = ((RectTransform)((Component)componentInParent.rootCanvas).transform).rect;
num = ((Rect)(ref rect)).width * 0.95f;
}
rectTransform.SetSizeWithCurrentAnchors((Axis)0, Mathf.Min(x + 16f, num));
}
RectMask2D componentInParent2 = ((Component)uE_UI_NameText).GetComponentInParent<RectMask2D>();
object[] obj = new object[4] { uE_UI_NameText.text, x, width, null };
rect = rectTransform.rect;
obj[3] = ((Rect)(ref rect)).width;
ModPreferences.Log(string.Format("[BiggerLobby] 观战名字 '{0}':需要 {1:0.#},原宽 {2:0.#} -> {3:0.#},", obj) + "mask=" + (((Object)(object)componentInParent2 != (Object)null) ? ((Object)componentInParent2).name : "none"));
}
}
[HarmonyPatch]
internal static class SurvivalResultPatch
{
internal const int UiSlots = 16;
private const string GridName = "BiggerLobbyResultGrid";
private static Type? _type;
private static FieldInfo? _columnsField;
private static FieldInfo? _countField;
private static MethodInfo? _patchResult;
private static readonly Dictionary<int, List<UIPrefab_SurvivalResultPlayerColumn>> ExtraColumns = new Dictionary<int, List<UIPrefab_SurvivalResultPlayerColumn>>();
private static object? _lastInstance;
private static UIPrefab_SurvivalResultPlayerColumn[]? _lastColumns;
private static RectTransform? _lastArea;
private static int _lastVisible;
private static float _lastTopOffset;
private static object? _offsetInstance;
private static float _autoTopOffset;
private static MethodBase? TargetMethod()
{
_type = AccessTools.TypeByName("UIPrefab_SurvivalResult");
if (_type == null)
{
MelonLogger.Error("[BiggerLobby] 找不到类型 UIPrefab_SurvivalResult,结算界面补丁未应用。");
return null;
}
_columnsField = AccessTools.Field(_type, "_playerColumns");
_countField = AccessTools.Field(_type, "_resultCount");
_patchResult = AccessTools.Method(typeof(UIPrefab_SurvivalResultPlayerColumn), "PatchResult", (Type[])null, (Type[])null);
MethodInfo methodInfo = AccessTools.Method(_type, "PatchParameter", (Type[])null, (Type[])null);
MelonLogger.Msg("[BiggerLobby] 结算补丁目标:" + _type.FullName + ".PatchParameter -> " + ((methodInfo == null) ? "null" : "ok") + ", columnsField=" + ((_columnsField == null) ? "null" : "ok") + ", patchResult=" + ((_patchResult == null) ? "null" : "ok"));
return methodInfo;
}
internal static object[]? BuildDebugParameters(int slots)
{
if (_type == null)
{
return null;
}
Type nestedType = _type.GetNestedType("eActorSurvivalState", BindingFlags.Public | BindingFlags.NonPublic);
if (nestedType == null)
{
return null;
}
List<object> list = new List<object> { 1, 1, true, slots };
for (int i = 0; i < slots; i++)
{
list.Add($"PLAYER {i + 1:D2}");
list.Add(Enum.ToObject(nestedType, i % 3));
list.Add((object)(AwardType)0);
}
list.Add(0);
return list.ToArray();
}
private static void Postfix(object __instance, object[] __args)
{
if (!ModPreferences.Enabled || __args == null || __args.Length == 0 || !(__args[0] is object[] array) || array.Length < 4)
{
return;
}
try
{
Apply(__instance, array);
}
catch (Exception arg)
{
MelonLogger.Error($"[BiggerLobby] 结算界面扩展失败:{arg}");
}
}
internal static void OnShown(object instance)
{
if (ModPreferences.Enabled && instance == _lastInstance && _lastColumns != null && (Object)(object)_lastArea != (Object)null && _lastVisible > 0)
{
ScheduleLayout(_lastArea, _lastColumns, _lastVisible, _lastTopOffset);
}
}
private static void Apply(object instance, object[] parameters)
{
//IL_00be: 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_030b: Unknown result type (might be due to invalid IL or missing references)
if (_columnsField == null)
{
MelonLogger.Warning("[BiggerLobby] _playerColumns 字段未解析,跳过结算扩展。");
return;
}
if (!(_columnsField.GetValue(instance) is UIPrefab_SurvivalResultPlayerColumn[] array) || array.Length == 0)
{
MelonLogger.Warning("[BiggerLobby] 结算列数组为空,跳过结算扩展。");
return;
}
int num = Mathf.Min(ModPreferences.MaxPlayers, 16);
int num2 = (int)parameters[3];
if (num2 > num)
{
MelonLogger.Warning($"[BiggerLobby] 结算玩家数 {num2} 超过界面上限 {num},只显示前 {num} 个。");
num2 = num;
}
int num3 = (ModPreferences.DebugPlaceholders ? num : Mathf.Min(num2, num));
if (num3 <= 4)
{
ModPreferences.Log($"[BiggerLobby] 结算玩家数 {num3} <= 4,保持原版排版。");
return;
}
object obj = ((instance is Component) ? instance : null);
Transform obj2 = ((obj != null) ? ((Component)obj).transform : null);
RectTransform root = (RectTransform)(object)((obj2 is RectTransform) ? obj2 : null);
Vector2 val = MeasureNatural(array);
if (_offsetInstance != instance)
{
_autoTopOffset = ComputeAutoTopOffset(root, array);
_offsetInstance = instance;
ModPreferences.Log($"[BiggerLobby] 原版结算列顶部偏移 = {_autoTopOffset:0.#}px");
}
float num4 = _autoTopOffset + ModPreferences.ResultTopOffset;
object obj3 = ((instance is Component) ? instance : null);
UIPrefab_SurvivalResultPlayerColumn[] array2 = EnsureColumns(array, num, (obj3 != null) ? ((Object)obj3).GetInstanceID() : 0);
_columnsField.SetValue(instance, array2);
RectTransform val2 = EnsureGridRoot(instance, array2);
if ((Object)(object)val2 == (Object)null)
{
MelonLogger.Warning("[BiggerLobby] 无法创建结算网格容器,退回原容器排布。");
}
Type stateType = ((_patchResult != null) ? _patchResult.GetParameters()[1].ParameterType : null);
for (int i = 0; i < array2.Length; i++)
{
UIPrefab_SurvivalResultPlayerColumn val3 = array2[i];
if (!((Object)(object)val3 == (Object)null))
{
if ((Object)(object)val2 != (Object)null && (Object)(object)((Component)val3).transform.parent != (Object)(object)val2)
{
((Component)val3).transform.SetParent((Transform)(object)val2, false);
}
if (i < num2)
{
string name = parameters[3 * i + 4]?.ToString() ?? string.Empty;
int state = (int)parameters[3 * i + 5];
object award = parameters[3 * i + 6] ?? ((object)(AwardType)0);
PatchColumn(val3, name, stateType, state, award);
((Component)val3).gameObject.SetActive(true);
}
else if (ModPreferences.DebugPlaceholders && i < num)
{
PatchColumn(val3, $"PLAYER {i + 1:D2}", stateType, 0, (object)(AwardType)0);
((Component)val3).gameObject.SetActive(true);
}
else
{
((Component)val3).gameObject.SetActive(false);
}
}
}
_countField?.SetValue(instance, num3);
_lastInstance = instance;
_lastColumns = array2;
_lastArea = (RectTransform?)(((Object)(object)val2 != (Object)null) ? ((object)val2) : ((object)/*isinst with value type is only supported in some contexts*/));
_lastVisible = num3;
_lastTopOffset = num4;
MelonLogger.Msg($"[BiggerLobby] 结算界面:playerCount={num2}, 列={array2.Length}, 显示={num3}, " + string.Format("容器={0}, 单元={1}, 顶部偏移={2:0.#}px ", ((Object)(object)_lastArea != (Object)null) ? ((Object)_lastArea).name : "null", val, num4) + $"(原版 {_autoTopOffset:0.#} + 配置 {ModPreferences.ResultTopOffset:0.#})");
if ((Object)(object)_lastArea != (Object)null)
{
ScheduleLayout(_lastArea, array2, num3, num4);
}
}
private static Vector2 MeasureNatural(UIPrefab_SurvivalResultPlayerColumn[] columns)
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: 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_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)
RectTransform val = (RectTransform)(((Object)(object)columns[0] != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
Vector2 val2;
if (!((Object)(object)val != (Object)null))
{
val2 = Vector2.zero;
}
else
{
Rect rect = val.rect;
val2 = ((Rect)(ref rect)).size;
}
Vector2 val3 = val2;
if (val3.x < 1f || val3.y < 1f)
{
((Vector2)(ref val3))..ctor(200f, 240f);
}
return val3;
}
private static float ComputeAutoTopOffset(RectTransform? root, UIPrefab_SurvivalResultPlayerColumn[] columns)
{
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: 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)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: 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_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)root == (Object)null)
{
return 0f;
}
float num = float.MinValue;
Rect rect;
foreach (UIPrefab_SurvivalResultPlayerColumn val in columns)
{
RectTransform val2 = (RectTransform)(((Object)(object)val != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
if (!((Object)(object)val2 == (Object)null))
{
rect = val2.rect;
Vector3 val3 = ((Transform)val2).TransformPoint(new Vector3(0f, ((Rect)(ref rect)).yMax, 0f));
Vector3 val4 = ((Transform)root).InverseTransformPoint(val3);
if (val4.y > num)
{
num = val4.y;
}
}
}
if (num == float.MinValue)
{
return 0f;
}
rect = root.rect;
float num2 = ((Rect)(ref rect)).yMax - num;
rect = root.rect;
return Mathf.Clamp(num2, 0f, Mathf.Max(0f, ((Rect)(ref rect)).height));
}
private static RectTransform? EnsureGridRoot(object instance, UIPrefab_SurvivalResultPlayerColumn[] columns)
{
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Expected O, but got Unknown
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: 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_0094: 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_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: Expected O, but got Unknown
object obj = ((instance is Component) ? instance : null);
Transform obj2 = ((obj != null) ? ((Component)obj).transform : null);
RectTransform val = (RectTransform)(object)((obj2 is RectTransform) ? obj2 : null);
if ((Object)(object)val == (Object)null)
{
if (!((Object)(object)columns[0] != (Object)null))
{
return null;
}
Transform parent = ((Component)columns[0]).transform.parent;
return (RectTransform?)(object)((parent is RectTransform) ? parent : null);
}
Transform obj3 = ((Transform)val).Find("BiggerLobbyResultGrid");
RectTransform val2 = (RectTransform)(object)((obj3 is RectTransform) ? obj3 : null);
if (val2 != null)
{
return val2;
}
GameObject val3 = new GameObject("BiggerLobbyResultGrid", new Type[1] { typeof(RectTransform) });
RectTransform val4 = (RectTransform)val3.transform;
((Transform)val4).SetParent((Transform)(object)val, false);
val4.anchorMin = Vector2.zero;
val4.anchorMax = Vector2.one;
val4.offsetMin = Vector2.zero;
val4.offsetMax = Vector2.zero;
((Transform)val4).SetAsLastSibling();
val3.AddComponent<LayoutElement>().ignoreLayout = true;
string name = ((Object)val).name;
Rect rect = val.rect;
ModPreferences.Log($"[BiggerLobby] 创建结算网格容器,root='{name}' rect={((Rect)(ref rect)).size}");
return val4;
}
private static UIPrefab_SurvivalResultPlayerColumn[] EnsureColumns(UIPrefab_SurvivalResultPlayerColumn[] columns, int slots, int key)
{
if (columns.Length >= slots)
{
return columns;
}
UIPrefab_SurvivalResultPlayerColumn val = columns[^1];
if ((Object)(object)val == (Object)null)
{
return columns;
}
Transform parent = ((Component)val).transform.parent;
if (!ExtraColumns.TryGetValue(key, out List<UIPrefab_SurvivalResultPlayerColumn> value) || value == null)
{
value = new List<UIPrefab_SurvivalResultPlayerColumn>();
ExtraColumns[key] = value;
}
value.RemoveAll((UIPrefab_SurvivalResultPlayerColumn column) => (Object)(object)column == (Object)null);
while (columns.Length + value.Count < slots)
{
GameObject obj = Object.Instantiate<GameObject>(((Component)val).gameObject, parent);
((Object)obj).name = ((Object)((Component)val).gameObject).name + "_" + (columns.Length + value.Count + 1);
obj.SetActive(false);
UIPrefab_SurvivalResultPlayerColumn component = obj.GetComponent<UIPrefab_SurvivalResultPlayerColumn>();
if ((Object)(object)component == (Object)null)
{
MelonLogger.Warning("[BiggerLobby] 克隆结算列失败:缺少 UIPrefab_SurvivalResultPlayerColumn。");
break;
}
value.Add(component);
}
List<UIPrefab_SurvivalResultPlayerColumn> list = new List<UIPrefab_SurvivalResultPlayerColumn>(slots);
list.AddRange(columns);
list.AddRange(value.GetRange(0, Mathf.Max(0, Mathf.Min(value.Count, slots - columns.Length))));
return list.ToArray();
}
private static void PatchColumn(UIPrefab_SurvivalResultPlayerColumn column, string name, Type? stateType, int state, object award)
{
if (_patchResult == null || stateType == null)
{
return;
}
try
{
_patchResult.Invoke(column, new object[3]
{
name,
Enum.ToObject(stateType, state),
award
});
}
catch (Exception ex)
{
MelonLogger.Warning("[BiggerLobby] 写入结算列失败:" + (ex.InnerException?.Message ?? ex.Message));
}
}
private static void ScheduleLayout(RectTransform area, UIPrefab_SurvivalResultPlayerColumn[] columns, int visible, float topOffset)
{
//IL_001f: 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_0053: Unknown result type (might be due to invalid IL or missing references)
if (visible <= 4)
{
UiUtil.RestoreLayout(area);
return;
}
int columns2 = Mathf.Clamp(Mathf.Min(ModPreferences.ResultColumns, visible), 1, 8);
Vector2 natural = MeasureNatural(columns);
List<RectTransform> items = ((IEnumerable<UIPrefab_SurvivalResultPlayerColumn>)columns).Select((Func<UIPrefab_SurvivalResultPlayerColumn, RectTransform>)delegate(UIPrefab_SurvivalResultPlayerColumn column)
{
if (!((Object)(object)column != (Object)null))
{
return (RectTransform)null;
}
Transform transform = ((Component)column).transform;
return (RectTransform)(object)((transform is RectTransform) ? transform : null);
}).ToList();
UiGridLayout.Schedule(area, items, visible, natural, columns2, ModPreferences.ResultScale, area, topOffset);
}
}
[HarmonyPatch]
internal static class SurvivalResultShowPatch
{
private static MethodBase? TargetMethod()
{
Type type = AccessTools.TypeByName("UIPrefab_SurvivalResult");
if (!(type == null))
{
return AccessTools.Method(type, "OnShow", (Type[])null, (Type[])null);
}
return null;
}
private static void Postfix(object __instance)
{
SurvivalResultPatch.OnShown(__instance);
}
}
}