using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using FishNet.Object;
using HarmonyLib;
using Microsoft.CodeAnalysis;
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("Estonia")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Prevents duplicate slot machine skin rewards in How to Fish.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("FreshWheelSkins")]
[assembly: AssemblyTitle("FreshWheelSkins")]
[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 FreshWheelSkins
{
[BepInPlugin("estonia.howtofish.freshwheelskins", "Fresh Wheel Skins", "1.0.0")]
[BepInProcess("How to Fish.exe")]
public sealed class FreshWheelSkinsPlugin : BaseUnityPlugin
{
private readonly struct Reward
{
public byte ItemId { get; }
public byte SkinIndex { get; }
public Reward(byte itemId, byte skinIndex)
{
ItemId = itemId;
SkinIndex = skinIndex;
}
}
[HarmonyPatch(typeof(SlotMachine), "Roll")]
private static class SlotMachineRollPatch
{
private static void Prefix(Player roller, byte[] itemIDs, byte[] itemSkins, byte rolled)
{
try
{
_instance?.ReplaceDuplicateReward(roller, itemIDs, itemSkins, rolled);
}
catch (Exception arg)
{
FreshWheelSkinsPlugin instance = _instance;
if (instance != null)
{
((BaseUnityPlugin)instance).Logger.LogError((object)$"Failed to replace duplicate wheel skin: {arg}");
}
}
}
}
private const string PluginGuid = "estonia.howtofish.freshwheelskins";
private const string PluginName = "Fresh Wheel Skins";
private const string PluginVersion = "1.0.0";
private const string Author = "Estonia";
private static readonly FieldInfo CurLocalSaveField = AccessTools.Field(typeof(SaveManager), "_curLocalSave");
private static FreshWheelSkinsPlugin _instance;
private ConfigEntry<bool> _keepRarity;
private ConfigEntry<bool> _allowOtherPrizeItems;
private Harmony _harmony;
private void Awake()
{
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Expected O, but got Unknown
_instance = this;
_keepRarity = ((BaseUnityPlugin)this).Config.Bind<bool>("Wheel", "KeepRarityFirst", true, (ConfigDescription)null);
_allowOtherPrizeItems = ((BaseUnityPlugin)this).Config.Bind<bool>("Wheel", "UseOtherPrizeItemsWhenNeeded", true, (ConfigDescription)null);
_harmony = new Harmony("estonia.howtofish.freshwheelskins");
_harmony.PatchAll(typeof(FreshWheelSkinsPlugin).Assembly);
((BaseUnityPlugin)this).Logger.LogInfo((object)"Fresh Wheel Skins 1.0.0 loaded. Author: Estonia.");
}
private void OnDestroy()
{
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
private void ReplaceDuplicateReward(Player roller, byte[] itemIDs, byte[] itemSkins, byte rolled)
{
//IL_0080: 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_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
if (!Object.op_Implicit((Object)(object)roller) || itemIDs == null || itemSkins == null || rolled >= itemIDs.Length || rolled >= itemSkins.Length || !((NetworkBehaviour)roller).Owner.IsLocalClient)
{
return;
}
object? obj = CurLocalSaveField?.GetValue(null);
LocalSaveObject val = (LocalSaveObject)((obj is LocalSaveObject) ? obj : null);
if (val == null)
{
return;
}
byte b = itemIDs[rolled];
byte b2 = itemSkins[rolled];
SkinPreset preset = GetPreset(b);
if (Object.op_Implicit((Object)(object)preset) && b2 < preset.Skins.Count && IsOwned(val, b, b2))
{
ItemSkin val2 = preset.Skins[b2];
Rarity rarity = ((ItemSkin)(ref val2)).Rarity;
if ((!_keepRarity.Value || !TryFindUnowned(val, new byte[1] { b }, rarity, out var reward)) && (!_allowOtherPrizeItems.Value || !_keepRarity.Value || !TryFindUnowned(val, GetPrizeItemIds(), rarity, out reward)) && !TryFindUnowned(val, new byte[1] { b }, null, out reward) && (!_allowOtherPrizeItems.Value || !TryFindUnowned(val, GetPrizeItemIds(), null, out reward)))
{
((BaseUnityPlugin)this).Logger.LogInfo((object)"Wheel rolled a duplicate skin, but there are no locked wheel skins left to swap in.");
return;
}
itemIDs[rolled] = reward.ItemId;
itemSkins[rolled] = reward.SkinIndex;
((BaseUnityPlugin)this).Logger.LogInfo((object)("Replaced duplicate wheel skin " + Describe(b, b2) + " with " + Describe(reward.ItemId, reward.SkinIndex) + "."));
}
}
private static bool TryFindUnowned(LocalSaveObject save, IEnumerable<byte> itemIds, Rarity? rarity, out Reward reward)
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
List<Reward> list = new List<Reward>();
foreach (byte itemId in itemIds)
{
SkinPreset preset = GetPreset(itemId);
if (!Object.op_Implicit((Object)(object)preset))
{
continue;
}
for (int i = 0; i < preset.Skins.Count && i <= 255; i++)
{
ItemSkin val = preset.Skins[i];
if ((int)((ItemSkin)(ref val)).Rarity != 0 && (!rarity.HasValue || ((ItemSkin)(ref val)).Rarity == rarity.Value))
{
byte skinIndex = (byte)i;
if (!IsOwned(save, itemId, skinIndex))
{
list.Add(new Reward(itemId, skinIndex));
}
}
}
}
if (list.Count == 0)
{
reward = default(Reward);
return false;
}
reward = list[Random.Range(0, list.Count)];
return true;
}
private static IEnumerable<byte> GetPrizeItemIds()
{
HashSet<byte> ids = new HashSet<byte>();
Item[] availableItems = SlotMachine.AvailableItems;
if (availableItems != null)
{
Item[] array = availableItems;
foreach (Item val in array)
{
if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.SkinPreset) && ids.Add(val.ID))
{
yield return val.ID;
}
}
}
if (!SlotMachine.ExcludeBoat)
{
yield return byte.MaxValue;
}
}
private static SkinPreset GetPreset(byte itemId)
{
if (itemId == byte.MaxValue)
{
if (!Object.op_Implicit((Object)(object)BoatManager.Boat))
{
return null;
}
return BoatManager.Boat.SkinPreset;
}
Item val = GameInfo.IDToItem(itemId);
if (!Object.op_Implicit((Object)(object)val))
{
return null;
}
return val.SkinPreset;
}
private static bool IsOwned(LocalSaveObject save, byte itemId, byte skinIndex)
{
if (itemId == byte.MaxValue)
{
if (save.UnlockedBoatSkins != null)
{
return save.UnlockedBoatSkins.Contains(skinIndex);
}
return false;
}
if (save.UnlockedItemSkins == null)
{
return false;
}
foreach (SavedItemSkin unlockedItemSkin in save.UnlockedItemSkins)
{
if (unlockedItemSkin != null && unlockedItemSkin.ID == itemId)
{
return unlockedItemSkin.SkinsUnlocked != null && unlockedItemSkin.SkinsUnlocked.Contains(skinIndex);
}
}
return false;
}
private static string Describe(byte itemId, byte skinIndex)
{
if (itemId == byte.MaxValue)
{
return $"Boat/{skinIndex}";
}
Item val = GameInfo.IDToItem(itemId);
return $"{(Object.op_Implicit((Object)(object)val) ? ((Object)val).name : itemId.ToString())}/{skinIndex}";
}
}
}