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.Versioning;
using BepInEx;
using BepInEx.Configuration;
using FishNet.Object;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("HowToFishDroppedPersistence")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("HowToFishDroppedPersistence")]
[assembly: AssemblyTitle("HowToFishDroppedPersistence")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace HowToFishDroppedPersistence
{
[BepInPlugin("local.howtofish.droppedpersistence", "How to Fish Dropped Item Persistence", "1.1.0")]
public sealed class Plugin : BaseUnityPlugin
{
[Serializable]
private sealed class PersistenceFile
{
public int Version = 1;
public string ServerName;
public DroppedItemRecord[] Items = Array.Empty<DroppedItemRecord>();
}
[Serializable]
private sealed class DroppedItemRecord
{
public bool Exists = true;
public byte InventorySlot = byte.MaxValue;
public byte ItemId;
public float PositionX;
public float PositionY;
public float PositionZ;
public float RotationX;
public float RotationY;
public float RotationZ;
public float RotationW;
public float Cookness;
public float BettingMultiplier = 1f;
public float Weight = 1f;
public float KillScoreMultiplier = 1f;
public byte SkinIndex;
public bool IsDripCreature;
public byte Sharpness;
public byte Sight;
public byte BarrelAttachment;
public byte AmmoType;
public bool ExtendedMag;
public bool LaserSight;
public float LinearVelocityX;
public float LinearVelocityY;
public float LinearVelocityZ;
public float AngularVelocityX;
public float AngularVelocityY;
public float AngularVelocityZ;
}
public const string PluginGuid = "local.howtofish.droppedpersistence";
public const string PluginName = "How to Fish Dropped Item Persistence";
public const string PluginVersion = "1.1.0";
private ConfigEntry<bool> _enabled;
private ConfigEntry<int> _maxItems;
private readonly HashSet<int> _baselineItems = new HashSet<int>();
private readonly HashSet<int> _trackedDroppedItems = new HashSet<int>();
private readonly HashSet<int> _seenHeldItems = new HashSet<int>();
private bool _loaded;
private bool _baselineCaptured;
private string _path;
private float _nextSave;
private float _restoreAt;
private bool _quitting;
private bool _errorLogged;
private void Awake()
{
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Expected O, but got Unknown
_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable dropped item persistence");
_maxItems = ((BaseUnityPlugin)this).Config.Bind<int>("Persistence", "MaxDroppedItems", 256, new ConfigDescription("Maximum dropped items saved per server", (AcceptableValueBase)(object)new AcceptableValueRange<int>(32, 1024), Array.Empty<object>()));
((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded How to Fish Dropped Item Persistence 1.1.0.");
}
private void OnApplicationQuit()
{
_quitting = true;
}
private void Update()
{
if (!_enabled.Value || _quitting || !Object.op_Implicit((Object)(object)Player.LocalPlayer))
{
return;
}
if (!Object.op_Implicit((Object)(object)Server.Instance) || !((NetworkBehaviour)Server.Instance).IsServerInitialized || !Object.op_Implicit((Object)(object)ItemManager.Instance) || SaveManager.CurServerSave == null)
{
_loaded = false;
_path = null;
_baselineCaptured = false;
_baselineItems.Clear();
_trackedDroppedItems.Clear();
_seenHeldItems.Clear();
return;
}
string persistencePath = GetPersistencePath();
if (!_loaded || !string.Equals(_path, persistencePath, StringComparison.OrdinalIgnoreCase))
{
_path = persistencePath;
_loaded = true;
_baselineCaptured = false;
_baselineItems.Clear();
_trackedDroppedItems.Clear();
_seenHeldItems.Clear();
_restoreAt = Time.unscaledTime + 1.25f;
_nextSave = Time.unscaledTime + 0.25f;
}
if (!_baselineCaptured)
{
if (Time.unscaledTime < _restoreAt && ItemManager.Items.Count == 0)
{
return;
}
CaptureBaseline();
Restore(persistencePath);
}
Track();
if (Time.unscaledTime >= _nextSave)
{
_nextSave = Time.unscaledTime + 0.5f;
Save(persistencePath);
}
}
private string GetPersistencePath()
{
string text = ((SaveManager.CurServerSave != null) ? SaveManager.CurServerSave.Name : "default");
if (string.IsNullOrWhiteSpace(text))
{
text = "default";
}
string text2 = string.Concat(text.Select((char value) => (!char.IsLetterOrDigit(value)) ? '_' : value));
if (string.IsNullOrWhiteSpace(text2))
{
text2 = "default";
}
return Path.Combine(Paths.ConfigPath, "local.howtofish.droppedpersistence.drops." + text2 + ".json");
}
private string GetLegacyPath()
{
string text = ((SaveManager.CurServerSave != null) ? SaveManager.CurServerSave.Name : "default");
if (string.IsNullOrWhiteSpace(text))
{
text = "default";
}
string text2 = string.Concat(text.Select((char value) => (!char.IsLetterOrDigit(value)) ? '_' : value));
if (string.IsNullOrWhiteSpace(text2))
{
text2 = "default";
}
return Path.Combine(Paths.ConfigPath, "local.howtofish.funpack.drops." + text2 + ".json");
}
private void Track()
{
HashSet<int> liveItems = new HashSet<int>();
Item[] array = ItemManager.Items.Values.ToArray();
foreach (Item val in array)
{
if (!Object.op_Implicit((Object)(object)val) || ((NetworkBehaviour)val).IsDeinitializing)
{
continue;
}
int instanceID = ((Object)val).GetInstanceID();
liveItems.Add(instanceID);
if (Object.op_Implicit((Object)(object)val.Holder) || Object.op_Implicit((Object)(object)val.SyncedHolder) || Object.op_Implicit((Object)(object)val.LastHolder) || val.IsInInventory)
{
_seenHeldItems.Add(instanceID);
}
if (Object.op_Implicit((Object)(object)val.Holder) || Object.op_Implicit((Object)(object)val.SyncedHolder) || val.IsInInventory || Object.op_Implicit((Object)(object)val.AttachedRod) || Object.op_Implicit((Object)(object)val.BirdHolder) || Object.op_Implicit((Object)(object)val.DeadPlayer))
{
_trackedDroppedItems.Remove(instanceID);
}
else if (!_baselineItems.Contains(instanceID) || _seenHeldItems.Contains(instanceID) || Object.op_Implicit((Object)(object)val.LastHolder))
{
if (!_trackedDroppedItems.Contains(instanceID))
{
_nextSave = Time.unscaledTime;
}
_trackedDroppedItems.Add(instanceID);
}
}
_trackedDroppedItems.RemoveWhere((int value) => !liveItems.Contains(value));
_seenHeldItems.RemoveWhere((int value) => !liveItems.Contains(value));
}
private void CaptureBaseline()
{
_baselineItems.Clear();
Item[] array = ItemManager.Items.Values.ToArray();
foreach (Item val in array)
{
if (Object.op_Implicit((Object)(object)val) && !((NetworkBehaviour)val).IsDeinitializing)
{
_baselineItems.Add(((Object)val).GetInstanceID());
}
}
_baselineCaptured = true;
}
private void Save(string path)
{
//IL_0117: Unknown result type (might be due to invalid IL or missing references)
//IL_012d: Unknown result type (might be due to invalid IL or missing references)
//IL_0169: Unknown result type (might be due to invalid IL or missing references)
//IL_0180: Unknown result type (might be due to invalid IL or missing references)
//IL_0197: Unknown result type (might be due to invalid IL or missing references)
//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
//IL_03cd: Unknown result type (might be due to invalid IL or missing references)
//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
//IL_0425: Unknown result type (might be due to invalid IL or missing references)
//IL_0451: Unknown result type (might be due to invalid IL or missing references)
//IL_047d: Unknown result type (might be due to invalid IL or missing references)
//IL_04a9: Unknown result type (might be due to invalid IL or missing references)
if (string.IsNullOrEmpty(path) || !Object.op_Implicit((Object)(object)ItemManager.Instance))
{
return;
}
try
{
Track();
List<DroppedItemRecord> list = new List<DroppedItemRecord>();
Item[] array = ItemManager.Items.Values.ToArray();
foreach (Item val in array)
{
if (Object.op_Implicit((Object)(object)val) && !((NetworkBehaviour)val).IsDeinitializing && !val.IsDestroying && !Object.op_Implicit((Object)(object)val.Holder) && !Object.op_Implicit((Object)(object)val.SyncedHolder) && !val.IsInInventory && !Object.op_Implicit((Object)(object)val.AttachedRod) && !Object.op_Implicit((Object)(object)val.BirdHolder) && !Object.op_Implicit((Object)(object)val.DeadPlayer) && (_trackedDroppedItems.Contains(((Object)val).GetInstanceID()) || !_baselineItems.Contains(((Object)val).GetInstanceID()) || _seenHeldItems.Contains(((Object)val).GetInstanceID()) || Object.op_Implicit((Object)(object)val.LastHolder)) && IsFinite(((Component)val).transform.position) && IsFinite(((Component)val).transform.rotation))
{
list.Add(new DroppedItemRecord
{
Exists = true,
InventorySlot = byte.MaxValue,
ItemId = val.ID,
PositionX = ((Component)val).transform.position.x,
PositionY = ((Component)val).transform.position.y,
PositionZ = ((Component)val).transform.position.z,
RotationX = ((Component)val).transform.rotation.x,
RotationY = ((Component)val).transform.rotation.y,
RotationZ = ((Component)val).transform.rotation.z,
RotationW = ((Component)val).transform.rotation.w,
Cookness = val.Cookness,
BettingMultiplier = val.BettingMultiplier,
Weight = val.RandomizedWeight,
KillScoreMultiplier = val.KillScoreMultiplier,
SkinIndex = val.CurSkin,
IsDripCreature = (Object.op_Implicit((Object)(object)val.Creature) && val.Creature.IsDrip),
Sharpness = (byte)(Object.op_Implicit((Object)(object)val.Melee) ? val.Melee.SharpnessIndex : 0),
Sight = (byte)((Object.op_Implicit((Object)(object)val.Weapon) && Object.op_Implicit((Object)(object)val.Weapon.Attachments)) ? val.Weapon.Attachments.Sight : 0),
BarrelAttachment = (byte)((Object.op_Implicit((Object)(object)val.Weapon) && Object.op_Implicit((Object)(object)val.Weapon.Attachments)) ? val.Weapon.Attachments.BarrelAttachment : 0),
AmmoType = (byte)((Object.op_Implicit((Object)(object)val.Weapon) && Object.op_Implicit((Object)(object)val.Weapon.Attachments)) ? val.Weapon.Attachments.AmmoType : 0),
ExtendedMag = (Object.op_Implicit((Object)(object)val.Weapon) && Object.op_Implicit((Object)(object)val.Weapon.Attachments) && val.Weapon.Attachments.ExtendedMag),
LaserSight = (Object.op_Implicit((Object)(object)val.Weapon) && Object.op_Implicit((Object)(object)val.Weapon.Attachments) && val.Weapon.Attachments.LaserSight),
LinearVelocityX = (Object.op_Implicit((Object)(object)val.Rig) ? val.Rig.linearVelocity.x : 0f),
LinearVelocityY = (Object.op_Implicit((Object)(object)val.Rig) ? val.Rig.linearVelocity.y : 0f),
LinearVelocityZ = (Object.op_Implicit((Object)(object)val.Rig) ? val.Rig.linearVelocity.z : 0f),
AngularVelocityX = (Object.op_Implicit((Object)(object)val.Rig) ? val.Rig.angularVelocity.x : 0f),
AngularVelocityY = (Object.op_Implicit((Object)(object)val.Rig) ? val.Rig.angularVelocity.y : 0f),
AngularVelocityZ = (Object.op_Implicit((Object)(object)val.Rig) ? val.Rig.angularVelocity.z : 0f)
});
if (list.Count >= _maxItems.Value)
{
break;
}
}
}
if (list.Count != 0 || !HasNonEmptySnapshot(path))
{
PersistenceFile persistenceFile = new PersistenceFile
{
ServerName = ((SaveManager.CurServerSave != null) ? SaveManager.CurServerSave.Name : "default"),
Items = list.ToArray()
};
Directory.CreateDirectory(Paths.ConfigPath);
string text = path + ".tmp";
File.WriteAllText(text, JsonConvert.SerializeObject((object)persistenceFile, (Formatting)1));
File.Copy(text, path, overwrite: true);
File.Delete(text);
_errorLogged = false;
}
}
catch (Exception ex)
{
if (!_errorLogged)
{
_errorLogged = true;
((BaseUnityPlugin)this).Logger.LogWarning((object)("Dropped item persistence save failed: " + ex.Message));
}
}
}
private bool HasNonEmptySnapshot(string path)
{
if (string.IsNullOrEmpty(path) || !File.Exists(path))
{
return false;
}
try
{
PersistenceFile persistenceFile = JsonConvert.DeserializeObject<PersistenceFile>(File.ReadAllText(path));
return persistenceFile != null && persistenceFile.Items != null && persistenceFile.Items.Length != 0;
}
catch
{
return false;
}
}
private void Restore(string path)
{
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
//IL_0103: Unknown result type (might be due to invalid IL or missing references)
//IL_0108: Unknown result type (might be due to invalid IL or missing references)
//IL_0115: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
//IL_012f: 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_0149: Unknown result type (might be due to invalid IL or missing references)
//IL_0156: Unknown result type (might be due to invalid IL or missing references)
//IL_0163: Unknown result type (might be due to invalid IL or missing references)
//IL_0170: Unknown result type (might be due to invalid IL or missing references)
//IL_017d: Unknown result type (might be due to invalid IL or missing references)
//IL_018a: Unknown result type (might be due to invalid IL or missing references)
//IL_0197: Unknown result type (might be due to invalid IL or missing references)
//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
//IL_01be: Unknown result type (might be due to invalid IL or missing references)
//IL_01d0: Expected O, but got Unknown
//IL_027f: Unknown result type (might be due to invalid IL or missing references)
//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
string path2 = (File.Exists(path) ? path : GetLegacyPath());
if (!File.Exists(path2))
{
return;
}
try
{
PersistenceFile persistenceFile = JsonConvert.DeserializeObject<PersistenceFile>(File.ReadAllText(path2));
if (persistenceFile == null || persistenceFile.Items == null)
{
return;
}
DroppedItemRecord[] items = persistenceFile.Items;
Vector3 val = default(Vector3);
Quaternion val2 = default(Quaternion);
foreach (DroppedItemRecord droppedItemRecord in items)
{
if (droppedItemRecord == null || !droppedItemRecord.Exists)
{
continue;
}
((Vector3)(ref val))..ctor(droppedItemRecord.PositionX, droppedItemRecord.PositionY, droppedItemRecord.PositionZ);
((Quaternion)(ref val2))..ctor(droppedItemRecord.RotationX, droppedItemRecord.RotationY, droppedItemRecord.RotationZ, droppedItemRecord.RotationW);
if (!IsFinite(val) || !IsFinite(val2))
{
continue;
}
Item spawnable = GameInfo.GetSpawnable(droppedItemRecord.ItemId);
if (!Object.op_Implicit((Object)(object)spawnable) || HasLooseItemAt(droppedItemRecord.ItemId, val))
{
continue;
}
Item val3 = ItemManager.Instance.SpawnNewItem(spawnable, val, val2);
if (Object.op_Implicit((Object)(object)val3))
{
val3.LoadFromSave(new SavedItem
{
Exists = droppedItemRecord.Exists,
InventorySlot = droppedItemRecord.InventorySlot,
ItemID = droppedItemRecord.ItemId,
Cookness = droppedItemRecord.Cookness,
BettingMultiplier = droppedItemRecord.BettingMultiplier,
Weight = droppedItemRecord.Weight,
KillScoreMultiplier = droppedItemRecord.KillScoreMultiplier,
SkinIndex = droppedItemRecord.SkinIndex,
Sharpness = droppedItemRecord.Sharpness,
Sight = droppedItemRecord.Sight,
BarrelAttachment = droppedItemRecord.BarrelAttachment,
AmmoType = droppedItemRecord.AmmoType,
ExtendedMag = droppedItemRecord.ExtendedMag,
LaserSight = droppedItemRecord.LaserSight,
IsDripCreature = droppedItemRecord.IsDripCreature
});
val3._cookness.Value = droppedItemRecord.Cookness;
val3._bettingMultiplier.Value = droppedItemRecord.BettingMultiplier;
val3._syncedRandomWeight.Value = droppedItemRecord.Weight;
val3._killScoreMultiplier.Value = droppedItemRecord.KillScoreMultiplier;
val3._curSkin.Value = droppedItemRecord.SkinIndex;
if (Object.op_Implicit((Object)(object)val3.Creature))
{
val3.Creature._isDrip.Value = droppedItemRecord.IsDripCreature;
}
if (Object.op_Implicit((Object)(object)val3.Rig))
{
val3.Rig.linearVelocity = new Vector3(droppedItemRecord.LinearVelocityX, droppedItemRecord.LinearVelocityY, droppedItemRecord.LinearVelocityZ);
val3.Rig.angularVelocity = new Vector3(droppedItemRecord.AngularVelocityX, droppedItemRecord.AngularVelocityY, droppedItemRecord.AngularVelocityZ);
}
_trackedDroppedItems.Add(((Object)val3).GetInstanceID());
}
}
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Dropped item persistence restore failed: " + ex.Message));
}
}
private bool HasLooseItemAt(byte itemId, Vector3 position)
{
//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)
Item[] array = ItemManager.Items.Values.ToArray();
foreach (Item val in array)
{
if (Object.op_Implicit((Object)(object)val) && val.ID == itemId && !((NetworkBehaviour)val).IsDeinitializing && !Object.op_Implicit((Object)(object)val.Holder) && !Object.op_Implicit((Object)(object)val.SyncedHolder) && !val.IsInInventory && Vector3.Distance(((Component)val).transform.position, position) < 0.75f)
{
return true;
}
}
return false;
}
private static bool IsFinite(Vector3 value)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: 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_0041: Unknown result type (might be due to invalid IL or missing references)
if (!float.IsNaN(value.x) && !float.IsNaN(value.y) && !float.IsNaN(value.z) && !float.IsInfinity(value.x) && !float.IsInfinity(value.y))
{
return !float.IsInfinity(value.z);
}
return false;
}
private static bool IsFinite(Quaternion value)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: 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_0041: 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_005b: Unknown result type (might be due to invalid IL or missing references)
if (!float.IsNaN(value.x) && !float.IsNaN(value.y) && !float.IsNaN(value.z) && !float.IsNaN(value.w) && !float.IsInfinity(value.x) && !float.IsInfinity(value.y) && !float.IsInfinity(value.z))
{
return !float.IsInfinity(value.w);
}
return false;
}
private void OnDestroy()
{
_quitting = true;
}
}
}