Decompiled source of Rummage v1.0.0
Rummage.dll
Decompiled 5 days ago
The result has been truncated due to the large size, download it to view full contents!
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.Serialization; using System.Runtime.Serialization.Json; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using I2.Loc; using PerfectRandom.Sulfur.Core; using PerfectRandom.Sulfur.Core.Input; using PerfectRandom.Sulfur.Core.Items; using PerfectRandom.Sulfur.Core.Stats; using PerfectRandom.Sulfur.Core.UI; using PerfectRandom.Sulfur.Core.UI.Inventory; using PerfectRandom.Sulfur.Core.World; using Ryuka.Sulfur.Rummage.Config; using Ryuka.Sulfur.Rummage.Diagnostics; using Ryuka.Sulfur.Rummage.Filter; using Ryuka.Sulfur.Rummage.Game; using Ryuka.Sulfur.Rummage.InputGuard; using Ryuka.Sulfur.Rummage.Localization; using Ryuka.Sulfur.Rummage.Search; using Ryuka.Sulfur.Rummage.Stashes; using Ryuka.Sulfur.Rummage.UserInterface; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.TextCore; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("Ryuka")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+4ec07084b37f1edf901e833c815e5ed503dacb6b")] [assembly: AssemblyProduct("Rummage")] [assembly: AssemblyTitle("Rummage")] [assembly: AssemblyVersion("1.0.0.0")] namespace Ryuka.Sulfur.Rummage { [BepInPlugin("ryuka.sulfur.rummage", "Rummage", "1.0.0")] public sealed class RummagePlugin : BaseUnityPlugin { public const string PluginGuid = "ryuka.sulfur.rummage"; public const string PluginName = "Rummage"; public const string PluginVersion = "1.0.0"; internal static ManualLogSource Log; private Harmony harmony; private PlayerSpawnSource playerSpawnSource; private LanguageWatcher languageWatcher; private RummageController controller; private void Awake() { //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; DiagnosticsConfig diagnostics = new DiagnosticsConfig(((BaseUnityPlugin)this).Config); StashProbe.Initialize(diagnostics); EnchantmentCatalogProbe.Initialize(diagnostics); GameTermProbe.Initialize(diagnostics); DisplayConfig displayConfig = new DisplayConfig(((BaseUnityPlugin)this).Config); InventoryLegend.Initialize(displayConfig.HideInventoryKeyHints); controller = new RummageController(diagnostics, displayConfig); InventoryStatePatch.StateSet += controller.OnInventoryStateSet; InventoryStatePatch.StateSet += GameTermProbe.OnInventoryStateSet; playerSpawnSource = new PlayerSpawnSource(); playerSpawnSource.PlayerSpawned += controller.OnPlayerSpawned; playerSpawnSource.PlayerSpawned += StashProbe.OnPlayerSpawned; playerSpawnSource.PlayerSpawned += EnchantmentCatalogProbe.OnPlayerSpawned; languageWatcher = new LanguageWatcher(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location)); languageWatcher.LanguageChanged += controller.OnLanguageChanged; harmony = new Harmony("ryuka.sulfur.rummage"); int num = 0; num += Patch(typeof(InventoryStatePatch), "search bar, item filter and world markers"); num += Patch(typeof(InventoryLegendPatch), "hiding of the inventory key hints"); num += Patch(typeof(InventoryKeyGuardPatch), "typing guard for inventory keys"); num += Patch(typeof(InventoryCancelGuardPatch), "typing guard for the close inventory keys"); num += Patch(typeof(PlayerStashDoSetupProbePatch), "stash setup probe"); num += Patch(typeof(PlayerStashEnterProbePatch), "stash open probe"); num += Patch(typeof(PlayerStashExitProbePatch), "stash close probe"); num += Patch(typeof(InventoryUISetStateProbePatch), "inventory open/close probe"); Log.LogInfo((object)("Rummage 1.0.0 loaded" + ((num == 0) ? "." : (" with " + num + " patch failure(s), see above.")))); } private void Update() { playerSpawnSource?.Tick(); languageWatcher?.Tick(); controller?.Tick(); } private void LateUpdate() { controller?.LateTick(); } private void OnDestroy() { if (controller != null) { InventoryStatePatch.StateSet -= controller.OnInventoryStateSet; } InventoryStatePatch.StateSet -= GameTermProbe.OnInventoryStateSet; languageWatcher?.Dispose(); languageWatcher = null; playerSpawnSource?.Dispose(); playerSpawnSource = null; controller?.Dispose(); controller = null; StashProbe.Shutdown(); InventoryLegend.Shutdown(); if (harmony != null) { harmony.UnpatchSelf(); harmony = null; } } private int Patch(Type patchClass, string capability) { try { harmony.CreateClassProcessor(patchClass).Patch(); return 0; } catch (Exception ex) { Log.LogError((object)("Could not install " + patchClass.Name + ", the " + capability + " is disabled. " + ex.GetType().Name + ": " + ex.Message)); return 1; } } } } namespace Ryuka.Sulfur.Rummage.UserInterface { internal static class GameFonts { public static TMP_FontAsset Current() { AsyncAssetLoading instance = StaticInstance<AsyncAssetLoading>.Instance; TMP_FontAsset[] array = (((Object)(object)instance != (Object)null) ? instance.fontCache : null); int num = 0; if (array == null || num >= array.Length) { return null; } if ((Object)(object)array[num] == (Object)null) { FontLocalizer.LoadFontCache(); } return array[num]; } } internal sealed class HoverTip : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler { public Action<bool> Hover; public void OnPointerEnter(PointerEventData eventData) { Hover?.Invoke(obj: true); } public void OnPointerExit(PointerEventData eventData) { Hover?.Invoke(obj: false); } private void OnDisable() { Hover?.Invoke(obj: false); } } internal sealed class SearchBar : IDisposable { private sealed class CategoryButton { public ItemCategory Category; public RectTransform Rect; public Image Background; public TextMeshProUGUI Label; } private const float RowHeight = 32f; private const float InputAreaPadding = 1f; private const float InputFontSize = 18f; private const float MinimumInputFontSize = 12f; private const float ButtonRowHeight = 26f; private const float Gap = 4f; private const float MarginAboveGrid = 6f; private const float ClearButtonWidth = 72f; private const float CheckboxIconInset = 3f; private const float CheckboxFallbackInset = 7f; private const float CheckboxIconOffAlpha = 0.45f; private const float TooltipFontSize = 14f; private const float MinimumWidth = 360f; private const int CharacterLimit = 64; private static readonly Vector3[] Corners = (Vector3[])(object)new Vector3[4]; private readonly InventoryFilter filter; private readonly DiagnosticsConfig diagnostics; private readonly DisplayConfig display; private readonly SearchResultsPanel results = new SearchResultsPanel(); private readonly List<CategoryButton> categoryButtons = new List<CategoryButton>(); private readonly List<TextMeshProUGUI> texts = new List<TextMeshProUGUI>(); private GameObject root; private RectTransform rootRect; private TMP_InputField input; private RectTransform inputRect; private RectTransform clearRect; private TextMeshProUGUI placeholder; private TextMeshProUGUI clearLabel; private RectTransform checkboxRect; private Image checkboxBackground; private Image checkboxIcon; private RectTransform tooltipRect; private TextMeshProUGUI tooltipText; private float barWidth; private RectTransform placedFor; private Rect placedForRect; private Vector3 placedForPosition; private bool fontStale; private bool buildFailed; public bool IsFocused { get { if ((Object)(object)input != (Object)null) { return input.isFocused; } return false; } } public bool IsVisible { get { if ((Object)(object)root != (Object)null && root.activeInHierarchy) { return (Object)(object)input != (Object)null; } return false; } } public SearchBar(InventoryFilter filter, DiagnosticsConfig diagnostics, DisplayConfig display) { this.filter = filter; this.diagnostics = diagnostics; this.display = display; filter.Changed += RefreshSelection; display.ResultsPlacement.SettingChanged += OnResultsPlacementChanged; } private void OnResultsPlacementChanged(object sender, EventArgs e) { placedFor = null; } public void FocusInput() { if (IsVisible) { EventSystem current = EventSystem.current; if ((Object)(object)current != (Object)null) { current.SetSelectedGameObject(((Component)input).gameObject); } input.ActivateInputField(); } } public void Tick(InventoryUI ui) { ItemGrid playerBackpackGrid = ui.PlayerBackpackGrid; if ((Object)(object)playerBackpackGrid == (Object)null) { return; } RectTransform val = (((Object)(object)playerBackpackGrid.RectTransform != (Object)null) ? playerBackpackGrid.RectTransform : ((Component)playerBackpackGrid).GetComponent<RectTransform>()); if ((Object)(object)val == (Object)null || !(((Transform)val).parent is RectTransform) || ((Object)(object)root == (Object)null && !TryBuild(ui, val))) { return; } if (!root.activeSelf) { root.SetActive(true); } results.SetShown(value: true); if (fontStale) { TMP_FontAsset val2 = SampleFont(ui); if ((Object)(object)val2 != (Object)null) { fontStale = false; ApplyFont(val2); LogFont(val2); } } Place(val); } public void SetSummary(List<LocationCount> counts) { results.SetCounts(counts); } public void OnInventoryHidden() { Unfocus(); if ((Object)(object)root != (Object)null) { root.SetActive(false); } results.SetShown(value: false); ShowTooltip(show: false); } public void Unfocus() { if (!((Object)(object)input == (Object)null)) { if (input.isFocused) { input.DeactivateInputField(false); } EventSystem current = EventSystem.current; if ((Object)(object)current != (Object)null && (Object)(object)current.currentSelectedGameObject == (Object)(object)((Component)input).gameObject) { current.SetSelectedGameObject((GameObject)null); } } } public void RefreshTexts() { fontStale = true; results.SetFontStale(); results.RefreshTexts(); if ((Object)(object)root == (Object)null) { return; } ((TMP_Text)placeholder).text = RummageText.Get("search.placeholder", "Search name, oil or effect"); ((TMP_Text)clearLabel).text = RummageText.Get("search.clear", "Clear"); ((TMP_Text)tooltipText).text = RummageText.Get("search.appliedOils.tooltip", "Also find weapons by the oils applied to them"); foreach (CategoryButton categoryButton in categoryButtons) { ((TMP_Text)categoryButton.Label).text = CategoryLabel(categoryButton.Category); } } public void Dispose() { filter.Changed -= RefreshSelection; display.ResultsPlacement.SettingChanged -= OnResultsPlacementChanged; results.Destroy(); if ((Object)(object)root != (Object)null) { Object.Destroy((Object)(object)root); } root = null; } private bool TryBuild(InventoryUI ui, RectTransform gridRect) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00af: 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_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Expected O, but got Unknown //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Expected O, but got Unknown //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Expected O, but got Unknown if (buildFailed) { return false; } try { categoryButtons.Clear(); texts.Clear(); root = new GameObject("Rummage_SearchBar", new Type[2] { typeof(RectTransform), typeof(LayoutElement) }); root.GetComponent<LayoutElement>().ignoreLayout = true; rootRect = root.GetComponent<RectTransform>(); ((Transform)rootRect).SetParent(((Transform)gridRect).parent, false); rootRect.anchorMin = new Vector2(0.5f, 0.5f); rootRect.anchorMax = new Vector2(0.5f, 0.5f); rootRect.pivot = Vector2.zero; TMP_FontAsset val = SampleFont(ui); if ((Object)(object)val == (Object)null) { RummagePlugin.Log.LogWarning((object)"No game font found to sample for the search bar; its text uses the TextMeshPro default font and may not render."); } LogFont(val); input = CreateInput(rootRect, val); inputRect = ((Component)input).GetComponent<RectTransform>(); Button val2 = UiParts.CreateButton(rootRect, "Clear", val, texts, out clearLabel); clearRect = ((Component)val2).GetComponent<RectTransform>(); ((UnityEvent)val2.onClick).AddListener(new UnityAction(OnClearClicked)); BuildCheckbox(val); BuildTooltip(val); ItemCategory[] selectable = ItemCategories.Selectable; for (int i = 0; i < selectable.Length; i++) { ItemCategory itemCategory = selectable[i]; TextMeshProUGUI label; Button val3 = UiParts.CreateButton(rootRect, "Category_" + itemCategory, val, texts, out label); ItemCategory captured = itemCategory; ((UnityEvent)val3.onClick).AddListener((UnityAction)delegate { OnCategoryClicked(captured); }); categoryButtons.Add(new CategoryButton { Category = itemCategory, Rect = ((Component)val3).GetComponent<RectTransform>(), Background = ((Component)val3).GetComponent<Image>(), Label = label }); } results.Destroy(); results.Build((RectTransform)((Transform)gridRect).parent, val); input.SetTextWithoutNotify(filter.Text); placedFor = null; RefreshTexts(); fontStale = false; results.ApplyFont(val); RefreshSelection(); return true; } catch (Exception ex) { buildFailed = true; RummagePlugin.Log.LogError((object)("Could not build the search bar; searching and category buttons are unavailable this session. " + ex)); results.Destroy(); if ((Object)(object)root != (Object)null) { Object.Destroy((Object)(object)root); } root = null; return false; } } private void Place(RectTransform gridRect) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: 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_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: 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_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_0195: 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_01bd: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) RectTransform val = (RectTransform)((Transform)gridRect).parent; if ((Object)(object)((Transform)rootRect).parent != (Object)(object)val) { ((Transform)rootRect).SetParent((Transform)(object)val, false); placedFor = null; } if (!((Object)(object)placedFor == (Object)(object)gridRect) || !(placedForRect == gridRect.rect) || !(placedForPosition == ((Transform)gridRect).localPosition)) { placedFor = gridRect; placedForRect = gridRect.rect; placedForPosition = ((Transform)gridRect).localPosition; gridRect.GetWorldCorners(Corners); Vector3 val2 = ((Transform)val).InverseTransformPoint(Corners[1]); Vector3 val3 = ((Transform)val).InverseTransformPoint(Corners[2]); float num = Mathf.Max(360f, val3.x - val2.x); float num2 = 62f; rootRect.sizeDelta = new Vector2(num, num2); ((Transform)rootRect).localPosition = new Vector3(val2.x, val2.y + 6f, 0f); ((Transform)rootRect).SetAsLastSibling(); Layout(num); float num3 = val2.y + 6f; results.Place(val2.x, num3, num3 + num2, num, display.ResultsPlacement.Value); if (diagnostics.LogSearchFilter.Value) { ManualLogSource log = RummagePlugin.Log; string[] obj = new string[12] { "[SearchBar] placed in '", ((Object)val).name, "' above backpack grid ", null, null, null, null, null, null, null, null, null }; Rect rect = gridRect.rect; obj[3] = ((Rect)(ref rect)).width.ToString("0"); obj[4] = "x"; rect = gridRect.rect; obj[5] = ((Rect)(ref rect)).height.ToString("0"); obj[6] = " at ("; obj[7] = val2.x.ToString("0"); obj[8] = ", "; obj[9] = val2.y.ToString("0"); obj[10] = "), bar width "; obj[11] = num.ToString("0"); log.LogInfo((object)string.Concat(obj)); } } } private void Layout(float width) { barWidth = width; UiParts.SetTopLeft(inputRect, 0f, 0f, width - 72f - 4f - 32f - 4f, 32f); UiParts.SetTopLeft(checkboxRect, width - 72f - 4f - 32f, 0f, 32f, 32f); UiParts.SetTopLeft(clearRect, width - 72f, 0f, 72f, 32f); int count = categoryButtons.Count; float num = (width - 4f * (float)(count - 1)) / (float)count; for (int i = 0; i < count; i++) { UiParts.SetTopLeft(categoryButtons[i].Rect, (float)i * (num + 4f), 36f, num, 26f); } } private void RefreshSelection() { //IL_0039: 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_0052: 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_009f: 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_00e0: Unknown result type (might be due to invalid IL or missing references) foreach (CategoryButton categoryButton in categoryButtons) { bool flag = categoryButton.Category == filter.Category; ((Graphic)categoryButton.Background).color = (flag ? UiTheme.ButtonSelected : UiTheme.Button); ((Graphic)categoryButton.Label).color = (flag ? UiTheme.Text : UiTheme.TextMuted); } if ((Object)(object)checkboxIcon != (Object)null) { bool includeAppliedEnchantments = filter.IncludeAppliedEnchantments; ((Graphic)checkboxBackground).color = (includeAppliedEnchantments ? UiTheme.CheckboxFilled : UiTheme.Button); if ((Object)(object)checkboxIcon.sprite != (Object)null) { ((Graphic)checkboxIcon).color = new Color(1f, 1f, 1f, includeAppliedEnchantments ? 1f : 0.45f); } else { ((Behaviour)checkboxIcon).enabled = false; } } if ((Object)(object)input != (Object)null && input.text != filter.Text) { input.SetTextWithoutNotify(filter.Text); } } private void BuildCheckbox(TMP_FontAsset font) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_00a7: 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) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Expected O, but got Unknown TextMeshProUGUI label; Button val = UiParts.CreateButton(rootRect, "IncludeAppliedOils", font, texts, out label); ((TMP_Text)label).text = string.Empty; checkboxRect = ((Component)val).GetComponent<RectTransform>(); checkboxBackground = ((Component)val).GetComponent<Image>(); Sprite appliedOilsGun = UiIcons.AppliedOilsGun; float num = (((Object)(object)appliedOilsGun != (Object)null) ? 3f : 7f); GameObject val2 = new GameObject("Icon", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); RectTransform component = val2.GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)checkboxRect, false); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = new Vector2(num, num); component.offsetMax = new Vector2(0f - num, 0f - num); checkboxIcon = val2.GetComponent<Image>(); checkboxIcon.sprite = appliedOilsGun; checkboxIcon.preserveAspect = true; ((Graphic)checkboxIcon).raycastTarget = false; ((UnityEvent)val.onClick).AddListener(new UnityAction(OnIncludeAppliedClicked)); ((Component)val).gameObject.AddComponent<HoverTip>().Hover = ShowTooltip; } private void BuildTooltip(TMP_FontAsset font) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: 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) GameObject val = new GameObject("Tooltip", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); tooltipRect = val.GetComponent<RectTransform>(); ((Transform)tooltipRect).SetParent((Transform)(object)rootRect, false); Image component = val.GetComponent<Image>(); ((Graphic)component).color = UiTheme.Panel; ((Graphic)component).raycastTarget = false; tooltipText = UiParts.CreateText(tooltipRect, "Text", font, 14f, UiTheme.Text, (TextAlignmentOptions)4097, texts, (TextOverflowModes)0); ((TMP_Text)tooltipText).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)tooltipText).rectTransform.offsetMin = new Vector2(8f, 4f); ((TMP_Text)tooltipText).rectTransform.offsetMax = new Vector2(-8f, -4f); val.SetActive(false); } private void ShowTooltip(bool show) { //IL_0059: 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) if (!((Object)(object)tooltipRect == (Object)null)) { if (!show || fontStale || string.IsNullOrEmpty(((TMP_Text)tooltipText).text)) { ((Component)tooltipRect).gameObject.SetActive(false); return; } Vector2 preferredValues = ((TMP_Text)tooltipText).GetPreferredValues(((TMP_Text)tooltipText).text, float.PositiveInfinity, 0f); float num = preferredValues.x + 16f; float height = preferredValues.y + 8f; float num2 = barWidth - 72f - 4f; UiParts.SetTopLeft(tooltipRect, Mathf.Max(0f, num2 - num), 34f, num, height); ((Transform)tooltipRect).SetAsLastSibling(); ((Component)tooltipRect).gameObject.SetActive(true); } } private void OnIncludeAppliedClicked() { filter.SetIncludeAppliedEnchantments(!filter.IncludeAppliedEnchantments); UiParts.ClearSelection(); } private void OnClearClicked() { filter.Clear(); Unfocus(); UiParts.ClearSelection(); } private void OnCategoryClicked(ItemCategory category) { filter.SetCategory((category != filter.Category) ? category : ItemCategory.All); UiParts.ClearSelection(); } private static string CategoryLabel(ItemCategory category) { return category switch { ItemCategory.Oils => RummageText.Get("category.oils", "Oils"), ItemCategory.Scrolls => RummageText.Get("category.scrolls", "Scrolls"), ItemCategory.Weapons => RummageText.Get("category.weapons", "Weapons"), ItemCategory.Attachments => GameTerms.Get("ItemDescriptions/Label_Attachments") ?? RummageText.Get("category.attachments", "Attachments"), ItemCategory.Consumables => GameTerms.Get("ItemDescriptions/UseType_Consumable") ?? RummageText.Get("category.consumables", "Consumables"), _ => RummageText.Get("category.all", "All"), }; } private static TMP_FontAsset SampleFont(InventoryUI ui) { TMP_FontAsset val = GameFonts.Current(); if ((Object)(object)val != (Object)null) { return val; } TextMeshProUGUI sacrificeFeedbackText = ui.sacrificeFeedbackText; if (!((Object)(object)sacrificeFeedbackText != (Object)null)) { return null; } return ((TMP_Text)sacrificeFeedbackText).font; } private void LogFont(TMP_FontAsset font) { if (diagnostics.LogSearchFilter.Value) { RummagePlugin.Log.LogInfo((object)("[SearchBar] font: " + (((Object)(object)font != (Object)null) ? ((Object)font).name : "<none>"))); } } private void ApplyFont(TMP_FontAsset font) { if ((Object)(object)font == (Object)null) { return; } foreach (TextMeshProUGUI text in texts) { if ((Object)(object)text != (Object)null) { ((TMP_Text)text).font = font; } } if ((Object)(object)input != (Object)null) { float pointSize = FitInputFontSize(font); input.fontAsset = font; input.pointSize = pointSize; } results.ApplyFont(font); } private TMP_InputField CreateInput(RectTransform parent, TMP_FontAsset font) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: 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_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("SearchInput", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)parent, false); val.SetActive(false); Image component2 = val.GetComponent<Image>(); ((Graphic)component2).color = UiTheme.Field; ((Graphic)component2).raycastTarget = true; SearchInputField searchInputField = val.AddComponent<SearchInputField>(); ((Selectable)searchInputField).targetGraphic = (Graphic)(object)component2; ((TMP_InputField)searchInputField).lineType = (LineType)0; ((TMP_InputField)searchInputField).characterLimit = 64; ((TMP_InputField)searchInputField).shouldHideMobileInput = true; ((TMP_InputField)searchInputField).shouldHideSoftKeyboard = true; ((TMP_InputField)searchInputField).onFocusSelectAll = false; ((TMP_InputField)searchInputField).resetOnDeActivation = false; ((TMP_InputField)searchInputField).restoreOriginalTextOnEscape = false; ((TMP_InputField)searchInputField).customCaretColor = true; ((TMP_InputField)searchInputField).caretColor = UiTheme.Text; ((TMP_InputField)searchInputField).caretWidth = 2; ((TMP_InputField)searchInputField).selectionColor = new Color(UiTheme.Text.r, UiTheme.Text.g, UiTheme.Text.b, 0.25f); Navigation navigation = default(Navigation); ((Navigation)(ref navigation)).mode = (Mode)0; ((Selectable)searchInputField).navigation = navigation; RectTransform component3 = new GameObject("TextArea", new Type[2] { typeof(RectTransform), typeof(RectMask2D) }).GetComponent<RectTransform>(); ((Transform)component3).SetParent((Transform)(object)component, false); component3.anchorMin = Vector2.zero; component3.anchorMax = Vector2.one; component3.offsetMin = new Vector2(8f, 1f); component3.offsetMax = new Vector2(-8f, -1f); float num = FitInputFontSize(font); TextMeshProUGUI textComponent = UiParts.CreateText(component3, "Text", font, num, UiTheme.Text, (TextAlignmentOptions)4097, texts, (TextOverflowModes)0); placeholder = UiParts.CreateText(component3, "Placeholder", font, num, UiTheme.TextMuted, (TextAlignmentOptions)4097, texts, (TextOverflowModes)0); ((TMP_InputField)searchInputField).textViewport = component3; ((TMP_InputField)searchInputField).textComponent = (TMP_Text)(object)textComponent; ((TMP_InputField)searchInputField).placeholder = (Graphic)(object)placeholder; ((TMP_InputField)searchInputField).pointSize = num; ((UnityEvent<string>)(object)((TMP_InputField)searchInputField).onValueChanged).AddListener((UnityAction<string>)filter.SetText); val.SetActive(true); return (TMP_InputField)(object)searchInputField; } private static float FitInputFontSize(TMP_FontAsset font) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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) float num = 30f; if (!((Object)(object)font == (Object)null)) { FaceInfo faceInfo = ((TMP_Asset)font).faceInfo; if (!(((FaceInfo)(ref faceInfo)).pointSize <= 0f)) { faceInfo = ((TMP_Asset)font).faceInfo; if (!(((FaceInfo)(ref faceInfo)).lineHeight <= 0f)) { faceInfo = ((TMP_Asset)font).faceInfo; float lineHeight = ((FaceInfo)(ref faceInfo)).lineHeight; faceInfo = ((TMP_Asset)font).faceInfo; float num2 = lineHeight / ((FaceInfo)(ref faceInfo)).pointSize; return Mathf.Clamp(Mathf.Floor(num / num2), 12f, 18f); } } } return 18f; } } internal sealed class SearchInputField : TMP_InputField { public override void OnCancel(BaseEventData eventData) { Keyboard current = Keyboard.current; if (current == null || !((ButtonControl)current.backspaceKey).isPressed) { ((TMP_InputField)this).OnCancel(eventData); } } } internal sealed class SearchResultsPanel { private const float Gap = 4f; private const float ToggleSize = 24f; private const float SummaryMinimumHeight = 30f; private const float SummaryMaximumHeight = 64f; private const float SummaryFontSize = 14f; private const float DetailFontSize = 14f; private const float DetailPadding = 6f; private const float DetailMinimumHeight = 40f; private const float AboveDetailMaximumHeight = 320f; private const float ScreenMargin = 8f; private const string Separator = " · "; private static readonly Vector3[] Corners = (Vector3[])(object)new Vector3[4]; private readonly List<TextMeshProUGUI> texts = new List<TextMeshProUGUI>(); private GameObject root; private RectTransform rootRect; private RectTransform summaryRow; private TextMeshProUGUI summaryText; private RectTransform toggleRect; private TextMeshProUGUI toggleLabel; private RectTransform detailPanel; private RectTransform detailContent; private TextMeshProUGUI detailText; private ScrollRect detailScroll; private List<LocationCount> counts; private bool expanded; private bool shown; private bool fontReady = true; private bool placed; private float left; private float barBottom; private float barTop; private float width; private ResultsPosition position; public bool IsBuilt => (Object)(object)root != (Object)null; public void Build(RectTransform parent, TMP_FontAsset font) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_0088: 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_00b2: Unknown result type (might be due to invalid IL or missing references) texts.Clear(); placed = false; fontReady = true; root = new GameObject("Rummage_SearchResults", new Type[2] { typeof(RectTransform), typeof(LayoutElement) }); root.GetComponent<LayoutElement>().ignoreLayout = true; rootRect = root.GetComponent<RectTransform>(); ((Transform)rootRect).SetParent((Transform)(object)parent, false); rootRect.anchorMin = new Vector2(0.5f, 0.5f); rootRect.anchorMax = new Vector2(0.5f, 0.5f); rootRect.pivot = Vector2.zero; BuildSummaryRow(font); BuildDetailPanel(font); Render(); UpdateVisibility(); } public void Place(float barLeft, float barBottomY, float barTopY, float barWidth, ResultsPosition resultsPosition) { left = barLeft; barBottom = barBottomY; barTop = barTopY; width = barWidth; position = resultsPosition; placed = true; if ((Object)(object)root != (Object)null) { ((Transform)rootRect).SetAsLastSibling(); Layout(); } } public void SetCounts(List<LocationCount> value) { counts = value; Render(); UpdateVisibility(); } public void SetShown(bool value) { shown = value; UpdateVisibility(); } public void RefreshTexts() { Render(); } public void SetFontStale() { fontReady = false; } public void ApplyFont(TMP_FontAsset font) { if ((Object)(object)font != (Object)null) { foreach (TextMeshProUGUI text in texts) { if ((Object)(object)text != (Object)null) { ((TMP_Text)text).font = font; } } } fontReady = true; Layout(); } public void Destroy() { if ((Object)(object)root != (Object)null) { Object.Destroy((Object)(object)root); } root = null; } private void BuildSummaryRow(TMP_FontAsset font) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: 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_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Expected O, but got Unknown GameObject val = new GameObject("Summary", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); summaryRow = val.GetComponent<RectTransform>(); ((Transform)summaryRow).SetParent((Transform)(object)rootRect, false); Image component = val.GetComponent<Image>(); ((Graphic)component).color = UiTheme.Field; ((Graphic)component).raycastTarget = false; summaryText = UiParts.CreateText(summaryRow, "Text", font, 14f, UiTheme.Text, (TextAlignmentOptions)4097, texts, (TextOverflowModes)0); ((TMP_Text)summaryText).textWrappingMode = (TextWrappingModes)1; ((TMP_Text)summaryText).rectTransform.offsetMin = new Vector2(8f, 2f); ((TMP_Text)summaryText).rectTransform.offsetMax = new Vector2(-36f, -2f); Button val2 = UiParts.CreateButton(summaryRow, "Expand", font, texts, out toggleLabel); toggleRect = ((Component)val2).GetComponent<RectTransform>(); ((TMP_Text)toggleLabel).enableAutoSizing = false; ((TMP_Text)toggleLabel).fontSize = 18f; ((TMP_Text)toggleLabel).overflowMode = (TextOverflowModes)0; ((Graphic)toggleLabel).color = UiTheme.Text; ((UnityEvent)val2.onClick).AddListener(new UnityAction(OnToggleClicked)); } private void BuildDetailPanel(TMP_FontAsset font) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_005c: 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_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: 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_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Expected O, but got Unknown //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_016e: 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_019a: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Details", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); detailPanel = val.GetComponent<RectTransform>(); ((Transform)detailPanel).SetParent((Transform)(object)rootRect, false); ((Graphic)val.GetComponent<Image>()).color = UiTheme.Panel; RectTransform component = new GameObject("Viewport", new Type[2] { typeof(RectTransform), typeof(RectMask2D) }).GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)detailPanel, false); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = new Vector2(6f, 6f); component.offsetMax = new Vector2(-6f, -6f); GameObject val2 = new GameObject("Content", new Type[1] { typeof(RectTransform) }); detailContent = val2.GetComponent<RectTransform>(); ((Transform)detailContent).SetParent((Transform)(object)component, false); detailContent.anchorMin = new Vector2(0f, 1f); detailContent.anchorMax = new Vector2(1f, 1f); detailContent.pivot = new Vector2(0.5f, 1f); detailContent.sizeDelta = Vector2.zero; detailContent.anchoredPosition = Vector2.zero; detailText = UiParts.CreateText(detailContent, "Text", font, 14f, UiTheme.TextMuted, (TextAlignmentOptions)257, texts, (TextOverflowModes)0); ((TMP_Text)detailText).textWrappingMode = (TextWrappingModes)1; ((TMP_Text)detailText).richText = true; detailScroll = val.AddComponent<ScrollRect>(); detailScroll.viewport = component; detailScroll.content = detailContent; detailScroll.horizontal = false; detailScroll.vertical = true; detailScroll.movementType = (MovementType)2; detailScroll.inertia = false; detailScroll.scrollSensitivity = 28f; val.SetActive(false); } private void OnToggleClicked() { expanded = !expanded; Render(); UiParts.ClearSelection(); } private void Render() { if (!((Object)(object)root == (Object)null)) { bool flag = counts != null && counts.Count > 0; ((TMP_Text)summaryText).text = ((counts == null) ? string.Empty : (flag ? SummaryLine(counts) : RummageText.Get("summary.none", "No matches"))); ((Component)toggleRect).gameObject.SetActive(flag); ((TMP_Text)toggleLabel).text = (expanded ? "-" : "+"); ((TMP_Text)detailText).text = ((flag && expanded) ? DetailLines(counts) : string.Empty); Layout(); } } private void Layout() { //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root == (Object)null || !placed || !fontReady) { return; } bool flag = position == ResultsPosition.BelowSearchBar; float num = Mathf.Max(40f, width - 24f - 20f); float num2 = Mathf.Clamp(PreferredHeight(summaryText, num) + 8f, 30f, 64f); bool flag2 = expanded && counts != null && counts.Count > 0; if (((Component)detailPanel).gameObject.activeSelf != flag2) { ((Component)detailPanel).gameObject.SetActive(flag2); } float num3 = 0f; if (flag2) { float num4 = Mathf.Max(40f, width - 12f); float num5 = PreferredHeight(detailText, num4); detailContent.sizeDelta = new Vector2(0f, num5); float num6 = (flag ? RoomBelow(barBottom - 4f - num2 - 4f) : Mathf.Min(320f, RoomAbove(barTop + 4f + num2 + 4f))); float num7 = Mathf.Max(40f, num6); num3 = Mathf.Clamp(num5 + 12f, 40f, num7); } float num8 = num2 + (flag2 ? (4f + num3) : 0f); if (flag) { UiParts.SetBottomLeft(summaryRow, 0f, flag2 ? (num3 + 4f) : 0f, width, num2); if (flag2) { UiParts.SetBottomLeft(detailPanel, 0f, 0f, width, num3); } ((Transform)rootRect).localPosition = new Vector3(left, barBottom - 4f - num8, 0f); } else { UiParts.SetBottomLeft(summaryRow, 0f, 0f, width, num2); if (flag2) { UiParts.SetBottomLeft(detailPanel, 0f, num2 + 4f, width, num3); } ((Transform)rootRect).localPosition = new Vector3(left, barTop + 4f, 0f); } UiParts.SetBottomLeft(toggleRect, width - 24f - 4f, (num2 - 24f) * 0.5f, 24f, 24f); rootRect.sizeDelta = new Vector2(width, num8); } private void UpdateVisibility() { if (!((Object)(object)root == (Object)null)) { bool flag = shown && counts != null; if (root.activeSelf != flag) { root.SetActive(flag); } } } private static string SummaryLine(List<LocationCount> locations) { StringBuilder stringBuilder = new StringBuilder(); foreach (LocationCount location in locations) { if (stringBuilder.Length > 0) { stringBuilder.Append(" · "); } stringBuilder.Append(location.Label).Append(" ×").Append(location.Quantity); } return stringBuilder.ToString(); } private static string DetailLines(List<LocationCount> locations) { StringBuilder stringBuilder = new StringBuilder(); foreach (LocationCount location in locations) { if (stringBuilder.Length > 0) { stringBuilder.Append('\n'); } stringBuilder.Append("<color=").Append("#F4C46A").Append('>') .Append(NoParse(location.Label)) .Append(" ×") .Append(location.Quantity) .Append("</color>\n"); for (int i = 0; i < location.Items.Count; i++) { if (i > 0) { stringBuilder.Append(" · "); } stringBuilder.Append(NoParse(location.Items[i].Name)).Append(" ×").Append(location.Items[i].Quantity); } } return stringBuilder.ToString(); } private static string NoParse(string value) { if (!string.IsNullOrEmpty(value) && value.IndexOf('<') >= 0) { return "<noparse>" + value + "</noparse>"; } return value; } private static float PreferredHeight(TextMeshProUGUI text, float width) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(((TMP_Text)text).text)) { return ((TMP_Text)text).GetPreferredValues(((TMP_Text)text).text, width, 0f).y; } return 0f; } private float RoomAbove(float localY) { if (!TryScreenEdge(1, out var y)) { return 320f; } return y - localY - 8f; } private float RoomBelow(float localY) { if (!TryScreenEdge(0, out var y)) { return 320f; } return localY - y - 8f; } private bool TryScreenEdge(int corner, out float y) { //IL_0068: 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) y = 0f; Canvas componentInParent = ((Component)rootRect).GetComponentInParent<Canvas>(); Transform parent = ((Transform)rootRect).parent; RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null); RectTransform val2 = (RectTransform)(((Object)(object)componentInParent != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val2 == (Object)null || (Object)(object)val == (Object)null) { return false; } val2.GetWorldCorners(Corners); y = ((Transform)val).InverseTransformPoint(Corners[corner]).y; return true; } } internal static class UiIcons { private const string AppliedOilsGunResource = "Ryuka.Sulfur.Rummage.UserInterface.Icons.AppliedOilsGun.png"; private static Sprite appliedOilsGun; private static bool appliedOilsGunLoaded; public static Sprite AppliedOilsGun { get { if (!appliedOilsGunLoaded) { appliedOilsGunLoaded = true; appliedOilsGun = Load("Ryuka.Sulfur.Rummage.UserInterface.Icons.AppliedOilsGun.png", "the applied-oils checkbox shows without its gun icon"); } return appliedOilsGun; } } private static bool LoadImage(Texture2D texture, byte[] bytes) { Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule"); MethodInfo methodInfo = ((type != null) ? type.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(Texture2D), typeof(byte[]) }, null) : null); if (methodInfo == null) { RummagePlugin.Log.LogWarning((object)"UnityEngine.ImageConversion.LoadImage(Texture2D, byte[]) was not found; embedded icons cannot be decoded."); return false; } object obj = methodInfo.Invoke(null, new object[2] { texture, bytes }); if (obj is bool) { return (bool)obj; } return false; } private static Sprite Load(string resource, string consequence) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_00f9: 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) try { byte[] bytes; using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resource)) { if (stream == null) { RummagePlugin.Log.LogWarning((object)("Embedded image " + resource + " is missing from this build; " + consequence + ".")); return null; } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); bytes = memoryStream.ToArray(); } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!LoadImage(val, bytes)) { RummagePlugin.Log.LogWarning((object)("Embedded image " + resource + " could not be decoded; " + consequence + ".")); return null; } ((Object)val).name = resource; ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; Sprite obj = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); ((Object)obj).name = resource; return obj; } catch (Exception ex) { RummagePlugin.Log.LogWarning((object)("Loading embedded image " + resource + " failed; " + consequence + ". " + ex.Message)); return null; } } } internal static class UiTheme { public static readonly Color Field = new Color(0.07f, 0.05f, 0.03f, 0.9f); public static readonly Color Panel = new Color(0.03f, 0.02f, 0.01f, 0.92f); public static readonly Color Button = new Color(0.13f, 0.08f, 0.03f, 0.91f); public static readonly Color ButtonSelected = new Color(0.29f, 0.19f, 0.07f, 0.95f); public static readonly Color Text = new Color(0.96f, 0.77f, 0.42f, 1f); public static readonly Color TextMuted = new Color(0.72f, 0.52f, 0.21f, 0.9f); public static readonly Color CheckboxFilled = new Color(0.9f, 0.63f, 0.18f, 1f); public const string TextHex = "#F4C46A"; } internal static class UiParts { public static TextMeshProUGUI CreateText(RectTransform parent, string name, TMP_FontAsset font, float size, Color color, TextAlignmentOptions alignment, List<TextMeshProUGUI> registry, TextOverflowModes overflow = (TextOverflowModes)1) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_0058: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(TextMeshProUGUI) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)parent, false); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; TextMeshProUGUI component2 = val.GetComponent<TextMeshProUGUI>(); if ((Object)(object)font != (Object)null) { ((TMP_Text)component2).font = font; } ((TMP_Text)component2).fontSize = size; ((Graphic)component2).color = color; ((TMP_Text)component2).alignment = alignment; ((Graphic)component2).raycastTarget = false; ((TMP_Text)component2).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)component2).overflowMode = overflow; registry.Add(component2); return component2; } public static Button CreateButton(RectTransform parent, string name, TMP_FontAsset font, List<TextMeshProUGUI> registry, out TextMeshProUGUI label) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_0070: 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) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008d: 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_00cd: 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_00e4: 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_013f: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[4] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(Button) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)parent, false); Image component2 = val.GetComponent<Image>(); ((Graphic)component2).color = UiTheme.Button; Button component3 = val.GetComponent<Button>(); ((Selectable)component3).targetGraphic = (Graphic)(object)component2; Navigation navigation = default(Navigation); ((Navigation)(ref navigation)).mode = (Mode)0; ((Selectable)component3).navigation = navigation; ColorBlock colors = ((Selectable)component3).colors; ((ColorBlock)(ref colors)).normalColor = Color.white; ((ColorBlock)(ref colors)).highlightedColor = new Color(1f, 0.92f, 0.8f, 1f); ((ColorBlock)(ref colors)).pressedColor = new Color(0.75f, 0.7f, 0.62f, 1f); ((ColorBlock)(ref colors)).selectedColor = Color.white; ((Selectable)component3).colors = colors; label = CreateText(component, "Label", font, 15f, UiTheme.TextMuted, (TextAlignmentOptions)514, registry, (TextOverflowModes)1); ((TMP_Text)label).enableAutoSizing = true; ((TMP_Text)label).fontSizeMin = 9f; ((TMP_Text)label).fontSizeMax = 15f; ((TMP_Text)label).rectTransform.offsetMin = new Vector2(3f, 1f); ((TMP_Text)label).rectTransform.offsetMax = new Vector2(-3f, -1f); return component3; } public static void SetTopLeft(RectTransform rect, float x, float y, float width, float height) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_0043: 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) rect.anchorMin = new Vector2(0f, 1f); rect.anchorMax = new Vector2(0f, 1f); rect.pivot = new Vector2(0f, 1f); rect.sizeDelta = new Vector2(width, height); rect.anchoredPosition = new Vector2(x, 0f - y); } public static void SetBottomLeft(RectTransform rect, float x, float y, float width, float height) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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_0032: Unknown result type (might be due to invalid IL or missing references) rect.anchorMin = Vector2.zero; rect.anchorMax = Vector2.zero; rect.pivot = Vector2.zero; rect.sizeDelta = new Vector2(width, height); rect.anchoredPosition = new Vector2(x, y); } public static void ClearSelection() { EventSystem current = EventSystem.current; if ((Object)(object)current != (Object)null) { current.SetSelectedGameObject((GameObject)null); } } } internal sealed class WorldMarkers : IDisposable { private sealed class Marker { public GameObject Root; public RectTransform Rect; public RectTransform Background; public TextMeshProUGUI Text; public string Shown; } private const float HeightAboveAnchor = 0.9f; private const float WorldUnitsPerPixel = 0.004f; private const float ReferenceDistance = 5f; private const float MaximumDistanceScale = 3f; private const float FontSize = 36f; private const float PaddingX = 18f; private const float PaddingY = 8f; private const int SortingOrder = 500; private readonly StorageIndex index; private readonly Dictionary<string, Marker> markers = new Dictionary<string, Marker>(StringComparer.Ordinal); private readonly HashSet<string> shownThisFrame = new HashSet<string>(StringComparer.Ordinal); private GameObject root; private List<LocationCount> counts; private TMP_FontAsset font; private bool fontStale = true; private bool failureReported; public WorldMarkers(DiagnosticsConfig diagnostics) { index = new StorageIndex(diagnostics); } public void SetCounts(List<LocationCount> value) { counts = value; } public void OnPlayerSpawned() { index.Invalidate(); } public void OnLanguageChanged() { fontStale = true; } public void LateTick() { try { Update(); } catch (Exception ex) { if (!failureReported) { failureReported = true; RummagePlugin.Log.LogError((object)("Updating world markers failed; further failures are not logged. " + ex)); } HideAll(); } } public void Dispose() { if ((Object)(object)root != (Object)null) { Object.Destroy((Object)(object)root); } root = null; markers.Clear(); } private void Update() { //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: 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_00d9: 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_0136: Unknown result type (might be due to invalid IL or missing references) if (counts == null || counts.Count == 0) { HideAll(); return; } GameManager instance = StaticInstance<GameManager>.Instance; GameObject val = (((Object)(object)instance != (Object)null) ? instance.PlayerObject : null); Camera val2 = PlayerCamera(instance); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { HideAll(); return; } if (fontStale) { TMP_FontAsset val3 = GameFonts.Current(); if ((Object)(object)val3 == (Object)null) { HideAll(); return; } font = val3; fontStale = false; foreach (Marker value in markers.Values) { ApplyFont(value); } } Vector3 position = val.transform.position; Vector3 position2 = ((Component)val2).transform.position; shownThisFrame.Clear(); foreach (LocationCount count in counts) { if (count.Identifier != null) { StorageIndex.Entry entry = index.Nearest(count.Identifier, position); if (entry != null) { Marker orCreate = GetOrCreate(count.Identifier); Place(orCreate, entry, count, position2); shownThisFrame.Add(count.Identifier); } } } foreach (KeyValuePair<string, Marker> marker in markers) { if (!shownThisFrame.Contains(marker.Key) && marker.Value.Root.activeSelf) { marker.Value.Root.SetActive(false); } } } private static Camera PlayerCamera(GameManager gameManager) { if ((Object)(object)gameManager != (Object)null && (Object)(object)gameManager.PlayerScript != (Object)null && (Object)(object)gameManager.PlayerScript.playerCamera != (Object)null) { return gameManager.PlayerScript.playerCamera; } return Camera.main; } private void Place(Marker marker, StorageIndex.Entry target, LocationCount count, Vector3 cameraPosition) { //IL_00a5: 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_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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_010e: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) if (!marker.Root.activeSelf) { marker.Root.SetActive(true); } string text = count.Label + " ×" + count.Quantity; if (marker.Shown != text) { marker.Shown = text; ((TMP_Text)marker.Text).text = text; Vector2 preferredValues = ((TMP_Text)marker.Text).GetPreferredValues(text); marker.Rect.sizeDelta = new Vector2(preferredValues.x + 36f, preferredValues.y + 16f); } Transform transform = marker.Root.transform; transform.position = target.Anchor.position + Vector3.up * 0.9f; Vector3 val = transform.position - cameraPosition; if (((Vector3)(ref val)).sqrMagnitude > 0.0001f) { transform.rotation = Quaternion.LookRotation(val, Vector3.up); } float num = Mathf.Clamp(((Vector3)(ref val)).magnitude / 5f, 1f, 3f); transform.localScale = Vector3.one * (0.004f * num); if (marker.Root.layer != target.Owner.layer) { SetLayer(marker.Root, target.Owner.layer); } } private Marker GetOrCreate(string identifier) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_00af: 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_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Expected O, but got Unknown //IL_0169: 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_003e: Expected O, but got Unknown if (markers.TryGetValue(identifier, out var value) && (Object)(object)value.Root != (Object)null) { return value; } if ((Object)(object)root == (Object)null) { root = new GameObject("Rummage_WorldMarkers"); } GameObject val = new GameObject("Marker_" + identifier, new Type[2] { typeof(RectTransform), typeof(Canvas) }); val.transform.SetParent(root.transform, false); Canvas component = val.GetComponent<Canvas>(); component.renderMode = (RenderMode)2; component.sortingOrder = 500; RectTransform component2 = val.GetComponent<RectTransform>(); component2.pivot = new Vector2(0.5f, 0f); GameObject val2 = new GameObject("Background", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); RectTransform component3 = val2.GetComponent<RectTransform>(); ((Transform)component3).SetParent((Transform)(object)component2, false); component3.anchorMin = Vector2.zero; component3.anchorMax = Vector2.one; component3.offsetMin = Vector2.zero; component3.offsetMax = Vector2.zero; Image component4 = val2.GetComponent<Image>(); ((Graphic)component4).color = UiTheme.Panel; ((Graphic)component4).raycastTarget = false; ((Graphic)component4).material = OnTop(new Material(Canvas.GetDefaultCanvasMaterial())); List<TextMeshProUGUI> registry = new List<TextMeshProUGUI>(); TextMeshProUGUI text = UiParts.CreateText(component2, "Text", null, 36f, UiTheme.Text, (TextAlignmentOptions)514, registry, (TextOverflowModes)0); value = new Marker { Root = val, Rect = component2, Background = component3, Text = text }; ApplyFont(value); markers[identifier] = value; return value; } private void ApplyFont(Marker marker) { if ((Object)(object)font != (Object)null) { ((TMP_Text)marker.Text).font = font; } OnTop(((TMP_Text)marker.Text).fontMaterial); marker.Shown = null; } private static Material OnTop(Material material) { if ((Object)(object)material != (Object)null) { material.SetInt("unity_GUIZTestMode", 8); } return material; } private void HideAll() { foreach (Marker value in markers.Values) { if ((Object)(object)value.Root != (Object)null && value.Root.activeSelf) { value.Root.SetActive(false); } } } private static void SetLayer(GameObject go, int layer) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) go.layer = layer; foreach (Transform item in go.transform) { SetLayer(((Component)item).gameObject, layer); } } } } namespace Ryuka.Sulfur.Rummage.Stashes { internal enum StashKind { Main, Wardrobe, Suitcase, Safe, Sideboard, Fridge, SnakeBasket, GunCabinet, WeaponRack, Coffin, Toilet, ItemFrame, WallMount, Unknown } internal readonly struct StashName { public StashKind Kind { get; } public int Number { get; } public StashName(StashKind kind, int number) { Kind = kind; Number = number; } } internal static class StashNaming { public static StashName Resolve(string identifier) { switch (identifier ?? string.Empty) { case "": return new StashName(StashKind.Main, 0); case "Wardrobe": return new StashName(StashKind.Wardrobe, 0); case "Suitcase": return new StashName(StashKind.Suitcase, 0); case "Safe": return new StashName(StashKind.Safe, 0); case "Sideboard": return new StashName(StashKind.Sideboard, 0); case "Fridge": return new StashName(StashKind.Fridge, 0); case "SnakeBasket": return new StashName(StashKind.SnakeBasket, 0); case "GunCabinet": return new StashName(StashKind.GunCabinet, 0); case "Coffin": return new StashName(StashKind.Coffin, 0); case "Toilet": return new StashName(StashKind.Toilet, 0); default: { if (TryNumberedSuffix(identifier, "WeaponRack", out var number)) { return new StashName(StashKind.WeaponRack, number + 1); } if (TryNumberedSuffix(identifier, "WallMount", out number)) { return new StashName(StashKind.WallMount, number + 1); } if (TryNumberedSuffix(identifier, "ItemFrame", out number) && number > 0) { return new StashName(StashKind.ItemFrame, number); } return new StashName(StashKind.Unknown, 0); } } } private static bool TryNumberedSuffix(string identifier, string prefix, out int number) { number = 0; if (identifier == null || identifier.Length <= prefix.Length || !identifier.StartsWith(prefix, StringComparison.Ordinal)) { return false; } for (int i = prefix.Length; i < identifier.Length; i++) { char c = identifier[i]; if (c < '0' || c > '9') { return false; } number = number * 10 + (c - 48); if (number > 9999) { return false; } } return true; } } internal static class StashSaveKey { public const string Prefix = "Stash"; private const char Separator = '_'; public static string FromIdentifier(string identifier) { if (!string.IsNullOrEmpty(identifier)) { return "Stash_" + identifier; } return "Stash"; } public static bool TryGetIdentifier(string key, out string identifier) { identifier = null; if (key == null || !key.StartsWith("Stash", StringComparison.Ordinal)) { return false; } if (key.Length == "Stash".Length) { identifier = string.Empty; return true; } if (key["Stash".Length] != '_' || key.Length == "Stash".Length + 1) { return false; } identifier = key.Substring("Stash".Length + 1); return true; } } } namespace Ryuka.Sulfur.Rummage.Search { internal enum ItemCategory { All, Oils, Scrolls, Weapons, Attachments, Consumables, Other } internal static class ItemCategories { public static readonly ItemCategory[] Selectable = new ItemCategory[6] { ItemCategory.All, ItemCategory.Oils, ItemCategory.Scrolls, ItemCategory.Weapons, ItemCategory.Attachments, ItemCategory.Consumables }; public static ItemCategory Next(ItemCategory current) { int num = Array.IndexOf(Selectable, current); return Selectable[(num + 1) % Selectable.Length]; } } internal sealed class PinyinName { private const int MaxLength = 64; private readonly string text; private readonly string[][] readings; private PinyinName(string text, string[][] readings) { this.text = text; this.readings = readings; } internal static PinyinName Create(string text) { if (string.IsNullOrEmpty(text) || !PinyinTable.IsAvailable) { return null; } if (text.Length > 64) { text = text.Substring(0, 64); } string[][] array = null; for (int i = 0; i < text.Length; i++) { string[] array2 = PinyinTable.GetReadings(text[i]); if (array2.Length != 0) { if (array == null) { array = new string[text.Length][]; } array[i] = array2; } } if (array != null) { return new PinyinName(text, array); } return null; } internal bool Matches(string query) { if (string.IsNullOrEmpty(query)) { return true; } for (int i = 0; i < text.Length; i++) { if (MatchFrom(i, query, 0)) { return true; } } return false; } private bool MatchFrom(int index, string query, int queryIndex) { if (queryIndex >= query.Length) { return true; } if (index >= this.text.Length) { return false; } string[] array = readings[index]; if (array == null) { char c = this.text[index]; if (c == query[queryIndex] && MatchFrom(index + 1, query, queryIndex + 1)) { return true; } if (!char.IsLetterOrDigit(c)) { return MatchFrom(index + 1, query, queryIndex); } return false; } for (int i = 0; i < array.Length; i++) { string text = array[i]; bool flag = i == 0; int j; for (j = 0; j < text.Length && queryIndex + j < query.Length && text[j] == query[queryIndex + j]; j++) { } if (j == 0) { continue; } if (queryIndex + j >= query.Length) { if (flag || j == text.Length) { return true; } continue; } if (j == text.Length && MatchFrom(index + 1, query, queryIndex + j)) { return true; } if (flag) { if (MatchFrom(index + 1, query, queryIndex + 1)) { return true; } if (j >= 2 && IsRetroflex(text) && MatchFrom(index + 1, query, queryIndex + 2)) { return true; } } } return false; } private static bool IsRetroflex(string reading) { if (reading.Length < 2 || reading[1] != 'h') { return false; } char c = reading[0]; if (c != 'z' && c != 'c') { return c == 's'; } return true; } } internal static class PinyinTable { private const string ResourceName = "Ryuka.Sulfur.Rummage.Search.PinyinTable.bin"; private static readonly string[] Empty = new string[0]; private static readonly Dictionary<char, string[]> Cache = new Dictionary<char, string[]>(); private static string[] syllables; private static ushort[] starts; private static ushort[] readingIds; private static char rangeStart; private static char rangeEnd; private static bool loaded; internal static bool IsAvailable { get { Load(); return syllables != null; } } internal static int CoveredCharacters { get { Load(); if (readingIds != null) { return readingIds.Length; } return 0; } } internal static bool IsHan(char character) { Load(); if (syllables != null && character >= rangeStart) { return character <= rangeEnd; } return false; } internal static string[] GetReadings(char character) { if (!IsHan(character)) { return Empty; } if (Cache.TryGetValue(character, out var value)) { return value; } int num = character - rangeStart; int num2 = starts[num]; int num3 = starts[num + 1] - num2; string[] array = Empty; if (num3 > 0) { array = new string[num3]; for (int i = 0; i < num3; i++) { array[i] = syllables[readingIds[num2 + i]]; } } Cache[character] = array; return array; } private static void Load() { if (loaded) { return; } loaded = true; try { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Ryuka.Sulfur.Rummage.Search.PinyinTable.bin"); if (stream == null) { RummagePlugin.Log.LogWarning((object)"The pinyin table is missing from this build; pinyin search is off."); } else { Read(stream); } } catch (Exception ex) { syllables = null; starts = null; readingIds = null; RummagePlugin.Log.LogWarning((object)("Could not read the pinyin table: " + ex.Message + " Pinyin search is off.")); } } private static void Read(Stream stream) { using BinaryReader binaryReader = new BinaryReader(stream, Encoding.UTF8); int num = binaryReader.ReadUInt16(); int count = (int)binaryReader.ReadUInt32(); syllables = Encoding.UTF8.GetString(binaryReader.ReadBytes(count)).Split(new char[1] { '\n' }); if (syllables.Length != num) { throw new InvalidDataException("expected " + num + " syllables but found " + syllables.Length); } rangeStart = (char)binaryReader.ReadUInt16(); rangeEnd = (char)binaryReader.ReadUInt16(); int num2 = rangeEnd - rangeStart + 1; starts = new ushort[num2 + 1]; List<ushort> list = new List<ushort>(num2 + num2 / 2); for (int i = 0; i < num2; i++) { starts[i] = (ushort)list.Count; int num3 = binaryReader.ReadByte(); for (int j = 0; j < num3; j++) { list.Add(binaryReader.ReadUInt16()); } } starts[num2] = (ushort)list.Count; readingIds = list.ToArray(); } } internal sealed class SearchQuery { public static readonly SearchQuery Empty = new SearchQuery(new string[0]); private readonly string[] terms; private readonly bool[] latinOnly; public bool IsEmpty => terms.Length == 0; public int TermCount => terms.Length; private SearchQuery(string[] terms) { this.terms = terms; latinOnly = new bool[terms.Length]; for (int i = 0; i < terms.Length; i++) { latinOnly[i] = IsLatin(terms[i]); } } public static SearchQuery Parse(string text) { if (string.IsNullOrWhiteSpace(text)) { return Empty; } string[] array = text.ToLowerInvariant().Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries); if (array.Length != 0) { return new SearchQuery(array); } return Empty; } public bool Matches(SearchableText searchable) { return Matches(searchable, null); } public bool Matches(SearchableText searchable, IReadOnlyList<SearchableText> more) { for (int i = 0; i < terms.Length; i++) { bool flag = searchable?.Contains(terms[i], latinOnly[i]) ?? false; if (!flag && more != null) { for (int j = 0; j < more.Count; j++) { if (flag) { break; } flag = more[j] != null && more[j].Contains(terms[i], latinOnly[i]); } } if (!flag) { return false; } } return true; } private static bool IsLatin(string term) { for (int i = 0; i < term.Length; i++) { if (term[i] < 'a' || term[i] > 'z') { return false; } } return term.Length > 0; } } internal sealed class SearchableText { private static readonly PinyinName[] NoSpokenNames = new PinyinName[0]; private readonly string[] texts; private readonly PinyinName[] spokenNames; private SearchableText(string[] texts, PinyinName[] spokenNames) { this.texts = texts; this.spokenNames = spokenNames; } public static SearchableText Create(IEnumerable<string> sources) { List<string> list = new List<string>(); HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); if (sources != null) { foreach (string source in sources) { if (!string.IsNullOrWhiteSpace(source)) { string item = source.Trim().ToLowerInvariant(); if (hashSet.Add(item)) { list.Add(item); } } } } List<PinyinName> list2 = null; foreach (string item2 in list) { PinyinName pinyinName = PinyinName.Create(item2); if (pinyinName != null) { (list2 ?? (list2 = new List<PinyinName>())).Add(pinyinName); } } return new SearchableText(list.ToArray(), (list2 == null) ? NoSpokenNames : list2.ToArray()); } internal bool Contains(string term, bool latinOnly) { for (int i = 0; i < texts.Length; i++) { if (texts[i].IndexOf(term, StringComparison.Ordinal) >= 0) { return true; } } if (!latinOnly) { return false; } for (int j = 0; j < spokenNames.Length; j++) { if (spokenNames[j].Matches(term)) { return true; } } return false; } } } namespace Ryuka.Sulfur.Rummage.Localization { internal static class GameLanguage { public const string FallbackCode = "en"; private static readonly string[] ShippedCodes = new string[14] { "en", "sv", "fr", "it", "de", "es", "pt", "ru", "pl", "ja", "ko", "zh-CN", "tr", "ar" }; public static string CurrentCode() { try { string currentLanguageCode = LocalizationManager.CurrentLanguageCode; return string.IsNullOrEmpty(currentLanguageCode) ? null : currentLanguageCode; } catch (Exception) { return null; } } public static bool IsRightToLeft() { try { return LocalizationManager.IsRight2Left; } catch (Exception) { return false; } } public static string FixRightToLeft(string text) { try { return LocalizationManager.FixRTL_IfNeeded(text, 0, false); } catch (Exception) { return text; } } public static string ResolveCode(string languageCode) { if (string.IsNullOrEmpty(languageCode)) { return "en"; } string[] shippedCodes = ShippedCodes; foreach (string text in shippedCodes) { if (string.Equals(text, languageCode, StringComparison.OrdinalIgnoreCase)) { return text; } } string b = LanguageOf(languageCode); shippedCodes = ShippedCodes; foreach (string text2 in shippedCodes) { if (string.Equals(LanguageOf(text2), b, StringComparison.OrdinalIgnoreCase)) { return text2; } } return "en"; } private static string LanguageOf(string languageCode) { int num = languageCode.IndexOf('-'); if (num <= 0) { return languageCode; } return languageCode.Substring(0, num); } } internal static class GameTerms { public const string Consumable = "ItemDescriptions/UseType_Consumable"; public const string Attachments = "ItemDescriptions/Label_Attachments"; public static string Get(string term) { try { string text = default(string); return (LocalizationManager.TryGetTranslation(term, ref text, true, 0, true, false, (GameObject)null, (string)null, true) && !string.IsNullOrWhiteSpace(text)) ? text : null; } catch (Exception) { return null; } } } internal sealed class LanguageWatcher : IDisposable { private const float RetrySeconds = 1f; private readonly string pluginDirectory; private readonly OnLanguageChange handler; private AsyncAssetLoading subscribedTo; private bool gameLanguageKnown; private float nextAttempt; public event Action LanguageChanged; public LanguageWatcher(string pluginDirectory) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown this.pluginDirectory = pluginDirectory; handler = new OnLanguageChange(OnGameLanguageChanged); } public void Tick() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown AsyncAssetLoading instance = StaticInstance<AsyncAssetLoading>.Instance; if (instance != subscribedTo) { Unsubscribe(); if ((Object)(object)instance != (Object)null) { instance.onLanguageChange = (OnLanguageChange)Delegate.Combine((Delegate?)(object)instance.onLanguageChange, (Delegate?)(object)handler); subscribedTo = instance; } } if (!gameLanguageKnown && Time.unscaledTime >= nextAttempt) { nextAttempt = Time.unscaledTime + 1f; Load(fromGameEvent: false); } } public void Dispose() { Unsubscribe(); this.LanguageChanged = null; } private void OnGameLanguageChanged() { Load(fromGameEvent: true); } private void Load(bool fromGameEvent) { bool flag = RummageText.Reload(pluginDirectory); gameLanguageKnown = RummageText.GameCode != null; if (flag) { string text = "Language: " + RummageText.LoadedCode + " (game language code: " + (RummageText.GameCode ?? "<not loaded yet>") + ") - " + RummageText.LoadedCount + " strings from " + (RummageText.LoadedFrom ?? "<nowhere>"); if (RummageText.LoadedCount == 0 || RummageText.LastLoadNote != null) { RummagePlugin.Log.LogWarning((object)(text + " | " + (RummageText.LastLoadNote ?? "no strings"))); } else { RummagePlugin.Log.LogInfo((object)text); } } if (flag || fromGameEvent) { Raise(); } } private void Raise() { Action action = this.LanguageChanged; if (action == null) { return; } Delegate[] invocationList = action.GetInvocationList(); foreach (Delegate obj in invocationList) { try { ((Action)obj)(); } catch (Exception ex) { RummagePlugin.Log.LogError((object)("Language change listener failed: " + ex)); } } } private void Unsubscribe() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown if (subscribedTo != null) { AsyncAssetLoading obj = subscribedTo; obj.onLanguageChange = (OnLanguageChange)Delegate.Remove((Delegate?)(object)obj.onLanguageChange, (Delegate?)(object)handler); subscribedTo = null; } } } internal static class RummageText { [DataContract] private sealed class LangEntry { [DataMember(Name = "key")] public string Key; [DataMember(Name = "value")] public string Value; } [DataContract] private sealed class LangFile { [DataMember(Name = "entries")] public LangEntry[] Entries; } private static readonly Dictionary<string, string> Strings = new Dictionary<string, string>(StringComparer.Ordinal); public static string LoadedCode { get; private set; } public static string GameCode { get; private set; } public static int LoadedCount => Strings.Count; public static string LastLoadNote { get; private set; } public static string LoadedFrom { get; private set; } public static bool Reload(string pluginDirectory) { string text = GameLanguage.CurrentCode(); string text2 = GameLanguage.ResolveCode(text); if (LoadedCode == text2 && GameCode == text) { return false; } Strings.Clear(); LastLoadNote = null; LoadedFrom = null; if (text2 != "en") { LoadFirstMatch(pluginDirectory, "en"); } LoadFirstMatch(pluginDirectory, text2); LoadedCode = text2; GameCode = text; return true; } public static string Get(string key, string englishFallback) { if (!Strings.TryGetValue(key, out var value) || string.IsNullOrEmpty(value)) { return englishFallback; } return value; } private static IEnumerable<string> CandidateDirectories(string pluginDirectory) { if (!string.IsNullOrEmpty(pluginDirectory)) { yield return Path.Combine(pluginDirectory, "lang"); yield return pluginDirectory; string text; try { text = Directory.GetParent(pluginDirectory)?.FullName; } catch (Exception) { text = null; } if (!string.IsNullOrEmpty(text)) { yield return Path.Combine(text, "lang"); } } } private static void LoadFirstMatch(string pluginDirectory, string code) { foreach (string item in CandidateDirectories(pluginDirectory)) { if (LoadInto(item, code)) { LoadedFrom = item; return; } } LastLoadNote = LastLoadNote ?? ("no readable " + code + ".json under " + (pluginDirectory ?? "<unknown>")); } private static bool LoadInto(string directory, string code) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) string text = Path.Combine(directory, code + ".json"); if (!File.Exists(text)) { return false; } try { LangFile langFile; using (MemoryStream memoryStream = new MemoryStream(File.ReadAllBytes(text))) { langFile = ((XmlObjectSerializer)new DataContractJsonSerializer(typeof(LangFile))).ReadObject((Stream)memoryStream) as LangFile; } if (langFile == null || langFile.Entries == null) { LastLoadNote = "no entries in " + text; return false; } bool flag = GameLanguage.IsRightToLeft(); int num = 0; LangEntry[] entries = langFile.Entries; foreach (LangEntry langEntry in entries) { if (langEntry != null && !string.IsNullOrEmpty(langEntry.Key) && langEntry.Value != null) { Strings[langEntry.Key] = (flag ? GameLanguage.FixRightToLeft(langEntry.Value) : langEntry.Value); num++; } } return num > 0; } catch (Exception ex) { LastLoadNote = ex.GetType().Name + " reading " + text; return false; } } } } namespace Ryuka.Sulfur.Rummage.InputGuard { internal static class SearchInputGuard { public static Func<bool> IsTyping; public static Action StopTyping; internal static bool Typing() { try { return IsTyping != null && IsTyping(); } catch (Exception) { return false; } } } [HarmonyPatch] internal static class InventoryKeyGuardPatch { private static readonly string[] Handlers = new string[6] { "InventoryRotateCurrentItem", "InventorySortCurrentGrid", "InventoryUse", "InventoryDrop", "InventorySubmit", "NavigateInventory" }; private static IEnumerable<MethodBase> TargetMethods() { string[] handlers = Handlers; foreach (string text in handlers) { MethodInfo methodInfo = AccessTools.Method(typeof(InputReader), text, new Type[1] { typeof(CallbackContext) }, (Type[])null); if (methodInfo == null) { RummagePlugin.Log.LogWarning((object)("InputReader." + text + " was not found; its key may act on the inventory while typing in the search box.")); } else { yield return methodInfo; } } } private static bool Prefix() { return !SearchInputGuard.Typing(); } } [HarmonyPatch(typeof(InputReader), "InventoryCancel")] internal static class InventoryCancelGuardPatch { private static bool Prefix(CallbackContext context) { if (!SearchInputGuard.Typing()) { return true; } Keyboard current = Keyboard.current; if (current != null && (object)((CallbackContext)(ref context)).control == current.escapeKey) { SearchInputGuard.StopTyping?.Invoke(); } return false; } } } namespace Ryuka.Sulfur.Rummage.Game { internal static class InventoryLegend { private static ConfigEntry<bool> hide; private static FieldRef<InventoryUI, GameObject> keyboardRow; private static FieldRef<InventoryUI, GameObject> gamepadRow; private static bool lastGamepadState; private static bool hasLastState; public static void Initialize(ConfigEntry<bool> hideSetting) { hide = hideSetting; try { keyboardRow = AccessTools.FieldRefAccess<InventoryUI, GameObject>("LegendKeyboard"); gamepadRow = AccessTools.FieldRefAccess<InventoryUI, GameObject>("LegendGamepad"); } catch (Exception ex) { keyboardRow = null; gamepadRow = null; RummagePlugin.Log.LogWarning((object)("InventoryUI.LegendKeyboard / LegendGamepad were not found; the inventory key hints cannot be hidden. " + ex.Message)); } hide.SettingChanged += OnSettingChanged; } public static void Shutdown() { if (hide != null) { hide.SettingChanged -= OnSettingChanged; } } public static void AfterToggle(InventoryUI ui, bool gamepadState) { lastGamepadState = gamepadState; hasLastState = true; if (hide != null && hide.Value) { HideRows(ui); } } private static void OnSettingChanged(object sender, EventArgs e) { UIManager instance = StaticInstance<UIManager>.Instance; InventoryUI val = (((Object)(object)instance != (Object)null) ? instance.InventoryUI : null); if ((Object)(object)val == (Object)null) { return; } try { if (hide.Value) { HideRows(val); } else if (hasLastState) { val.ToggleGamepadLegend(lastGamepadState); } } catch (Exception ex) { RummagePlugin.Log.LogWarning((object)("Applying the key hint setting failed: " + ex.Message)); } } private static void HideRows(InventoryUI ui) { if (keyboardRow != null && gamepadRow != null && !((Object)(object)ui == (Object)null)) { GameObject val = keyboardRow.Invoke(ui); GameObject val2 = gamepadRow.Invoke(ui); if ((Object)(object)val != (Object)null && val.activeSelf) { val.SetActive(false); } if ((Object)(object)val2 != (Object)null && val2.activeSelf) { val2.SetActive(false); } } } } [HarmonyPatch(typeof(InventoryUI), "ToggleGamepadLegend")] internal static class InventoryLegendPatch { private static void Postfix(InventoryUI __instance, bool state) { try { InventoryLegend.AfterToggle(__instance, state); } catch (Exception ex) { RummagePlugin.Log.LogWarning((object)("Hiding the inventory key hints failed: " + ex.Message)); } } } [HarmonyPatch(typeof(InventoryUI), "SetState")] internal static class InventoryStatePatch { internal static event Action<InventoryUI, UIState> StateSet; private static void Postfix(InventoryUI __instance, UIState state) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) Action<InventoryUI, UIState> stateSet = InventoryStatePatch.StateSet; if (stateSet == null) { return; } try { stateSet(__instance, state); } catch (Exception ex) { RummagePlugin.Log.LogError((object)("Inventory open/close handling failed: " + ex)); } } } internal static class ItemMatcher { private static readonly List<SearchableText> Applied = new List<SearchableText>(); public static bool Matches(InventoryItem item, InventoryFilter filter) { ItemSearchCatalog.Entry entry = ItemSearchCatalog.Get(item.itemDefinition); Applied.Clear(); if (UsesApplied(filter) && item.enchantments != null) { foreach (EnchantmentDefinition enchantment in item.enchantments) { SearchableText applied = ItemSearchCatalog.GetApplied(enchantment); if (applied != null) { Applied.Add(applied); } } } return filter.Accepts(entry.Category, entry.Text, Applied); } public static bool Matches(InventoryData data, ItemDefinition definition, InventoryFilter filter) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) ItemSearchCatalog.Entry entry = ItemSearchCatalog.Get(definition); Applied.Clear(); if (UsesApplied(filter) && data.enchantmentIds != null) { ItemId[] enchantmentIds = data.enchantmentIds; for (int i = 0; i < enchantmentIds.Length; i++) { ItemId val = enchantmentIds[i]; ItemDefinition val2 = (((ItemId)(ref val)).IsValid ? AssetAccess.GetAsset(val) : null); if ((Object)(object)val2 != (Object)null) { Applied.Add(ItemSearchCatalog.Get(val2).Text); } } } return filter.Accepts(entry.Category, entry.Text, Applied); } private static bool UsesApplied(InventoryFilter filter) { if (filter.IncludeAppliedEnchantments) { return !filter.Query.IsEmpty; } return false; } } internal static class ItemSearchCatalog { internal sealed class Entry { public ItemCategory Category { get; } public SearchableText Text { get; } public Entry(ItemCategory category, SearchableText text) { Category = category; Text = text; } } private static readonly Dictionary<ItemDefinition, Entry> Entries = new Dictionary<ItemDefinition, Entry>(); private static readonly Entry Unindexed = new Entry(ItemCategory.Other, SearchableText.Create(null)); private static bool indexFailureReported; private static readonly Dictionary<EnchantmentDefinition, SearchableText> EnchantmentTexts = new Dictionary<EnchantmentDefinition, SearchableText>(); private static readonly string[] Placeholders = new string[5] { "VALUE_X", "DURATION_X", "AMOUNT_X", "STATUS_X", "ATTRIBUTE_X" }; public static void Invalidate() { Entries.Clear(); EnchantmentTexts.Clear(); } public static SearchableText GetApplied(EnchantmentDefinition enchantment) { if ((Object)(object)enchantment == (Object)null) { return null; } if ((Object)(object)enchantment.ItemThatAppliedThis != (Object)null) { return Get(enchantment.ItemThatAppliedThis).Text; } if (!EnchantmentTexts.TryGetValue(enchantment, out var value)) { List<string> list = new List<string>(); try { list.Add(Translate("EnchantmentDefinitions/" + ((Object)enchantment).name, enchantment.enchantmentName)); list.Add(enchantment.enchantmentName); AddModifierTexts(enchantment.modifiersApplied, onlyShownInDescription: true, list); } catch (Exception) { } value = SearchableText.Create(list); EnchantmentTexts[enchantment] = value; } return value; } public static Entry Get(ItemDefinition item) { if ((Object)(object)item == (Object)null) { return Unindexed; } if (!Entries.TryGetValue(item, out var value)) { value = Build(item); Entries[item] = value; } return value; } private static Entry Build(ItemDefinition item) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) try { List<string> list = new List<string>(); list.Add(Translate("Items/" + ((Object)item).name, item.displayName)); list.Add(item.displayName); EnchantmentDefinition val = (((EnchantmentId)(ref item.appliesEnchantment)).IsValid ? AssetAccess.GetAsset(item.appliesEnchantment) : null); if ((Object)(object)val != (Object)null) { list.Add(Translate("EnchantmentDefinitions/" + ((Object)val).name, val.enchantmentName)); list.Add(val.enchantmentName); AddModifierTexts(val.modifiersApplied, onlyShownInDescription: true, list); } AddModifierTexts(item.modifiersOnAttachToItem, onlyShownInDescription: false, list); AddDescriptionTexts(item, list); return new Entry(Classify(item, val), SearchableText.Create(list)); } catch (Exception ex) { if (!indexFailureReported) { indexFailureReported = true; RummagePlugin.Log.LogWarning((object)("Could not index item '" + ((Object)item).name + "' for search; it will not match any search or category. Further indexing failures are not logged. " + ex)); } return Unindexed; } } private static void AddModifierTexts(List<ItemModifierContainer> modifiers, bool onlyShownInDescription, List<string> sources) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (modifiers == null) { return; } foreach (ItemModifierContainer modifier in modifiers) { if (modifier == null || (int)modifier.attribute == 0) { continue; } ItemAttribute asset = AssetAccess.GetAsset(modifier.attribute); if (!((Object)(object)asset == (Object)null) && (!onlyShownInDescription || asset.showInItemDescription)) { string text = "ItemAttributes/" + ((object)Unsafe.As<ItemAttributes, ItemAttributes>(ref modifier.attribute)/*cast due to .constrained prefix*/).ToString(); if (asset.simplifiedModAmount) { sources.Add((modifier.value > 0f) ? Translate(text + "_simplifiedIncrease", asset.simplifiedIncreaseString) : Translate(text + "_simplifiedDecrease", asset.simplifiedDecreaseString)); } else { sources.Add(Translate(text + "_itemDescription", asset.itemDescriptionName)); } } } } private static void AddDescriptionTexts(ItemDefinition item, List<string> sources) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Invalid comparison between Unknown and I4 //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_014b: 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_00c1: Invalid comparison between Unknown and I4 //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Invalid comparison between Unknown and I4 //IL_015f: 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_00dd: Invalid comparison between Unknown and I4 //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: 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_021d: Unknown result type (might be due to invalid IL or missing references) if (item.hasCustomDescription) { sources.Add(Translate("Items/" + ((Object)item).name + "_description", null)); } if (item.valueChangeOnItemConsume != null) { foreach (ItemConsumeContainer item2 in item.valueChangeOnItemCo