using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FishNet;
using FishNet.Broadcast;
using FishNet.Connection;
using FishNet.Object;
using FishNet.Serializing;
using FishNet.Transporting;
using HarmonyLib;
using HowtoFishIdentityAPI.Api;
using HowtoFishLocalizationAPI.Api;
using Newtonsoft.Json;
using OwnedItemRecovery.Configuration;
using OwnedItemRecovery.Localization;
using OwnedItemRecovery.Runtime;
using OwnedItemRecovery.UI;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("OwnedItemRecovery")]
[assembly: AssemblyDescription("Owned Item Recovery for How to Fish by Ice Box Studio")]
[assembly: AssemblyCompany("Ice Box Studio")]
[assembly: AssemblyProduct("OwnedItemRecovery")]
[assembly: AssemblyCopyright("Copyright © 2026 Ice Box Studio All rights reserved.")]
[assembly: ComVisible(false)]
[assembly: Guid("73f7f5bf-64e5-4e2a-9bbf-4e7a3f36dcf4")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace OwnedItemRecovery
{
[BepInPlugin("IceBoxStudio.HowToFish.OwnedItemRecovery", "OwnedItemRecovery", "1.0.0")]
[BepInDependency("IceBoxStudio.HowToFish.LocalizationAPI", "1.0.0")]
[BepInDependency("IceBoxStudio.HowToFish.IdentityAPI", "1.0.0")]
public sealed class OwnedItemRecoveryPlugin : BaseUnityPlugin
{
private Harmony _harmony;
internal static ManualLogSource Log { get; private set; }
private void Awake()
{
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
try
{
Log.LogInfo((object)"=============================================");
Log.LogInfo((object)("OwnedItemRecovery " + I18n.Text("plugin.initializing")));
Log.LogInfo((object)(I18n.Text("plugin.author_prefix") + "Ice Box Studio(https://steamcommunity.com/id/ibox666/)"));
ConfigManager.Init(((BaseUnityPlugin)this).Config);
OwnedItemRuntime.Init(((BaseUnityPlugin)this).Logger);
_harmony = new Harmony("IceBoxStudio.HowToFish.OwnedItemRecovery");
_harmony.PatchAll(Assembly.GetExecutingAssembly());
Log.LogInfo((object)("OwnedItemRecovery " + I18n.Text("plugin.initialized")));
Log.LogInfo((object)"=============================================");
}
catch (Exception arg)
{
Log.LogError((object)$"Failed to initialize OwnedItemRecovery: {arg}");
}
}
private void Update()
{
OwnedItemRuntime.Update();
}
}
public static class PluginInfo
{
public const string PLUGIN_GUID = "IceBoxStudio.HowToFish.OwnedItemRecovery";
public const string PLUGIN_NAME = "OwnedItemRecovery";
public const string PLUGIN_VERSION = "1.0.0";
}
}
namespace OwnedItemRecovery.UI
{
internal sealed class OwnedItemUi : MonoBehaviour
{
private static readonly BindingFlags PrivateInstance = BindingFlags.Instance | BindingFlags.NonPublic;
private static OwnedItemUi _current;
private GameObject _pauseHolder;
private GameObject _mainScreen;
private GameObject _optionsScreen;
private GameObject _serverScreen;
private GameObject _root;
private GameObject _buttonTemplate;
private Transform _rows;
private TextMeshProUGUI _title;
private TextMeshProUGUI _summary;
private TextMeshProUGUI _allLabel;
private TextMeshProUGUI _closeLabel;
private Button _allButton;
private bool _open;
private bool _built;
internal static bool IsOpen
{
get
{
if (Object.op_Implicit((Object)(object)_current))
{
return _current._open;
}
return false;
}
}
internal static void Attach()
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
if (!Object.op_Implicit((Object)(object)_current))
{
Transform fXCanvasTrans = PlayerUI.FXCanvasTrans;
if (Object.op_Implicit((Object)(object)fXCanvasTrans))
{
GameObject val = new GameObject("OwnedItemRecovery UI");
val.transform.SetParent(fXCanvasTrans, false);
_current = val.AddComponent<OwnedItemUi>();
_current.TryBuild();
}
}
}
internal static void Open()
{
Attach();
if (Object.op_Implicit((Object)(object)_current))
{
_current.Show();
}
}
internal static void Toggle()
{
if (IsOpen)
{
_current.Hide();
}
else
{
Open();
}
}
internal static void RefreshAll()
{
if (Object.op_Implicit((Object)(object)_current) && _current._open)
{
_current.Refresh();
}
}
internal static void DestroyCurrent()
{
if (Object.op_Implicit((Object)(object)_current))
{
if (Object.op_Implicit((Object)(object)_current._root))
{
Object.Destroy((Object)(object)_current._root);
}
Object.Destroy((Object)(object)((Component)_current).gameObject);
}
_current = null;
}
private bool Build(PauseManager pause, GameObject holder)
{
//IL_0147: Unknown result type (might be due to invalid IL or missing references)
//IL_0151: Expected O, but got Unknown
//IL_0199: Unknown result type (might be due to invalid IL or missing references)
//IL_01a0: Expected O, but got Unknown
//IL_0201: Unknown result type (might be due to invalid IL or missing references)
//IL_0208: Expected O, but got Unknown
//IL_025a: Unknown result type (might be due to invalid IL or missing references)
//IL_026f: Unknown result type (might be due to invalid IL or missing references)
//IL_0284: Unknown result type (might be due to invalid IL or missing references)
//IL_028f: Unknown result type (might be due to invalid IL or missing references)
//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
//IL_02da: Unknown result type (might be due to invalid IL or missing references)
//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
//IL_0306: Unknown result type (might be due to invalid IL or missing references)
//IL_0312: Unknown result type (might be due to invalid IL or missing references)
//IL_0380: Unknown result type (might be due to invalid IL or missing references)
//IL_0387: Expected O, but got Unknown
//IL_045c: Unknown result type (might be due to invalid IL or missing references)
//IL_0466: Expected O, but got Unknown
_pauseHolder = holder;
_mainScreen = GetObject(pause, "_mainScreen");
_optionsScreen = GetObject(pause, "_optionsScreen");
_serverScreen = GetObject(pause, "_serverSettingsScreen");
if (!Object.op_Implicit((Object)(object)_serverScreen))
{
return false;
}
_root = Object.Instantiate<GameObject>(_serverScreen, _pauseHolder.transform, false);
((Object)_root).name = "OwnedItemRecoveryScreen";
_root.SetActive(false);
Transform val = _root.transform.Find("PausedText");
Transform val2 = _root.transform.Find("ServerDisplay");
Transform val3 = _root.transform.Find("LowerButtonHolder/BackButton");
if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)val3))
{
return false;
}
_title = ((Component)val).GetComponent<TextMeshProUGUI>();
_buttonTemplate = ((Component)val3).gameObject;
Button val4 = UseButton(_buttonTemplate);
_closeLabel = GetText(_buttonTemplate);
if ((Object)(object)_title == (Object)null || (Object)(object)val4 == (Object)null || (Object)(object)_closeLabel == (Object)null)
{
return false;
}
((UnityEvent)val4.onClick).AddListener(new UnityAction(Hide));
DisableForeignComponents(((Component)_title).gameObject);
GameObject gameObject = ((Component)val2).gameObject;
TextMeshProUGUI componentInChildren = ((Component)val2).GetComponentInChildren<TextMeshProUGUI>(true);
if ((Object)(object)componentInChildren == (Object)null)
{
return false;
}
foreach (Transform item in _root.transform)
{
Transform val5 = item;
if ((Object)(object)val5 != (Object)(object)val && (Object)(object)val5 != (Object)(object)val2 && (Object)(object)val5 != (Object)(object)val3.parent)
{
((Component)val5).gameObject.SetActive(false);
}
}
foreach (Transform item2 in val2)
{
Transform val6 = item2;
if (((Object)val6).name != "Outline")
{
((Component)val6).gameObject.SetActive(false);
}
}
RectTransform component = gameObject.GetComponent<RectTransform>();
component.anchorMin = new Vector2(0.5f, 0.5f);
component.anchorMax = new Vector2(0.5f, 0.5f);
component.pivot = new Vector2(0.5f, 0.5f);
component.anchoredPosition = Vector2.zero;
component.sizeDelta = new Vector2(860f, 580f);
GameObject val7 = new GameObject("OwnedItemContent");
val7.transform.SetParent(val2, false);
RectTransform val8 = val7.AddComponent<RectTransform>();
val8.anchorMin = Vector2.zero;
val8.anchorMax = Vector2.one;
val8.offsetMin = new Vector2(28f, 24f);
val8.offsetMax = new Vector2(-28f, -24f);
((Transform)val8).localScale = Vector3.one;
((Transform)val8).SetAsLastSibling();
VerticalLayoutGroup obj = val7.AddComponent<VerticalLayoutGroup>();
((HorizontalOrVerticalLayoutGroup)obj).spacing = 8f;
((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true;
((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true;
((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true;
((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false;
_summary = AddText(componentInChildren, (Transform)(object)val8, "Summary", 20f, 32f, (TextAlignmentOptions)514);
BuildRows((Transform)(object)val8, componentInChildren);
GameObject val9 = new GameObject("Footer");
val9.transform.SetParent((Transform)(object)val8, false);
val9.AddComponent<LayoutElement>().preferredHeight = 48f;
HorizontalLayoutGroup obj2 = val9.AddComponent<HorizontalLayoutGroup>();
((HorizontalOrVerticalLayoutGroup)obj2).spacing = 8f;
((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true;
((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true;
((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = true;
((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false;
GameObject val10 = MakeButton(_buttonTemplate, val9.transform, "RecoverAll");
_allButton = GetButton(val10);
_allLabel = GetText(val10);
if ((Object)(object)_allButton == (Object)null || (Object)(object)_allLabel == (Object)null)
{
return false;
}
ConfigureButtonText(_allLabel, 12f, Mathf.Max(18f, ((TMP_Text)_allLabel).fontSize));
((UnityEvent)_allButton.onClick).AddListener(new UnityAction(RecoverAll));
(val10.GetComponent<LayoutElement>() ?? val10.AddComponent<LayoutElement>()).preferredHeight = 48f;
LocalizationApi.LanguageChanged += OnLanguageChanged;
Refresh();
return true;
}
private void BuildRows(Transform parent, TextMeshProUGUI nativeText)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Expected O, but got Unknown
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Expected O, but got Unknown
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00e3: 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_0103: Unknown result type (might be due to invalid IL or missing references)
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_0123: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject("OwnedItemViewport");
val.transform.SetParent(parent, false);
val.AddComponent<LayoutElement>().preferredHeight = 390f;
RectTransform val2 = val.GetComponent<RectTransform>() ?? val.AddComponent<RectTransform>();
((Transform)val2).localScale = Vector3.one;
((Graphic)val.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.08f);
val.AddComponent<RectMask2D>();
ScrollRect obj = val.AddComponent<ScrollRect>();
obj.horizontal = false;
obj.vertical = true;
obj.movementType = (MovementType)1;
obj.scrollSensitivity = 30f;
GameObject val3 = new GameObject("Rows");
val3.transform.SetParent(val.transform, false);
RectTransform val4 = val3.GetComponent<RectTransform>() ?? val3.AddComponent<RectTransform>();
val4.anchorMin = new Vector2(0f, 1f);
val4.anchorMax = new Vector2(1f, 1f);
val4.pivot = new Vector2(0.5f, 1f);
val4.anchoredPosition = Vector2.zero;
val4.sizeDelta = new Vector2(0f, 0f);
((Transform)val4).localScale = Vector3.one;
VerticalLayoutGroup obj2 = val3.AddComponent<VerticalLayoutGroup>();
((HorizontalOrVerticalLayoutGroup)obj2).spacing = 4f;
((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true;
((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true;
((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = true;
((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false;
ContentSizeFitter obj3 = val3.AddComponent<ContentSizeFitter>();
obj3.horizontalFit = (FitMode)0;
obj3.verticalFit = (FitMode)2;
obj.viewport = val2;
obj.content = val4;
_rows = val3.transform;
}
private bool TryBuild()
{
if (_built)
{
return true;
}
PauseManager val = Object.FindAnyObjectByType<PauseManager>();
GameObject val2 = (Object.op_Implicit((Object)(object)val) ? GetObject(val, "_pauseHolder") : null);
if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2))
{
return false;
}
if (Object.op_Implicit((Object)(object)_root))
{
Object.Destroy((Object)(object)_root);
_root = null;
}
if (!Build(val, val2))
{
if (Object.op_Implicit((Object)(object)_root))
{
Object.Destroy((Object)(object)_root);
_root = null;
}
return false;
}
_built = true;
return true;
}
private void Update()
{
if (Object.op_Implicit((Object)(object)Player.LocalPlayer) && !MainMenuManager.IsInMenu && (_built || TryBuild()) && _open && Input.GetKeyDown((KeyCode)27))
{
Hide();
}
}
private void OnDestroy()
{
LocalizationApi.LanguageChanged -= OnLanguageChanged;
if ((Object)(object)_current == (Object)(object)this)
{
_current = null;
}
}
private void OnLanguageChanged(string language)
{
Refresh();
}
private void Show()
{
if (!_built && !TryBuild())
{
return;
}
if (_open)
{
Refresh();
return;
}
_open = true;
_root.SetActive(true);
HideNativeScreens();
PauseManager.TogglePause(true);
HideNativeScreens();
_root.SetActive(true);
Refresh();
if ((Object)(object)EventSystem.current != (Object)null && (Object)(object)_allButton != (Object)null)
{
EventSystem.current.SetSelectedGameObject(((Component)_allButton).gameObject);
}
}
private void Hide()
{
if (_open)
{
_open = false;
if (Object.op_Implicit((Object)(object)_root))
{
_root.SetActive(false);
}
PauseManager.TogglePause(false);
}
}
private void HideNativeScreens()
{
if (Object.op_Implicit((Object)(object)_mainScreen))
{
_mainScreen.SetActive(false);
}
if (Object.op_Implicit((Object)(object)_optionsScreen))
{
_optionsScreen.SetActive(false);
}
if (Object.op_Implicit((Object)(object)_serverScreen))
{
_serverScreen.SetActive(false);
}
}
private void RecoverAll()
{
OwnedItemRuntime.RecoverAll();
}
private void RecoverSingle(int objectId)
{
OwnedItemRuntime.RecoverSingle(objectId);
}
private void Refresh()
{
if ((Object)(object)_title == (Object)null || (Object)(object)_summary == (Object)null || (Object)(object)_allLabel == (Object)null || (Object)(object)_closeLabel == (Object)null || (Object)(object)_rows == (Object)null)
{
return;
}
List<OwnedItemStateBroadcast> clientStates = OwnedItemRuntime.GetClientStates();
int num = 0;
int num2 = 0;
string text2 = default(string);
string text = (((Object)(object)Player.LocalPlayer != (Object)null && IdentityApi.TryGetKey(Player.LocalPlayer, ref text2)) ? text2 : null);
for (int i = 0; i < clientStates.Count; i++)
{
if (!string.IsNullOrEmpty(text) && clientStates[i].PlayerKey == text)
{
num++;
if (clientStates[i].HolderSteamID == 0L)
{
num2++;
}
}
}
((TMP_Text)_title).text = I18n.Text("owned.ui.title");
((TMP_Text)_summary).text = I18n.Text("owned.ui.summary", num, num2);
((TMP_Text)_allLabel).text = I18n.Text("owned.ui.recover_all");
((TMP_Text)_closeLabel).text = I18n.Text("owned.ui.close");
((Selectable)_allButton).interactable = num2 > 0;
RefreshRows(clientStates, text);
}
private void RefreshRows(List<OwnedItemStateBroadcast> states, string localKey)
{
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Expected O, but got Unknown
//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
//IL_02bd: Expected O, but got Unknown
for (int num = _rows.childCount - 1; num >= 0; num--)
{
Object.Destroy((Object)(object)((Component)_rows.GetChild(num)).gameObject);
}
bool flag = false;
for (int i = 0; i < states.Count; i++)
{
OwnedItemStateBroadcast ownedItemStateBroadcast = states[i];
if (string.IsNullOrEmpty(localKey) || ownedItemStateBroadcast.PlayerKey != localKey)
{
continue;
}
flag = true;
GameObject val = new GameObject("OwnedItemRow " + ownedItemStateBroadcast.ObjectId);
val.transform.SetParent(_rows, false);
val.AddComponent<LayoutElement>().preferredHeight = 56f;
HorizontalLayoutGroup obj = val.AddComponent<HorizontalLayoutGroup>();
((HorizontalOrVerticalLayoutGroup)obj).spacing = 8f;
((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true;
((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true;
((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false;
((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false;
string text = (string.IsNullOrWhiteSpace(ownedItemStateBroadcast.OwnerName) ? ownedItemStateBroadcast.PlayerKey : ownedItemStateBroadcast.OwnerName);
string text2 = I18n.Text(ownedItemStateBroadcast.DeathDrop ? "owned.ui.death_drop" : "owned.ui.manual_drop");
string text3 = ((ownedItemStateBroadcast.HolderSteamID == 0L) ? I18n.Text("owned.ui.on_ground") : I18n.Text("owned.ui.on_player", string.IsNullOrWhiteSpace(ownedItemStateBroadcast.HolderName) ? ownedItemStateBroadcast.HolderSteamID.ToString() : ownedItemStateBroadcast.HolderName));
string text4 = I18n.Text("owned.ui.row", ownedItemStateBroadcast.ItemName, text, text2, text3);
TextMeshProUGUI val2 = AddText(GetText(_buttonTemplate), val.transform, "Details", 17f, 56f, (TextAlignmentOptions)513);
((TMP_Text)val2).text = text4;
(((Component)val2).GetComponent<LayoutElement>() ?? ((Component)val2).gameObject.AddComponent<LayoutElement>()).flexibleWidth = 1f;
if (ownedItemStateBroadcast.HolderSteamID != 0L)
{
continue;
}
GameObject val3 = MakeButton(_buttonTemplate, val.transform, "Recover");
Button button = GetButton(val3);
TextMeshProUGUI text5 = GetText(val3);
if ((Object)(object)button == (Object)null || (Object)(object)text5 == (Object)null)
{
Object.Destroy((Object)(object)val3);
continue;
}
((TMP_Text)text5).text = I18n.Text("owned.ui.recover");
ConfigureButtonText(text5, 10f, Mathf.Max(18f, ((TMP_Text)text5).fontSize));
LayoutElement obj2 = val3.GetComponent<LayoutElement>() ?? val3.AddComponent<LayoutElement>();
obj2.preferredWidth = 120f;
obj2.preferredHeight = 56f;
int objectId = ownedItemStateBroadcast.ObjectId;
((UnityEvent)button.onClick).AddListener((UnityAction)delegate
{
RecoverSingle(objectId);
});
}
if (!flag)
{
((TMP_Text)AddText(GetText(_buttonTemplate), _rows, "Empty", 20f, 44f, (TextAlignmentOptions)514)).text = I18n.Text("owned.ui.empty");
}
}
private static TextMeshProUGUI AddText(TextMeshProUGUI template, Transform parent, string name, float size, float height, TextAlignmentOptions alignment)
{
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
TextMeshProUGUI val = Object.Instantiate<TextMeshProUGUI>(template, parent, false);
((Object)((Component)val).gameObject).name = name;
((Component)val).gameObject.SetActive(true);
DisableForeignComponents(((Component)val).gameObject);
((TMP_Text)val).fontSize = size;
((TMP_Text)val).alignment = alignment;
((Graphic)val).raycastTarget = false;
((TMP_Text)val).textWrappingMode = (TextWrappingModes)1;
(((Component)val).GetComponent<LayoutElement>() ?? ((Component)val).gameObject.AddComponent<LayoutElement>()).preferredHeight = height;
return val;
}
private static GameObject MakeButton(GameObject template, Transform parent, string name)
{
GameObject obj = Object.Instantiate<GameObject>(template, parent, false);
((Object)obj).name = name;
obj.SetActive(true);
UseButton(obj);
TextMeshProUGUI text = GetText(obj);
if ((Object)(object)text != (Object)null)
{
((TMP_Text)text).text = string.Empty;
}
return obj;
}
private static void ConfigureButtonText(TextMeshProUGUI text, float minSize, float maxSize)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: 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)
if (!((Object)(object)text == (Object)null))
{
RectTransform rectTransform = ((TMP_Text)text).rectTransform;
rectTransform.anchorMin = Vector2.zero;
rectTransform.anchorMax = Vector2.one;
rectTransform.offsetMin = new Vector2(4f, 2f);
rectTransform.offsetMax = new Vector2(-4f, -2f);
((TMP_Text)text).alignment = (TextAlignmentOptions)514;
((TMP_Text)text).verticalAlignment = (VerticalAlignmentOptions)512;
((TMP_Text)text).enableAutoSizing = true;
((TMP_Text)text).fontSizeMin = minSize;
((TMP_Text)text).fontSizeMax = maxSize;
((TMP_Text)text).textWrappingMode = (TextWrappingModes)0;
((TMP_Text)text).overflowMode = (TextOverflowModes)0;
((TMP_Text)text).characterSpacing = 0f;
((Graphic)text).raycastTarget = false;
}
}
private static Button UseButton(GameObject buttonObject)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected O, but got Unknown
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
Button val = (((Object)(object)buttonObject == (Object)null) ? null : buttonObject.GetComponent<Button>());
if ((Object)(object)val == (Object)null)
{
return null;
}
val.onClick = new ButtonClickedEvent();
Navigation navigation = default(Navigation);
((Navigation)(ref navigation)).mode = (Mode)3;
((Selectable)val).navigation = navigation;
return val;
}
private static Button GetButton(GameObject root)
{
Button[] array = (((Object)(object)root == (Object)null) ? Array.Empty<Button>() : root.GetComponents<Button>());
for (int num = array.Length - 1; num >= 0; num--)
{
if (((Behaviour)array[num]).enabled)
{
return array[num];
}
}
return null;
}
private static TextMeshProUGUI GetText(GameObject root)
{
if (!((Object)(object)root == (Object)null))
{
return root.GetComponentInChildren<TextMeshProUGUI>(true);
}
return null;
}
private static void DisableForeignComponents(GameObject root)
{
if ((Object)(object)root == (Object)null)
{
return;
}
MonoBehaviour[] componentsInChildren = root.GetComponentsInChildren<MonoBehaviour>(true);
foreach (MonoBehaviour val in componentsInChildren)
{
if (!(val is Graphic) && !(val is Selectable) && !(val is TMP_Text) && !(val is Shadow) && !(val is LayoutGroup) && !(val is LayoutElement) && !(val is ContentSizeFitter) && !(val is RectMask2D))
{
((Behaviour)val).enabled = false;
}
}
}
private static GameObject GetObject(PauseManager pause, string field)
{
object? obj = typeof(PauseManager).GetField(field, PrivateInstance)?.GetValue(pause);
return (GameObject)((obj is GameObject) ? obj : null);
}
}
}
namespace OwnedItemRecovery.Runtime
{
public struct OwnedItemStateBroadcast : IBroadcast
{
public int ObjectId;
public string PlayerKey;
public string OwnerName;
public string ItemName;
public bool DeathDrop;
public bool Removed;
public ulong HolderSteamID;
public string HolderName;
public OwnedItemStateBroadcast(int objectId, string playerKey, string ownerName, string itemName, bool deathDrop, bool removed, ulong holderSteamId = 0uL, string holderName = "")
{
ObjectId = objectId;
PlayerKey = playerKey;
OwnerName = ownerName;
ItemName = itemName;
DeathDrop = deathDrop;
Removed = removed;
HolderSteamID = holderSteamId;
HolderName = holderName;
}
}
public struct OwnedItemNoticeBroadcast : IBroadcast
{
public string Key;
public string Arg0;
public string Arg1;
public OwnedItemNoticeBroadcast(string key, string arg0 = "", string arg1 = "")
{
Key = key;
Arg0 = arg0;
Arg1 = arg1;
}
}
[StructLayout(LayoutKind.Sequential, Size = 1)]
public struct RecoverOwnedItemsBroadcast : IBroadcast
{
}
public struct RecoverSingleOwnedItemBroadcast : IBroadcast
{
public int ObjectId;
public RecoverSingleOwnedItemBroadcast(int objectId)
{
ObjectId = objectId;
}
}
[StructLayout(LayoutKind.Sequential, Size = 1)]
public struct SyncOwnedItemsBroadcast : IBroadcast
{
}
internal static class OwnedItemRuntime
{
private sealed class OwnedDrop
{
internal Item Item;
internal string PlayerKey;
internal string OwnerName;
internal string ItemName;
internal byte Island;
internal float DroppedAt;
internal bool DeathDrop;
internal ulong HolderSteamID;
internal string HolderName;
}
private sealed class OwnerMark
{
internal Item Item;
internal string PlayerKey;
internal string OwnerName;
}
[Serializable]
private sealed class OwnedItemSave
{
public List<OwnedDropSave> Drops = new List<OwnedDropSave>();
}
[Serializable]
private sealed class OwnedDropSave
{
public int WorldIndex;
public SavedItem Item;
public string PlayerKey;
public string OwnerName;
public string ItemName;
public byte Island;
public bool DeathDrop;
public long DroppedAtUtcTicks;
}
private static readonly Dictionary<int, OwnedDrop> Drops = new Dictionary<int, OwnedDrop>();
private static readonly Dictionary<int, OwnerMark> OwnerMarks = new Dictionary<int, OwnerMark>();
private static readonly Dictionary<int, OwnedItemStateBroadcast> ClientStates = new Dictionary<int, OwnedItemStateBroadcast>();
private static readonly List<OwnedDropSave> Pending = new List<OwnedDropSave>();
private static ManualLogSource _log;
private static bool _serializersReady;
private static bool _clientRegistered;
private static bool _serverRegistered;
private static int _inputFrame = -1;
private static bool _syncPending;
private static bool _openPending;
private static bool _serverReady;
private static bool _pendingLoaded;
private static bool _worldItemsLoaded;
private static string _savePath;
private static int _worldSpawnIndex;
internal static void Init(ManualLogSource log)
{
_log = log;
if (!_serializersReady)
{
GenericWriter<OwnedItemStateBroadcast>.SetWrite((Action<Writer, OwnedItemStateBroadcast>)WriteState);
GenericReader<OwnedItemStateBroadcast>.SetRead((Func<Reader, OwnedItemStateBroadcast>)ReadState);
GenericWriter<OwnedItemNoticeBroadcast>.SetWrite((Action<Writer, OwnedItemNoticeBroadcast>)WriteNotice);
GenericReader<OwnedItemNoticeBroadcast>.SetRead((Func<Reader, OwnedItemNoticeBroadcast>)ReadNotice);
GenericWriter<RecoverOwnedItemsBroadcast>.SetWrite((Action<Writer, RecoverOwnedItemsBroadcast>)delegate
{
});
GenericReader<RecoverOwnedItemsBroadcast>.SetRead((Func<Reader, RecoverOwnedItemsBroadcast>)((Reader reader) => default(RecoverOwnedItemsBroadcast)));
GenericWriter<RecoverSingleOwnedItemBroadcast>.SetWrite((Action<Writer, RecoverSingleOwnedItemBroadcast>)WriteSingleRequest);
GenericReader<RecoverSingleOwnedItemBroadcast>.SetRead((Func<Reader, RecoverSingleOwnedItemBroadcast>)ReadSingleRequest);
GenericWriter<SyncOwnedItemsBroadcast>.SetWrite((Action<Writer, SyncOwnedItemsBroadcast>)delegate
{
});
GenericReader<SyncOwnedItemsBroadcast>.SetRead((Func<Reader, SyncOwnedItemsBroadcast>)((Reader reader) => default(SyncOwnedItemsBroadcast)));
_serializersReady = true;
}
}
internal static void Update()
{
EnsureNetwork();
TickInput();
if (_syncPending && InstanceFinder.IsClientStarted && (Object)(object)InstanceFinder.ClientManager != (Object)null)
{
InstanceFinder.ClientManager.Broadcast<SyncOwnedItemsBroadcast>(default(SyncOwnedItemsBroadcast), (Channel)0);
_syncPending = false;
}
if (InstanceFinder.IsServerStarted)
{
Prune();
}
}
internal static void TickInput()
{
if (_inputFrame == Time.frameCount)
{
return;
}
_inputFrame = Time.frameCount;
EnsureNetwork();
if (!Object.op_Implicit((Object)(object)Player.LocalPlayer) || ((NetworkBehaviour)Player.LocalPlayer).Owner == (NetworkConnection)null || !((NetworkBehaviour)Player.LocalPlayer).Owner.IsLocalClient || ChatManager.IsTyping)
{
return;
}
bool recoverPressed = ConfigManager.RecoverPressed;
if (recoverPressed && OwnedItemUi.IsOpen)
{
OwnedItemUi.Toggle();
_openPending = false;
return;
}
if (recoverPressed && !PauseManager.IsPaused && !Player.LocalPlayer.BlockInputs && !MainMenuManager.IsInMenu)
{
_openPending = true;
}
if (_openPending && !PauseManager.IsPaused && !Player.LocalPlayer.BlockInputs && !MainMenuManager.IsInMenu)
{
OwnedItemUi.Open();
if (OwnedItemUi.IsOpen)
{
_openPending = false;
}
}
}
internal static void PlayerStarted(Player player)
{
if (!((Object)(object)player == (Object)null) && !(((NetworkBehaviour)player).Owner == (NetworkConnection)null) && ((NetworkBehaviour)player).Owner.IsLocalClient)
{
EnsureNetwork();
ClientStates.Clear();
OwnedItemUi.RefreshAll();
_syncPending = true;
}
}
internal static void PlayerStopped(Player player)
{
if (!((Object)(object)player == (Object)null) && !(((NetworkBehaviour)player).Owner == (NetworkConnection)null) && ((NetworkBehaviour)player).Owner.IsLocalClient)
{
ClientStates.Clear();
_syncPending = false;
_openPending = false;
OwnedItemUi.DestroyCurrent();
}
}
internal static void EnsureNetwork()
{
if (!_clientRegistered && InstanceFinder.IsClientStarted && (Object)(object)InstanceFinder.ClientManager != (Object)null)
{
InstanceFinder.ClientManager.RegisterBroadcast<OwnedItemStateBroadcast>((Action<OwnedItemStateBroadcast, Channel>)OnState);
InstanceFinder.ClientManager.RegisterBroadcast<OwnedItemNoticeBroadcast>((Action<OwnedItemNoticeBroadcast, Channel>)OnNotice);
_clientRegistered = true;
}
if (!_serverRegistered && (Object)(object)InstanceFinder.ServerManager != (Object)null)
{
InstanceFinder.ServerManager.RegisterBroadcast<RecoverOwnedItemsBroadcast>((Action<NetworkConnection, RecoverOwnedItemsBroadcast, Channel>)OnRecoverRequest, true);
InstanceFinder.ServerManager.RegisterBroadcast<RecoverSingleOwnedItemBroadcast>((Action<NetworkConnection, RecoverSingleOwnedItemBroadcast, Channel>)OnRecoverSingleRequest, true);
InstanceFinder.ServerManager.RegisterBroadcast<SyncOwnedItemsBroadcast>((Action<NetworkConnection, SyncOwnedItemsBroadcast, Channel>)OnSyncRequest, true);
_serverRegistered = true;
}
}
internal static void ServerStop()
{
Drops.Clear();
OwnerMarks.Clear();
ClientStates.Clear();
_syncPending = false;
_openPending = false;
OwnedItemUi.DestroyCurrent();
_serverRegistered = false;
_serverReady = false;
_pendingLoaded = false;
_worldItemsLoaded = false;
_savePath = null;
_worldSpawnIndex = 0;
}
internal static void ServerStart()
{
Drops.Clear();
OwnerMarks.Clear();
Pending.Clear();
ClientStates.Clear();
_serverReady = true;
_pendingLoaded = false;
_worldSpawnIndex = 0;
_savePath = SavePath();
_worldItemsLoaded = SaveManager.CurServerSave == null || SaveManager.CurServerSave.WorldItems == null || SaveManager.CurServerSave.WorldItems.Count == 0;
LoadPending();
}
internal static void DeleteSave(string name)
{
string path = SavePath(name);
try
{
if (File.Exists(path))
{
File.Delete(path);
}
}
catch (Exception ex)
{
ManualLogSource log = _log;
if (log != null)
{
log.LogError((object)("Failed to delete owned item save: " + ex));
}
}
}
internal static List<OwnedItemStateBroadcast> GetClientStates()
{
return ClientStates.Values.Where((OwnedItemStateBroadcast state) => !state.Removed).OrderBy<OwnedItemStateBroadcast, string>((OwnedItemStateBroadcast state) => state.OwnerName, StringComparer.OrdinalIgnoreCase).ThenBy<OwnedItemStateBroadcast, string>((OwnedItemStateBroadcast state) => state.ItemName, StringComparer.OrdinalIgnoreCase)
.ToList();
}
internal static void RecoverSingle(int objectId)
{
EnsureNetwork();
if (InstanceFinder.IsClientStarted && (Object)(object)InstanceFinder.ClientManager != (Object)null)
{
InstanceFinder.ClientManager.Broadcast<RecoverSingleOwnedItemBroadcast>(new RecoverSingleOwnedItemBroadcast(objectId), (Channel)0);
}
}
internal static void RecoverAll()
{
EnsureNetwork();
if (InstanceFinder.IsClientStarted && (Object)(object)InstanceFinder.ClientManager != (Object)null)
{
InstanceFinder.ClientManager.Broadcast<RecoverOwnedItemsBroadcast>(default(RecoverOwnedItemsBroadcast), (Channel)0);
}
}
internal static void RegisterDrop(Item item, Player owner, bool deathDrop)
{
string text = default(string);
if (!InstanceFinder.IsServerStarted || (Object)(object)item == (Object)null || (Object)(object)owner == (Object)null || !IdentityApi.TryGetKey(owner, ref text) || item.IsDestroying)
{
return;
}
int objectId = ((NetworkBehaviour)item).ObjectId;
if (objectId >= 0)
{
Drops.TryGetValue(objectId, out var value);
OwnerMarks.TryGetValue(objectId, out var value2);
bool flag = value != null && (Object)(object)value.Item == (Object)(object)item;
bool flag2 = !flag && value2 != null && (Object)(object)value2.Item == (Object)(object)item;
string playerKey = (flag ? value.PlayerKey : (flag2 ? value2.PlayerKey : text));
string ownerName = (flag ? value.OwnerName : (flag2 ? value2.OwnerName : owner.SteamName));
OwnedDrop ownedDrop = new OwnedDrop
{
Item = item,
PlayerKey = playerKey,
OwnerName = ownerName,
ItemName = (flag ? value.ItemName : item.GetName()),
Island = CurrentIsland(),
DroppedAt = Time.time,
DeathDrop = deathDrop,
HolderSteamID = 0uL,
HolderName = ""
};
if (value != null && value.DeathDrop)
{
ownedDrop.DeathDrop = true;
}
Drops[objectId] = ownedDrop;
OwnerMarks[objectId] = new OwnerMark
{
Item = item,
PlayerKey = ownedDrop.PlayerKey,
OwnerName = ownedDrop.OwnerName
};
Broadcast(State(ownedDrop));
}
}
private static void LoadPending()
{
if (_pendingLoaded || string.IsNullOrEmpty(_savePath))
{
return;
}
_pendingLoaded = true;
if (!File.Exists(_savePath))
{
return;
}
try
{
OwnedItemSave ownedItemSave = JsonConvert.DeserializeObject<OwnedItemSave>(File.ReadAllText(_savePath));
if (ownedItemSave == null || ownedItemSave.Drops == null)
{
return;
}
foreach (OwnedDropSave drop in ownedItemSave.Drops)
{
if (drop != null && drop.Item != null && drop.Item.Exists && !string.IsNullOrEmpty(drop.PlayerKey))
{
Pending.Add(drop);
}
}
}
catch (Exception ex)
{
ManualLogSource log = _log;
if (log != null)
{
log.LogError((object)("Failed to load owned item save: " + ex));
}
}
}
internal static void WorldItemSpawned(SavedWorldItem saved, Item item)
{
int worldIndex = _worldSpawnIndex++;
if (SaveManager.CurServerSave != null && SaveManager.CurServerSave.WorldItems != null && _worldSpawnIndex >= SaveManager.CurServerSave.WorldItems.Count)
{
_worldItemsLoaded = true;
}
if (InstanceFinder.IsServerStarted && saved != null && saved.Item != null && !((Object)(object)item == (Object)null))
{
LoadPending();
OwnedDropSave ownedDropSave = Pending.FirstOrDefault((OwnedDropSave entry) => entry.WorldIndex == worldIndex);
if (ownedDropSave != null && ownedDropSave.Item != null && ownedDropSave.Island == CurrentIsland())
{
Pending.Remove(ownedDropSave);
OwnedDrop ownedDrop = new OwnedDrop
{
Item = item,
PlayerKey = ownedDropSave.PlayerKey,
OwnerName = (ownedDropSave.OwnerName ?? ""),
ItemName = (string.IsNullOrEmpty(ownedDropSave.ItemName) ? item.GetName() : ownedDropSave.ItemName),
Island = ownedDropSave.Island,
DroppedAt = Time.time - (float)(DateTime.UtcNow - new DateTime(ownedDropSave.DroppedAtUtcTicks, DateTimeKind.Utc)).TotalSeconds,
DeathDrop = ownedDropSave.DeathDrop,
HolderSteamID = 0uL,
HolderName = ""
};
Drops[((NetworkBehaviour)item).ObjectId] = ownedDrop;
OwnerMarks[((NetworkBehaviour)item).ObjectId] = new OwnerMark
{
Item = item,
PlayerKey = ownedDrop.PlayerKey,
OwnerName = ownedDrop.OwnerName
};
Broadcast(State(ownedDrop));
}
}
}
internal static bool TryGetOwner(Item item, out OwnedItemStateBroadcast state)
{
if ((Object)(object)item != (Object)null && ClientStates.TryGetValue(((NetworkBehaviour)item).ObjectId, out state))
{
return !state.Removed;
}
state = default(OwnedItemStateBroadcast);
return false;
}
internal static string GetHoverText(Item item)
{
if (!ConfigManager.ShowOwnershipOnHover || !TryGetOwner(item, out var state))
{
return null;
}
string text = default(string);
string key = (((Object)(object)Player.LocalPlayer != (Object)null && IdentityApi.TryGetKey(Player.LocalPlayer, ref text) && text == state.PlayerKey) ? "owned.hover.self" : "owned.hover.other");
return item.GetName() + "\n" + SpriteManager.GetPickUpInput() + "\n" + I18n.Text(key, state.OwnerName);
}
internal static bool CanPick(Item item, Player picker)
{
if (!ConfigManager.RestrictOwnedItems || (Object)(object)item == (Object)null || (Object)(object)picker == (Object)null || !Drops.TryGetValue(((NetworkBehaviour)item).ObjectId, out var value))
{
return true;
}
string text = default(string);
if (IdentityApi.TryGetKey(picker, ref text) && value.PlayerKey == text)
{
return true;
}
SendNotice(((NetworkBehaviour)picker).Owner, "owned.restrict.denied", value.OwnerName);
return false;
}
internal static void Picked(Item item, Player picker)
{
if (InstanceFinder.IsServerStarted && !((Object)(object)item == (Object)null) && !((Object)(object)picker == (Object)null) && Drops.TryGetValue(((NetworkBehaviour)item).ObjectId, out var value) && !((Object)(object)item.SyncedHolder != (Object)(object)picker))
{
string text = default(string);
if (!IdentityApi.TryGetKey(picker, ref text) || value.PlayerKey != text)
{
value.HolderSteamID = picker.SteamID;
value.HolderName = picker.SteamName;
Broadcast(State(value));
SendNotice(((NetworkBehaviour)picker).Owner, "owned.item.picked_by", value.Item.ID.ToString(), value.OwnerName);
}
else
{
Drops.Remove(((NetworkBehaviour)item).ObjectId);
OwnerMarks.Remove(((NetworkBehaviour)item).ObjectId);
Broadcast(new OwnedItemStateBroadcast(((NetworkBehaviour)item).ObjectId, value.PlayerKey, value.OwnerName, value.ItemName, value.DeathDrop, removed: true, 0uL));
SendNotice(((NetworkBehaviour)picker).Owner, "owned.item.recovered", value.Item.ID.ToString());
}
}
}
internal static void Destroyed(Item item)
{
if (!((Object)(object)item == (Object)null))
{
bool num = Drops.Remove(((NetworkBehaviour)item).ObjectId);
OwnerMarks.Remove(((NetworkBehaviour)item).ObjectId);
if (num)
{
Broadcast(new OwnedItemStateBroadcast(((NetworkBehaviour)item).ObjectId, null, "", "", deathDrop: false, removed: true, 0uL));
}
}
}
internal static void BirdCaught(Item item)
{
if (InstanceFinder.IsServerStarted && !((Object)(object)item == (Object)null))
{
bool num = Drops.Remove(((NetworkBehaviour)item).ObjectId);
OwnerMarks.Remove(((NetworkBehaviour)item).ObjectId);
if (num)
{
Broadcast(new OwnedItemStateBroadcast(((NetworkBehaviour)item).ObjectId, null, "", "", deathDrop: false, removed: true, 0uL));
}
}
}
internal static void SendAll(NetworkConnection connection)
{
if ((Object)(object)InstanceFinder.ServerManager == (Object)null || connection == (NetworkConnection)null)
{
return;
}
foreach (OwnedDrop value in Drops.Values)
{
InstanceFinder.ServerManager.Broadcast<OwnedItemStateBroadcast>(connection, State(value), true, (Channel)0);
}
}
private static void OnRecoverRequest(NetworkConnection connection, RecoverOwnedItemsBroadcast message, Channel channel)
{
Player val = FindPlayer(connection);
if (!((Object)(object)val == (Object)null) && !((Object)(object)val.Transform == (Object)null))
{
Recover(connection, val, null);
}
}
private static void OnRecoverSingleRequest(NetworkConnection connection, RecoverSingleOwnedItemBroadcast message, Channel channel)
{
Player val = FindPlayer(connection);
if (!((Object)(object)val == (Object)null) && !((Object)(object)val.Transform == (Object)null))
{
Recover(connection, val, message.ObjectId);
}
}
private static void Recover(NetworkConnection connection, Player player, int? objectId)
{
if (objectId.HasValue && !Drops.ContainsKey(objectId.Value))
{
SendNotice(connection, "owned.recover.missing");
return;
}
byte island = CurrentIsland();
float range = ConfigManager.RecoverRange;
float rangeSq = range * range;
List<OwnedDrop> list = Drops.Values.Where(delegate(OwnedDrop drop)
{
//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0102: Unknown result type (might be due to invalid IL or missing references)
//IL_0107: Unknown result type (might be due to invalid IL or missing references)
string text = default(string);
if ((!objectId.HasValue || ((Object)(object)drop.Item != (Object)null && ((NetworkBehaviour)drop.Item).ObjectId == objectId.Value)) && IdentityApi.TryGetKey(player, ref text) && drop.PlayerKey == text && drop.Island == island && (Object)(object)drop.Item != (Object)null && !drop.Item.IsDestroying && !((NetworkBehaviour)drop.Item).IsDeinitializing && drop.Item.IsInteractable && (Object)(object)drop.Item.SyncedHolder == (Object)null && ((Component)((Component)drop.Item).transform).gameObject.activeInHierarchy)
{
if (!(range <= 0f))
{
Vector3 val = ((Component)drop.Item).transform.position - player.Transform.position;
if (!(((Vector3)(ref val)).sqrMagnitude <= rangeSq))
{
goto IL_0121;
}
}
return !Expired(drop);
}
goto IL_0121;
IL_0121:
return false;
}).OrderBy(delegate(OwnedDrop drop)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: 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)
Vector3 val = ((Component)drop.Item).transform.position - player.Transform.position;
return ((Vector3)(ref val)).sqrMagnitude;
}).Take(objectId.HasValue ? 1 : ConfigManager.RecoverBatchLimit)
.ToList();
int num = 0;
foreach (OwnedDrop item2 in list)
{
Item item = item2.Item;
item.SetSyncedHolder(player, false);
if (player.Inventory.ServerTryStoreHeldItem(item))
{
Drops.Remove(((NetworkBehaviour)item).ObjectId);
OwnerMarks.Remove(((NetworkBehaviour)item).ObjectId);
Broadcast(new OwnedItemStateBroadcast(((NetworkBehaviour)item).ObjectId, item2.PlayerKey, item2.OwnerName, item2.ItemName, item2.DeathDrop, removed: true, 0uL));
num++;
}
else
{
item.SetSyncedHolder((Player)null, false);
}
}
if (objectId.HasValue)
{
SendNotice(connection, (num == 1) ? "owned.recover.single" : ((list.Count == 0) ? "owned.recover.missing" : "owned.recover.no_space"));
return;
}
string key = ((list.Count == 0) ? "owned.recover.empty" : ((num == 0) ? "owned.recover.no_space" : ((num == list.Count) ? "owned.recover.full" : "owned.recover.partial")));
SendNotice(connection, key, num.ToString(), list.Count.ToString());
}
private static void OnSyncRequest(NetworkConnection connection, SyncOwnedItemsBroadcast message, Channel channel)
{
Prune();
SendAll(connection);
}
private static void Prune()
{
byte b = CurrentIsland();
List<int> list = new List<int>();
foreach (KeyValuePair<int, OwnedDrop> drop in Drops)
{
OwnedDrop value = drop.Value;
if ((Object)(object)value.Item == (Object)null || value.Item.IsDestroying || ((NetworkBehaviour)value.Item).IsDeinitializing || (Object)(object)value.Item.BirdHolder != (Object)null || value.Island != b || Expired(value))
{
list.Add(drop.Key);
}
}
foreach (int item in list)
{
Drops.Remove(item);
OwnerMarks.Remove(item);
Broadcast(new OwnedItemStateBroadcast(item, null, "", "", deathDrop: false, removed: true, 0uL));
}
}
private static Player FindPlayer(string playerKey)
{
string text = default(string);
foreach (Player player in PlayerManager.Players)
{
if ((Object)(object)player != (Object)null && IdentityApi.TryGetKey(player, ref text) && text == playerKey)
{
return player;
}
}
return null;
}
private static Player FindPlayer(NetworkConnection connection)
{
if (connection == (NetworkConnection)null)
{
return null;
}
foreach (Player player in PlayerManager.Players)
{
if ((Object)(object)player != (Object)null && ((NetworkBehaviour)player).Owner != (NetworkConnection)null && ((NetworkBehaviour)player).Owner.ClientId == connection.ClientId)
{
return player;
}
}
return null;
}
private static byte CurrentIsland()
{
if (!((Object)(object)OnlineIslandManager.Instance == (Object)null))
{
return OnlineIslandManager.CurIsland;
}
return byte.MaxValue;
}
private static void Broadcast(OwnedItemStateBroadcast message)
{
EnsureNetwork();
if ((Object)(object)InstanceFinder.ServerManager != (Object)null)
{
InstanceFinder.ServerManager.Broadcast<OwnedItemStateBroadcast>(message, true, (Channel)0);
}
}
private static void SendNotice(NetworkConnection connection, string key, string arg0 = "", string arg1 = "")
{
EnsureNetwork();
if (connection != (NetworkConnection)null && (Object)(object)InstanceFinder.ServerManager != (Object)null)
{
InstanceFinder.ServerManager.Broadcast<OwnedItemNoticeBroadcast>(connection, new OwnedItemNoticeBroadcast(key, arg0, arg1), true, (Channel)0);
}
}
private static void OnState(OwnedItemStateBroadcast message, Channel channel)
{
if (message.Removed)
{
ClientStates.Remove(message.ObjectId);
}
else
{
ClientStates[message.ObjectId] = message;
}
OwnedItemUi.RefreshAll();
}
private static void OnNotice(OwnedItemNoticeBroadcast message, Channel channel)
{
if (!string.IsNullOrWhiteSpace(message.Key))
{
string text = message.Arg0;
if (IsItemNotice(message.Key) && byte.TryParse(text, out var result))
{
Item val = GameInfo.IDToItem(result);
text = (((Object)(object)val == (Object)null) ? message.Arg0 : val.GetName());
}
ChatManager.ChatMessage("<i>" + I18n.Text(message.Key, text, message.Arg1) + "</i>");
}
}
private static bool IsItemNotice(string key)
{
if (!(key == "owned.item.recovered") && !(key == "owned.item.picked_by"))
{
return key == "owned.item.lost";
}
return true;
}
private static void WriteState(Writer writer, OwnedItemStateBroadcast message)
{
writer.WriteInt32(message.ObjectId);
writer.WriteString(message.PlayerKey);
writer.WriteString(message.OwnerName);
writer.WriteString(message.ItemName);
writer.WriteBoolean(message.DeathDrop);
writer.WriteBoolean(message.Removed);
writer.WriteUInt64(message.HolderSteamID);
writer.WriteString(message.HolderName);
}
private static OwnedItemStateBroadcast ReadState(Reader reader)
{
return new OwnedItemStateBroadcast(reader.ReadInt32(), reader.ReadStringAllocated(), reader.ReadStringAllocated(), reader.ReadStringAllocated(), reader.ReadBoolean(), reader.ReadBoolean(), reader.ReadUInt64(), reader.ReadStringAllocated());
}
private static void WriteSingleRequest(Writer writer, RecoverSingleOwnedItemBroadcast message)
{
writer.WriteInt32(message.ObjectId);
}
private static RecoverSingleOwnedItemBroadcast ReadSingleRequest(Reader reader)
{
return new RecoverSingleOwnedItemBroadcast(reader.ReadInt32());
}
private static void WriteNotice(Writer writer, OwnedItemNoticeBroadcast message)
{
writer.WriteString(message.Key);
writer.WriteString(message.Arg0);
writer.WriteString(message.Arg1);
}
private static OwnedItemNoticeBroadcast ReadNotice(Reader reader)
{
return new OwnedItemNoticeBroadcast(reader.ReadStringAllocated(), reader.ReadStringAllocated(), reader.ReadStringAllocated());
}
internal static void AfterNativeSave()
{
if (!InstanceFinder.IsServerStarted || !_serverReady || string.IsNullOrEmpty(_savePath) || SaveManager.CurServerSave == null || SaveManager.CurServerSave.WorldItems == null || !_worldItemsLoaded)
{
return;
}
try
{
List<OwnedDropSave> list = new List<OwnedDropSave>();
HashSet<int> used = new HashSet<int>();
List<SavedWorldItem> worldItems = SaveManager.CurServerSave.WorldItems;
for (int i = 0; i < worldItems.Count; i++)
{
OwnedDrop ownedDrop = FindDrop(worldItems[i], used);
if (ownedDrop != null)
{
list.Add(new OwnedDropSave
{
WorldIndex = i,
Item = CaptureItem(ownedDrop.Item),
PlayerKey = ownedDrop.PlayerKey,
OwnerName = ownedDrop.OwnerName,
ItemName = ownedDrop.ItemName,
Island = ownedDrop.Island,
DeathDrop = ownedDrop.DeathDrop,
DroppedAtUtcTicks = DateTime.UtcNow.AddSeconds(0f - (Time.time - ownedDrop.DroppedAt)).Ticks
});
}
}
WriteSave(list);
}
catch (Exception ex)
{
ManualLogSource log = _log;
if (log != null)
{
log.LogError((object)("Failed to save owned item save: " + ex));
}
}
}
private static OwnedDrop FindDrop(SavedWorldItem worldItem, HashSet<int> used)
{
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
if (worldItem == null || worldItem.Item == null)
{
return null;
}
OwnedDrop ownedDrop = null;
float num = float.PositiveInfinity;
float num2 = float.PositiveInfinity;
foreach (OwnedDrop value in Drops.Values)
{
if (!((Object)(object)value.Item == (Object)null) && !used.Contains(((NetworkBehaviour)value.Item).ObjectId) && CanSave(value.Item) && value.Item.ID == worldItem.Item.ItemID)
{
Vector3 val = ((Component)value.Item).transform.position - worldItem.Position;
float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
float num3 = Quaternion.Angle(((Component)value.Item).transform.rotation, worldItem.Rotation);
if (sqrMagnitude < num || (sqrMagnitude == num && num3 < num2))
{
num = sqrMagnitude;
num2 = num3;
ownedDrop = value;
}
}
}
if (ownedDrop != null)
{
used.Add(((NetworkBehaviour)ownedDrop.Item).ObjectId);
}
return ownedDrop;
}
private static void WriteSave(List<OwnedDropSave> entries)
{
string directoryName = Path.GetDirectoryName(_savePath);
if (!Directory.Exists(directoryName))
{
Directory.CreateDirectory(directoryName);
}
OwnedItemSave ownedItemSave = new OwnedItemSave();
ownedItemSave.Drops.AddRange(entries);
File.WriteAllText(_savePath, JsonConvert.SerializeObject((object)ownedItemSave));
}
private static bool CanSave(Item item)
{
if ((Object)(object)item == (Object)null || !((NetworkBehaviour)item).IsServerInitialized || item.IsDestroying || ((NetworkBehaviour)item).IsDeinitializing || (Object)(object)item.SyncedHolder != (Object)null || (Object)(object)item.Holder != (Object)null || item.IsInInventory || (Object)(object)item.BirdHolder != (Object)null || (Object)(object)item.AttachedRod != (Object)null || (Object)(object)item.DeadPlayer != (Object)null || item.IgnoredByCloseDots)
{
return false;
}
if (!((Object)(object)item.Creature == (Object)null))
{
return item.Creature.IsDead;
}
return true;
}
private static SavedItem CaptureItem(Item item)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: 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_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: 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_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: 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_0105: Unknown result type (might be due to invalid IL or missing references)
//IL_012c: 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_0176: Expected O, but got Unknown
return new SavedItem
{
Exists = true,
ItemID = item.ID,
Cookness = item.Cookness,
BettingMultiplier = item.BettingMultiplier,
IsDripCreature = ((Object)(object)item.Creature != (Object)null && item.Creature.IsDrip),
Weight = (((Object)(object)item.Creature != (Object)null) ? ((Item)item.Creature).RandomizedWeight : 1f),
KillScoreMultiplier = item.KillScoreMultiplier,
SkinIndex = item.CurSkin,
Sight = (byte)(((Object)(object)item.Weapon != (Object)null) ? item.Weapon.Attachments.Sight : 0),
BarrelAttachment = (byte)(((Object)(object)item.Weapon != (Object)null) ? item.Weapon.Attachments.BarrelAttachment : 0),
AmmoType = (byte)(((Object)(object)item.Weapon != (Object)null) ? item.Weapon.Attachments.AmmoType : 0),
ExtendedMag = ((Object)(object)item.Weapon != (Object)null && item.Weapon.Attachments.ExtendedMag),
LaserSight = ((Object)(object)item.Weapon != (Object)null && item.Weapon.Attachments.LaserSight),
Sharpness = (byte)(((Object)(object)item.Melee != (Object)null) ? item.Melee.SharpnessIndex : 0)
};
}
private static string SavePath()
{
return SavePath(SaveManager.CurServerSave.Name);
}
private static string SavePath(string name)
{
char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
foreach (char oldChar in invalidFileNameChars)
{
name = name.Replace(oldChar, '_');
}
return Path.Combine(Application.persistentDataPath, "Saves", name + ".OwnedItemRecovery.json");
}
private static bool Expired(OwnedDrop drop)
{
float ownershipTimeout = ConfigManager.OwnershipTimeout;
if (ownershipTimeout > 0f)
{
return Time.time - drop.DroppedAt > ownershipTimeout;
}
return false;
}
private static OwnedItemStateBroadcast State(OwnedDrop drop)
{
return new OwnedItemStateBroadcast(((NetworkBehaviour)drop.Item).ObjectId, drop.PlayerKey, drop.OwnerName, drop.ItemName, drop.DeathDrop, removed: false, drop.HolderSteamID, drop.HolderName);
}
}
}
namespace OwnedItemRecovery.Patches
{
[HarmonyPatch(typeof(Item), "SetSyncedHolder")]
internal static class ItemDropPatch
{
private static void Prefix(Item __instance, ref Player __state)
{
__state = (((Object)(object)__instance == (Object)null) ? null : __instance.SyncedHolder);
}
private static void Postfix(Item __instance, Player newHolder, Player __state)
{
if ((Object)(object)__instance != (Object)null && (Object)(object)newHolder == (Object)null && (Object)(object)__state != (Object)null && (Object)(object)__instance.SyncedHolder == (Object)null && !__instance.IsInInventory)
{
OwnedItemRuntime.RegisterDrop(__instance, __state, deathDrop: false);
}
}
}
[HarmonyPatch(typeof(PlayerInventory), "ServerDropAll")]
internal static class InventoryDeathDropPatch
{
private static void Prefix(PlayerInventory __instance, Player ____player)
{
if ((Object)(object)__instance == (Object)null || (Object)(object)____player == (Object)null)
{
return;
}
if ((Object)(object)____player.Holding.HeldItem != (Object)null)
{
OwnedItemRuntime.RegisterDrop(____player.Holding.HeldItem, ____player, deathDrop: true);
}
foreach (KeyValuePair<byte, Item> item in __instance._items)
{
if ((Object)(object)item.Value != (Object)null)
{
OwnedItemRuntime.RegisterDrop(item.Value, ____player, deathDrop: true);
}
}
}
}
[HarmonyPatch(typeof(Server), "RpcLogic___SetItemHolder___3876263354")]
internal static class ItemPickupPatch
{
private static bool Prefix(Item __0, Player __1)
{
return OwnedItemRuntime.CanPick(__0, __1);
}
private static void Postfix(Item __0, Player __1)
{
OwnedItemRuntime.Picked(__0, __1);
}
}
[HarmonyPatch(typeof(Item), "DestroyItem")]
internal static class ItemDestroyPatch
{
private static void Prefix(Item __instance)
{
OwnedItemRuntime.Destroyed(__instance);
}
}
[HarmonyPatch(typeof(Item), "TryCaughtByBird", new Type[] { typeof(Bird) })]
internal static class ItemBirdCatchPatch
{
private static void Postfix(Item __instance, bool __result)
{
if (__result)
{
OwnedItemRuntime.BirdCaught(__instance);
}
}
}
[HarmonyPatch(typeof(ItemManager), "SpawnSavedItem")]
internal static class SavedWorldItemPatch
{
private static void Postfix(SavedWorldItem __0, Item __result)
{
OwnedItemRuntime.WorldItemSpawned(__0, __result);
}
}
[HarmonyPatch(typeof(Item), "Hover")]
internal static class ItemHoverPatch
{
private static void Postfix(Item __instance, ref string ____hoverString)
{
string hoverText = OwnedItemRuntime.GetHoverText(__instance);
if (!string.IsNullOrEmpty(hoverText))
{
PlayerUI.UpdateLookAtText(hoverText);
____hoverString = hoverText;
}
}
}
[HarmonyPatch(typeof(PlayerDying), "ServerDie")]
internal static class PlayerDeathDropPatch
{
private static void Prefix(PlayerDying __instance, Player ____player)
{
if ((Object)(object)__instance != (Object)null && (Object)(object)____player != (Object)null && (Object)(object)__instance.DeadPlayer == (Object)null && (Object)(object)____player.Holding.HeldItem != (Object)null)
{
OwnedItemRuntime.RegisterDrop(____player.Holding.HeldItem, ____player, deathDrop: true);
}
}
}
[HarmonyPatch(typeof(Player), "OnStartClient")]
internal static class PlayerStartPatch
{
private static void Postfix(Player __instance)
{
if ((Object)(object)__instance != (Object)null && ((NetworkBehaviour)__instance).Owner != (NetworkConnection)null && ((NetworkBehaviour)__instance).Owner.IsLocalClient)
{
OwnedItemRuntime.PlayerStarted(__instance);
}
}
}
[HarmonyPatch(typeof(Player), "OnStopClient")]
internal static class PlayerStopPatch
{
private static void Postfix(Player __instance)
{
if ((Object)(object)__instance != (Object)null && ((NetworkBehaviour)__instance).Owner != (NetworkConnection)null && ((NetworkBehaviour)__instance).Owner.IsLocalClient)
{
OwnedItemRuntime.PlayerStopped(__instance);
}
}
}
[HarmonyPatch(typeof(Server), "OnStopServer")]
internal static class ServerStopPatch
{
private static void Postfix()
{
OwnedItemRuntime.ServerStop();
}
}
[HarmonyPatch(typeof(MoneyManager), "OnStartServer")]
internal static class ServerStartPatch
{
private static void Postfix()
{
OwnedItemRuntime.ServerStart();
}
}
[HarmonyPatch(typeof(SaveManager), "SaveServer")]
internal static class SaveServerPatch
{
private static void Postfix()
{
OwnedItemRuntime.AfterNativeSave();
}
}
[HarmonyPatch(typeof(SaveManager), "DeleteServer")]
internal static class DeleteServerPatch
{
private static string _name;
private static void Prefix()
{
_name = ((SaveManager.CurServerSave == null) ? null : SaveManager.CurServerSave.Name);
}
private static void Postfix()
{
if (!string.IsNullOrEmpty(_name))
{
OwnedItemRuntime.DeleteSave(_name);
}
_name = null;
}
}
[HarmonyPatch(typeof(PlayerUI), "Update")]
internal static class OwnedItemInputPatch
{
private static void Postfix()
{
OwnedItemRuntime.TickInput();
}
}
}
namespace OwnedItemRecovery.Localization
{
internal static class I18n
{
private const string FileName = "OwnedItemRecovery.Localization.json";
private static readonly ModLocalizer _localizer = Load();
internal static string Text(string key, params object[] args)
{
return _localizer.GetLocalizedText(key, args);
}
private static ModLocalizer Load()
{
string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
ModLocalizer obj = LocalizationApi.For("IceBoxStudio.HowToFish.OwnedItemRecovery");
obj.RegisterJson(Path.Combine(directoryName, "OwnedItemRecovery.Localization.json"));
return obj;
}
}
}
namespace OwnedItemRecovery.Configuration
{
internal static class ConfigManager
{
private static ConfigEntry<KeyboardShortcut> _recoverKey;
private static ConfigEntry<float> _recoverRange;
private static ConfigEntry<int> _recoverBatchLimit;
private static ConfigEntry<bool> _showOwnershipOnHover;
private static ConfigEntry<bool> _notifyOwnerWhenPicked;
private static ConfigEntry<bool> _restrictOwnedItems;
private static ConfigEntry<float> _ownershipTimeout;
internal static bool RecoverPressed
{
get
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
if (_recoverKey != null)
{
KeyboardShortcut value = _recoverKey.Value;
return ((KeyboardShortcut)(ref value)).IsDown();
}
return false;
}
}
internal static float RecoverRange => Mathf.Max(0f, (_recoverRange == null) ? 0f : _recoverRange.Value);
internal static int RecoverBatchLimit => Mathf.Clamp((_recoverBatchLimit == null) ? 32 : _recoverBatchLimit.Value, 1, 128);
internal static bool ShowOwnershipOnHover
{
get
{
if (_showOwnershipOnHover != null)
{
return _showOwnershipOnHover.Value;
}
return true;
}
}
internal static bool NotifyOwnerWhenPicked
{
get
{
if (_notifyOwnerWhenPicked != null)
{
return _notifyOwnerWhenPicked.Value;
}
return true;
}
}
internal static bool RestrictOwnedItems
{
get
{
if (_restrictOwnedItems != null)
{
return _restrictOwnedItems.Value;
}
return false;
}
}
internal static float OwnershipTimeout
{
get
{
if (_ownershipTimeout != null)
{
return _ownershipTimeout.Value;
}
return 1800f;
}
}
internal static void Init(ConfigFile config)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
_recoverKey = config.Bind<KeyboardShortcut>("Controls", "RecoverOwnedItems", new KeyboardShortcut((KeyCode)111, Array.Empty<KeyCode>()), I18n.Text("config.recover_key"));
_recoverRange = config.Bind<float>("Gameplay", "RecoverRange", 0f, I18n.Text("config.recover_range"));
_recoverBatchLimit = config.Bind<int>("Gameplay", "RecoverBatchLimit", 32, I18n.Text("config.recover_limit"));
_showOwnershipOnHover = config.Bind<bool>("Gameplay", "ShowOwnershipOnHover", true, I18n.Text("config.show_hover"));
_notifyOwnerWhenPicked = config.Bind<bool>("Gameplay", "NotifyOwnerWhenPicked", true, I18n.Text("config.notify_owner"));
_restrictOwnedItems = config.Bind<bool>("Gameplay", "RestrictOwnedItems", false, I18n.Text("config.restrict"));
_ownershipTimeout = config.Bind<float>("Gameplay", "OwnershipTimeout", 1800f, I18n.Text("config.timeout"));
}
}
}