using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using FishNet.Broadcast; using FishNet.Connection; using FishNet.Managing; using FishNet.Object; using FishNet.Serializing; using FishNet.Transporting; using HarmonyLib; using HowToFish.MoreHead.Bootstrap; using HowToFish.MoreHead.Content; using HowToFish.MoreHead.Diagnostics; using HowToFish.MoreHead.Networking; using HowToFish.MoreHead.Persistence; using HowToFish.MoreHead.Players; using HowToFish.MoreHead.Visuals; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; [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("HTFMoreHead")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Custom cosmetic framework for How to Fish")] [assembly: AssemblyFileVersion("0.6.3.0")] [assembly: AssemblyInformationalVersion("0.6.3+06517c320af77ef3e7ad1f01838d4b612fc44623")] [assembly: AssemblyProduct("HTFMoreHead")] [assembly: AssemblyTitle("HTFMoreHead")] [assembly: AssemblyVersion("0.6.3.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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 HowToFish.MoreHead { [BepInPlugin("com.htfmodding.morehead", "HTF MoreHead", "0.6.3")] public sealed class MoreHeadPlugin : BaseUnityPlugin { private const int MainThreadQueueCapacity = 128; private const int MainThreadActionsPerFrame = 32; private Harmony _harmony; private MainThreadDispatcher _dispatcher; private BoundedLog _boundedLog; private PlayerProbeTracker _tracker; private CosmeticCatalog _catalog; private LocalLoadoutStore _localLoadoutStore; private LocalSkinPreviewVisuals _localSkinPreviewVisuals; private PlayerAppearanceService _appearanceService; private CosmeticNetworkService _networkService; private ConfigEntry _enableStage0Probe; private ConfigEntry _probeTimeoutSeconds; private bool _shuttingDown; private int _probeDisableCleanupRequested; private int _probeSettingChangePending; private int _requestedProbeEnabled; internal static MoreHeadPlugin Instance { get; private set; } private void Awake() { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Expected O, but got Unknown Instance = this; _dispatcher = new MainThreadDispatcher(128); _boundedLog = new BoundedLog(((BaseUnityPlugin)this).Logger, 256); _enableStage0Probe = ((BaseUnityPlugin)this).Config.Bind("Diagnostics", "EnableStage0Probe", false, "Legacy development probe. Production 0.6.0 forces this off."); _enableStage0Probe.Value = false; _probeTimeoutSeconds = ((BaseUnityPlugin)this).Config.Bind("Diagnostics", "ProbeTimeoutSeconds", 2f, new ConfigDescription("Maximum time to reconcile Player and PlayerSkin lifecycle signals.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 10f), Array.Empty())); _requestedProbeEnabled = (_enableStage0Probe.Value ? 1 : 0); _tracker = new PlayerProbeTracker(((BaseUnityPlugin)this).Logger, _boundedLog, _probeTimeoutSeconds.Value); _catalog = new CosmeticCatalog(((BaseUnityPlugin)this).Logger, _boundedLog); _catalog.LoadAll(Paths.PluginPath); _localLoadoutStore = new LocalLoadoutStore(((BaseUnityPlugin)this).Logger, Path.Combine(Paths.ConfigPath, "HTFMoreHead", "loadout.json")); _localLoadoutStore.Load(); _localSkinPreviewVisuals = new LocalSkinPreviewVisuals(((BaseUnityPlugin)this).Logger, _catalog, _localLoadoutStore); _appearanceService = new PlayerAppearanceService(((BaseUnityPlugin)this).Logger, _boundedLog, _catalog); _networkService = new CosmeticNetworkService(((BaseUnityPlugin)this).Logger, _boundedLog, _catalog, _localLoadoutStore, _appearanceService); _localSkinPreviewVisuals.SelectionCommitted += OnLocalSelectionCommitted; try { RuntimeFingerprint.LogCurrent(((BaseUnityPlugin)this).Logger, ((BaseUnityPlugin)this).Info.Location); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"[HTFMoreHead][Stage0][FINGERPRINT] Runtime fingerprint failed safely: {arg}"); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"[HTFMoreHead][CREDITS] Thanks to Masaicker, creator of MoreHead, for permission to reference the original project: https://github.com/Masaicker/repo-MoreHead"); if (!ValidatePatchTargets()) { ((BaseUnityPlugin)this).Logger.LogError((object)"[HTFMoreHead][Stage0][PATCH] Required lifecycle methods were not found; stage 0 probes are disabled for this game build."); return; } SceneManager.sceneUnloaded += OnSceneUnloaded; _harmony = new Harmony("com.htfmodding.morehead"); try { _harmony.PatchAll(Assembly.GetExecutingAssembly()); } catch (Exception arg2) { SceneManager.sceneUnloaded -= OnSceneUnloaded; try { _harmony.UnpatchSelf(); } catch (Exception arg3) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[HTFMoreHead][Stage0][PATCH] Cleanup after patch failure also failed: " + $"{arg3}")); } _harmony = null; ((BaseUnityPlugin)this).Logger.LogError((object)$"[HTFMoreHead][Stage0][PATCH] Lifecycle probes could not be installed: {arg2}"); return; } _enableStage0Probe.SettingChanged += OnStage0ProbeSettingChanged; ((BaseUnityPlugin)this).Logger.LogInfo((object)("[HTFMoreHead][Stage0][READY] Lifecycle probes installed. " + $"Enabled={_enableStage0Probe.Value}, MainThreadId={_dispatcher.MainThreadId}, " + $"Timeout={_probeTimeoutSeconds.Value:F1}s.")); } private void Update() { if (_shuttingDown || _dispatcher == null) { return; } try { ApplyPendingProbeSettingChange(); _dispatcher.Drain(32, delegate(Exception ex) { ReportPatchException("MainThreadQueue", ex); }); int num = _dispatcher.ConsumeDroppedCount(); if (num > 0) { _boundedLog.WarningOnce("main-thread-queue-overflow", "[HTFMoreHead][Stage0][THREAD] Main-thread queue overflowed; " + $"DroppedActions={num}, Capacity={128}."); } if (_enableStage0Probe != null && _enableStage0Probe.Value) { _tracker?.Tick(); } _networkService?.Tick(); } catch (Exception exception) { ReportPatchException("Update", exception); } } private void OnDestroy() { if (_shuttingDown) { return; } _shuttingDown = true; SceneManager.sceneUnloaded -= OnSceneUnloaded; if (_enableStage0Probe != null) { _enableStage0Probe.SettingChanged -= OnStage0ProbeSettingChanged; } try { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogWarning((object)$"[HTFMoreHead][Stage0][SHUTDOWN] Harmony unpatch failed: {arg}"); } try { if (_localSkinPreviewVisuals != null) { _localSkinPreviewVisuals.SelectionCommitted -= OnLocalSelectionCommitted; } _networkService?.ClearAndDetach(); _appearanceService?.ClearAll(); _localSkinPreviewVisuals?.Dispose(); _tracker?.ClearAll("PluginDestroy"); } catch (Exception arg2) { ((BaseUnityPlugin)this).Logger.LogWarning((object)$"[HTFMoreHead][Stage0][SHUTDOWN] Tracker cleanup failed: {arg2}"); } finally { _dispatcher?.Clear(); _harmony = null; _tracker = null; _networkService = null; _appearanceService = null; _localSkinPreviewVisuals = null; _localLoadoutStore = null; _catalog?.UnloadAll(); _catalog = null; _dispatcher = null; if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } } internal void DispatchPlayerStarted(Player player) { DispatchInfrastructure("PlayerStart", delegate { _appearanceService?.NotifyPlayerReady(player); _networkService?.NotifyPlayerReady(player); if (_enableStage0Probe != null && _enableStage0Probe.Value) { _tracker?.NotifyPlayerStarted(player); } }); } internal void DispatchSkinStarted(PlayerSkin skin) { Dispatch("SkinStart", delegate { _tracker?.NotifySkinStarted(skin); }); } internal void DispatchPlayerStopping(Player player) { DispatchInfrastructure("PlayerStop", delegate { _appearanceService?.NotifyPlayerStopping(player); if (_enableStage0Probe != null && _enableStage0Probe.Value) { _tracker?.NotifyPlayerStopping(player); } }); } internal void DispatchLocalSkinPreview(bool visible) { DispatchInfrastructure("LocalSkinPreview", delegate { if (visible) { _localSkinPreviewVisuals?.Show(); } else { _localSkinPreviewVisuals?.CloseAndSave(); } }); } internal void DispatchLocalSkinReady() { DispatchInfrastructure("LocalSkinReady", delegate { _localSkinPreviewVisuals?.RestorePersistedSelection(); }); } internal bool HandleNativeCosmeticArrow(CosmeticSlot slot, int amount) { try { return _localSkinPreviewVisuals != null && _localSkinPreviewVisuals.HandleArrow(slot, amount); } catch (Exception exception) { ReportPatchException("NativeCosmeticArrowPrefix", exception); return false; } } internal void NotifyNativeCosmeticArrowCompleted(CosmeticSlot slot, int amount, byte beforeIndex, byte afterIndex) { try { _localSkinPreviewVisuals?.OnNativeArrowCompleted(slot, amount, beforeIndex, afterIndex); } catch (Exception exception) { ReportPatchException("NativeCosmeticArrowPostfix", exception); } } internal void NotifyActiveCosmeticSlot(CosmeticSlot slot) { try { _localSkinPreviewVisuals?.SetActiveSlot(slot); } catch (Exception exception) { ReportPatchException("ActiveCosmeticSlot", exception); } } internal void ReportPatchException(string source, Exception exception) { if (!_shuttingDown && exception != null) { _boundedLog?.ErrorOnce("exception-" + source, $"[HTFMoreHead][Stage0][ERROR] {source} probe failed safely: {exception}"); } } private void Dispatch(string source, Action action) { if (_enableStage0Probe != null && _enableStage0Probe.Value) { DispatchInfrastructure(source, action); } } private void DispatchInfrastructure(string source, Action action) { if (_shuttingDown || _dispatcher == null || action == null) { return; } _dispatcher.RunOrEnqueue(delegate { try { action(); } catch (Exception exception) { ReportPatchException(source, exception); } }); } private void OnSceneUnloaded(Scene scene) { DispatchInfrastructure("SceneUnloaded", delegate { _tracker?.RequestPrune(); _appearanceService?.PruneDestroyedPlayers(); }); } private void OnLocalSelectionCommitted(CosmeticLoadout loadout) { _networkService?.RequestLocalEquip(loadout); } private void OnStage0ProbeSettingChanged(object sender, EventArgs eventArgs) { bool flag = _enableStage0Probe != null && _enableStage0Probe.Value; Volatile.Write(ref _requestedProbeEnabled, flag ? 1 : 0); if (!flag) { Interlocked.Exchange(ref _probeDisableCleanupRequested, 1); } Interlocked.Exchange(ref _probeSettingChangePending, 1); } private void ApplyPendingProbeSettingChange() { if (Interlocked.Exchange(ref _probeDisableCleanupRequested, 0) != 0) { _tracker?.ClearAll("ProbeDisabled"); } if (Interlocked.Exchange(ref _probeSettingChangePending, 0) != 0) { bool flag = Volatile.Read(in _requestedProbeEnabled) != 0; ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[HTFMoreHead][Stage0][CONFIG] EnableStage0Probe={flag}."); } } private bool ValidatePatchTargets() { MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(Player), "OnStartClient", Type.EmptyTypes, (Type[])null); MethodInfo methodInfo2 = AccessTools.DeclaredMethod(typeof(PlayerSkin), "OnStartClient", Type.EmptyTypes, (Type[])null); MethodInfo methodInfo3 = AccessTools.DeclaredMethod(typeof(Player), "OnStopClient", Type.EmptyTypes, (Type[])null); bool result = methodInfo != null && methodInfo2 != null && methodInfo3 != null; ((BaseUnityPlugin)this).Logger.LogInfo((object)($"[HTFMoreHead][Stage0][PATCH_CHECK] PlayerStart={methodInfo != null}, " + $"SkinStart={methodInfo2 != null}, PlayerStop={methodInfo3 != null}, " + $"ThreadId={Thread.CurrentThread.ManagedThreadId}.")); return result; } } internal static class RuntimeMetadata { internal const string PluginGuid = "com.htfmodding.morehead"; internal const string PluginName = "HTF MoreHead"; internal const string PluginVersion = "0.6.3"; internal const byte ProtocolVersion = 3; internal const string ExpectedGameVersion = "1.0.11"; internal const string ExpectedAssemblyCSharpSha256 = "349126D96D66B290341CBDA1628C746995210097C1A415652FA8961D9A20CFA6"; internal const string ExpectedAssemblyCSharpMvid = "a79eca11-9a20-409b-ab30-d5f7ec1cd857"; internal const string ExpectedFishNetSha256 = "71AC44A95C7AF0CD9333C851F41792EF342B373AF26E10F69795E02C9550C61A"; internal const string ExpectedFishNetMvid = "5254e175-6a7c-489e-beb8-55179113ab9f"; } } namespace HowToFish.MoreHead.Visuals { internal sealed class LocalSkinPreviewVisuals { private static readonly CosmeticSlot[] AllSlots = new CosmeticSlot[3] { CosmeticSlot.Hat, CosmeticSlot.Accessory, CosmeticSlot.Outfit }; private static readonly FieldInfo LocalSkinInstanceField = AccessTools.Field(typeof(LocalSkin), "_instance"); private static readonly FieldInfo LocalHatRendererField = AccessTools.Field(typeof(LocalSkin), "_hatRenderer"); private static readonly FieldInfo LocalAccessoryRendererField = AccessTools.Field(typeof(LocalSkin), "_accessoryRenderer"); private static readonly FieldInfo LocalOutfitRendererField = AccessTools.Field(typeof(LocalSkin), "_outfitRenderer"); private static readonly FieldInfo LocalHatIndexField = AccessTools.Field(typeof(LocalSkin), "k__BackingField"); private static readonly FieldInfo LocalAccessoryIndexField = AccessTools.Field(typeof(LocalSkin), "k__BackingField"); private static readonly FieldInfo LocalOutfitIndexField = AccessTools.Field(typeof(LocalSkin), "k__BackingField"); private static readonly FieldInfo CanvasManagerInstanceField = AccessTools.Field(typeof(CanvasManager), "_instance"); private static readonly FieldInfo VersionTextField = AccessTools.Field(typeof(CanvasManager), "_versionText"); private readonly ManualLogSource _logger; private readonly CosmeticCatalog _catalog; private readonly LocalLoadoutStore _loadoutStore; private readonly GameObject[] _instances = (GameObject[])(object)new GameObject[3]; private readonly int[] _customIndices = new int[3] { -1, -1, -1 }; private readonly TextMeshProUGUI[] _selectionTitles = (TextMeshProUGUI[])(object)new TextMeshProUGUI[3]; private readonly bool[] _selectorFallbackLogged = new bool[3]; private CosmeticLoadout _selected; private bool _previewOpen; internal event Action SelectionCommitted; internal LocalSkinPreviewVisuals(ManualLogSource logger, CosmeticCatalog catalog, LocalLoadoutStore loadoutStore) { _logger = logger ?? throw new ArgumentNullException("logger"); _catalog = catalog ?? throw new ArgumentNullException("catalog"); _loadoutStore = loadoutStore ?? throw new ArgumentNullException("loadoutStore"); _selected = _loadoutStore.GetLoadout(); } internal void Show() { _previewOpen = true; DestroyAllCustom(); _selected = _loadoutStore.GetLoadout(); ApplySavedSelections(); RefreshSelectionTitles(); } internal void RestorePersistedSelection() { _selected = _loadoutStore.GetLoadout(); DestroyAllCustom(); ApplySavedSelections(); HideSelectionTitles(); _logger.LogInfo((object)("[HTFMoreHead][LOADOUT] Restored Hat='" + DisplayId(_selected.HatId) + "', Accessory='" + DisplayId(_selected.AccessoryId) + "', Outfit='" + DisplayId(_selected.OutfitId) + "'.")); } internal void SetActiveSlot(CosmeticSlot slot) { if (_previewOpen) { RefreshSelectionTitle(slot); } } internal bool HandleArrow(CosmeticSlot slot, int amount) { int count = _catalog.GetCount(slot); if (!_previewOpen || _customIndices[(uint)slot] < 0 || count == 0 || amount == 0) { return false; } int num = ((amount > 0) ? 1 : (-1)); int num2 = _customIndices[(uint)slot] + num; if (num2 >= 0 && num2 < count) { _customIndices[(uint)slot] = num2; ShowDefinition(slot, _catalog.GetAt(slot, num2), showTitle: true); ColorPicker.UpdateSelectedPicker(); return true; } ExitCustomToNative(slot, num); return true; } internal void OnNativeArrowCompleted(CosmeticSlot slot, int amount, byte beforeIndex, byte afterIndex) { int count = _catalog.GetCount(slot); if (_previewOpen && _customIndices[(uint)slot] < 0 && count != 0 && amount != 0) { _selected.Set(slot, string.Empty); bool flag = amount > 0 && afterIndex <= beforeIndex; bool flag2 = amount < 0 && afterIndex >= beforeIndex; if (!flag && !flag2) { RefreshSelectionTitle(slot); return; } _customIndices[(uint)slot] = ((!flag) ? (count - 1) : 0); ShowDefinition(slot, _catalog.GetAt(slot, _customIndices[(uint)slot]), showTitle: true); _logger.LogInfo((object)($"[HTFMoreHead][NATIVE_LIST] Entered custom {slot}. Direction={amount}, " + $"NativeBefore={beforeIndex}, NativeAfter={afterIndex}, CustomIndex={_customIndices[(uint)slot]}.")); } } internal void CloseAndSave() { _previewOpen = false; HideSelectionTitles(); _loadoutStore.Save(_selected); this.SelectionCommitted?.Invoke(_selected.Clone()); } internal void Dispose() { _loadoutStore.Save(_selected); _previewOpen = false; DestroyAllCustom(); DestroySelectionTitles(); } private void ApplySavedSelections() { for (int i = 0; i < AllSlots.Length; i++) { CosmeticSlot cosmeticSlot = AllSlots[i]; int index = _catalog.GetIndex(cosmeticSlot, _selected.Get(cosmeticSlot)); _customIndices[(uint)cosmeticSlot] = index; if (index >= 0) { ShowDefinition(cosmeticSlot, _catalog.GetAt(cosmeticSlot, index), showTitle: false); } else { _selected.Set(cosmeticSlot, string.Empty); } } } private void ShowDefinition(CosmeticSlot slot, CosmeticDefinition definition, bool showTitle) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) if (definition == null || definition.Slot != slot) { return; } DestroyCustom(slot); SetNativeBackingToNone(slot); Transform val = ResolvePreviewTarget(slot); if ((Object)(object)val == (Object)null) { _logger.LogWarning((object)$"[HTFMoreHead][PREVIEW] {slot} preview target is unavailable."); return; } GameObject val2 = Object.Instantiate(definition.Prefab, val, false); ((Object)val2).name = "HTFMoreHead_Preview_" + definition.Id; val2.transform.localPosition = definition.Entry.localPosition.ToVector3(); val2.transform.localEulerAngles = definition.Entry.localEulerAngles.ToVector3(); val2.transform.localScale = definition.Entry.localScale.ToVector3(); SetLayerRecursively(val2.transform, ((Component)val).gameObject.layer); _instances[(uint)slot] = val2; _selected.Set(slot, definition.Id); if (showTitle) { ShowSelectionTitle(slot, definition); } } private void RefreshSelectionTitles() { for (int i = 0; i < AllSlots.Length; i++) { RefreshSelectionTitle(AllSlots[i]); } } private void RefreshSelectionTitle(CosmeticSlot slot) { int index = _customIndices[(uint)slot]; ShowSelectionTitle(slot, _catalog.GetAt(slot, index)); } private void ShowSelectionTitle(CosmeticSlot slot, CosmeticDefinition definition) { if (definition == null) { HideSelectionTitle(slot); return; } TextMeshProUGUI val = EnsureSelectionTitle(slot); if (!((Object)(object)val == (Object)null)) { string text = (string.IsNullOrWhiteSpace(definition.Entry.displayName) ? definition.Id : definition.Entry.displayName.Trim()); string text2 = definition.AuthorName?.Trim(); ((TMP_Text)val).text = (string.IsNullOrEmpty(text2) ? text : (text + " By " + text2)); ((Component)val).gameObject.SetActive(true); ((TMP_Text)val).transform.SetAsLastSibling(); } } private TextMeshProUGUI EnsureSelectionTitle(CosmeticSlot slot) { //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) int num = (int)slot; if ((Object)(object)_selectionTitles[num] != (Object)null) { AlignSelectionTitle(slot, _selectionTitles[num]); return _selectionTitles[num]; } object obj = CanvasManagerInstanceField?.GetValue(null); TextMeshProUGUI val = (TextMeshProUGUI)((obj != null) ? /*isinst with value type is only supported in some contexts*/: null); Canvas val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponentInParent() : null); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { _logger.LogWarning((object)"[HTFMoreHead][TITLE] Full-screen Canvas is unavailable."); return null; } val2 = val2.rootCanvas; GameObject val3 = new GameObject("HTFMoreHead_" + slot.ToString() + "SelectionTitle", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(TextMeshProUGUI) }) { layer = ((Component)val).gameObject.layer }; val3.transform.SetParent(((Component)val2).transform, false); TextMeshProUGUI component = val3.GetComponent(); _selectionTitles[num] = component; ((TMP_Text)component).font = ((TMP_Text)val).font; ((TMP_Text)component).fontSharedMaterial = ((TMP_Text)val).fontSharedMaterial; ((TMP_Text)component).fontSize = 30f; ((TMP_Text)component).fontStyle = (FontStyles)1; ((TMP_Text)component).alignment = (TextAlignmentOptions)513; ((TMP_Text)component).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)component).overflowMode = (TextOverflowModes)1; ((Graphic)component).raycastTarget = false; ((TMP_Text)component).enableVertexGradient = true; ((TMP_Text)component).colorGradient = new VertexGradient(new Color(1f, 0.25f, 0.35f), new Color(1f, 0.85f, 0.2f), new Color(0.2f, 0.9f, 1f), new Color(0.85f, 0.3f, 1f)); AlignSelectionTitle(slot, component); return component; } private void AlignSelectionTitle(CosmeticSlot slot, TextMeshProUGUI title) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) RectTransform rectTransform = ((TMP_Text)title).rectTransform; Canvas componentInParent = ((Component)title).GetComponentInParent(); Canvas val = ((componentInParent != null) ? componentInParent.rootCanvas : null); if ((Object)(object)val != (Object)null && TryGetSelectorRightEdge(slot, val, out var localRightEdge)) { Transform transform = ((Component)val).transform; RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null); float num; if (!((Object)(object)val2 != (Object)null)) { num = 340f; } else { Rect rect = val2.rect; num = ((Rect)(ref rect)).xMax - localRightEdge.x - 18f; } float num2 = num; rectTransform.anchorMin = new Vector2(0.5f, 0.5f); rectTransform.anchorMax = new Vector2(0.5f, 0.5f); rectTransform.pivot = new Vector2(0f, 0.5f); rectTransform.anchoredPosition = localRightEdge + new Vector2(18f, 0f); rectTransform.sizeDelta = new Vector2(Mathf.Clamp(num2, 180f, 420f), 52f); } else { ApplyFallbackTitlePosition(slot, rectTransform); if (!_selectorFallbackLogged[(uint)slot]) { _selectorFallbackLogged[(uint)slot] = true; _logger.LogWarning((object)$"[HTFMoreHead][TITLE] Could not resolve native {slot} arrow row; using fallback position."); } } } private static bool TryGetSelectorRightEdge(CosmeticSlot slot, Canvas canvas, out Vector2 localRightEdge) { //IL_0001: 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_0167: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: 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_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012b: 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) localRightEdge = default(Vector2); Transform transform = ((Component)canvas).transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val == (Object)null) { return false; } string selectorMethodName = GetSelectorMethodName(slot); Camera val2 = (((int)canvas.renderMode == 0) ? null : canvas.worldCamera); Button[] array = Object.FindObjectsByType