using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("ReplicatorQuantity.InGameTests")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("ReplicatorQuantity")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+a98b6e74d9370058d4aed382d50a7f90cc20eb66")]
[assembly: AssemblyProduct("ReplicatorQuantity")]
[assembly: AssemblyTitle("ReplicatorQuantity")]
[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 ReplicatorQuantity
{
[BepInPlugin("com.github.jiesiluo.replicatorquantity", "Replicator Quantity", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
public const string Guid = "com.github.jiesiluo.replicatorquantity";
public const string Name = "Replicator Quantity";
public const string Version = "1.0.0";
internal static ManualLogSource Log;
internal static ConfigEntry<int> CtrlStep;
internal static ConfigEntry<int> ShiftStep;
internal static ConfigEntry<int> MaxQuantity;
internal static ConfigEntry<bool> AltForMax;
internal static Func<(bool ctrl, bool shift, bool alt)> Modifiers = () => (ctrl: Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305), shift: Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303), alt: Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307));
internal static Func<int> KeyDirection = () => (Input.GetKeyDown((KeyCode)61) || Input.GetKeyDown((KeyCode)270)) ? 1 : ((Input.GetKeyDown((KeyCode)45) || Input.GetKeyDown((KeyCode)269)) ? (-1) : 0);
private int lastRecipe;
private int lastAmount;
private void Awake()
{
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Expected O, but got Unknown
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
Log = ((BaseUnityPlugin)this).Logger;
CtrlStep = ((BaseUnityPlugin)this).Config.Bind<int>("Steps", "CtrlStep", 10, "Ctrl + click on +/- changes the amount by this much.");
ShiftStep = ((BaseUnityPlugin)this).Config.Bind<int>("Steps", "ShiftStep", 100, "Shift + click on +/- changes the amount by this much.");
AltForMax = ((BaseUnityPlugin)this).Config.Bind<bool>("Steps", "AltForMax", true, "Alt + click on + sets the amount to as many as you can craft; Alt + click on - resets it to 1.");
MaxQuantity = ((BaseUnityPlugin)this).Config.Bind<int>("Limits", "MaxQuantity", 999, new ConfigDescription("Largest amount one click on the produce button can queue (the game's own limit is 10).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 9999), Array.Empty<object>()));
new Harmony("com.github.jiesiluo.replicatorquantity").PatchAll(typeof(ReplicatorPatches));
}
private void LateUpdate()
{
UIReplicatorWindow val = UIRoot.instance?.uiGame?.replicator;
RecipeProto val2 = (((Object)(object)val != (Object)null && ((ManualBehaviour)val).active) ? ReplicatorPatches.SelectedRecipe.Invoke(val) : null);
if (val2 == null || val.multipliers == null)
{
lastRecipe = 0;
return;
}
int num = KeyDirection();
if (num != 0 && ((Proto)val2).ID == lastRecipe)
{
val.multipliers[((Proto)val2).ID] = ReplicatorPatches.Next(val, val2, lastAmount, num);
}
lastRecipe = ((Proto)val2).ID;
lastAmount = ReplicatorPatches.Amount(val, val2);
}
}
[HarmonyPatch(typeof(UIReplicatorWindow))]
internal static class ReplicatorPatches
{
internal static readonly FieldRef<UIReplicatorWindow, RecipeProto> SelectedRecipe = AccessTools.FieldRefAccess<UIReplicatorWindow, RecipeProto>("selectedRecipe");
private static readonly FieldRef<UIReplicatorWindow, MechaForge> Forge = AccessTools.FieldRefAccess<UIReplicatorWindow, MechaForge>("mechaForge");
private static Action<int> plusHandler;
private static Action<int> minusHandler;
public static int Cap()
{
return Math.Max(10, Plugin.MaxQuantity.Value);
}
[HarmonyPostfix]
[HarmonyPatch("_OnRegEvent")]
private static void RegisterButtons(UIReplicatorWindow __instance)
{
UIReplicatorWindow window = __instance;
__instance.plusButton.onClick -= GameHandler(__instance, "OnPlusButtonClick");
__instance.minusButton.onClick -= GameHandler(__instance, "OnMinusButtonClick");
plusHandler = delegate
{
Change(window, 1);
};
minusHandler = delegate
{
Change(window, -1);
};
__instance.plusButton.onClick += plusHandler;
__instance.minusButton.onClick += minusHandler;
}
[HarmonyPostfix]
[HarmonyPatch("_OnUnregEvent")]
private static void UnregisterButtons(UIReplicatorWindow __instance)
{
if (plusHandler != null)
{
__instance.plusButton.onClick -= plusHandler;
}
if (minusHandler != null)
{
__instance.minusButton.onClick -= minusHandler;
}
plusHandler = (minusHandler = null);
}
private static Action<int> GameHandler(UIReplicatorWindow window, string method)
{
return (Action<int>)Delegate.CreateDelegate(typeof(Action<int>), window, AccessTools.Method(typeof(UIReplicatorWindow), method, (Type[])null, (Type[])null));
}
internal static int Amount(UIReplicatorWindow window, RecipeProto recipe)
{
if (window.multipliers == null || !window.multipliers.TryGetValue(((Proto)recipe).ID, out var value))
{
return 1;
}
return value;
}
internal static void Change(UIReplicatorWindow window, int direction)
{
RecipeProto val = SelectedRecipe.Invoke(window);
if (val != null && window.multipliers != null)
{
window.multipliers[((Proto)val).ID] = Next(window, val, Amount(window, val), direction);
}
}
internal static int Next(UIReplicatorWindow window, RecipeProto recipe, int current, int direction)
{
(bool, bool, bool) tuple = Plugin.Modifiers();
bool item = tuple.Item1;
bool item2 = tuple.Item2;
bool item3 = tuple.Item3;
int num = Cap();
int val;
if (item3 && Plugin.AltForMax.Value)
{
if (direction < 0)
{
val = 1;
}
else if (window.isInstantItem)
{
val = num;
}
else
{
MechaForge obj = Forge.Invoke(window);
val = ((obj != null) ? obj.PredictTaskCount(((Proto)recipe).ID, num, false) : current);
}
}
else
{
int num2 = Math.Max(1, item2 ? Plugin.ShiftStep.Value : ((!item) ? 1 : Plugin.CtrlStep.Value));
val = ((direction > 0 && current == 1 && num2 > 1) ? num2 : (current + direction * num2));
}
return Math.Max(1, Math.Min(num, val));
}
[HarmonyTranspiler]
[HarmonyPatch("OnOkButtonClick")]
private static IEnumerable<CodeInstruction> ProduceTranspiler(IEnumerable<CodeInstruction> instructions)
{
List<CodeInstruction> list = instructions.ToList();
MethodInfo predict = AccessTools.Method(typeof(MechaForge), "PredictTaskCount", (Type[])null, (Type[])null);
MethodInfo operand = AccessTools.Method(typeof(ReplicatorPatches), "Cap", (Type[])null, (Type[])null);
List<CodeInstruction> list2 = list.Where((CodeInstruction ci) => CodeInstructionExtensions.LoadsConstant(ci, 10L)).ToList();
int num = list.FindIndex((CodeInstruction ci) => CodeInstructionExtensions.Calls(ci, predict));
bool flag = num >= 2 && CodeInstructionExtensions.LoadsConstant(list[num - 2], 99L);
if (list2.Count != 2 || !flag)
{
Plugin.Log.LogError((object)($"The replicator's produce button has changed (found {list2.Count} limits of 10, " + "material check " + (flag ? "found" : "not found") + "); keeping the game's limit of 10 per click."));
return list;
}
foreach (CodeInstruction item in list2.Append(list[num - 2]))
{
item.opcode = OpCodes.Call;
item.operand = operand;
}
Plugin.Log.LogInfo((object)"Replicator produce button: limit raised from 10 to the MaxQuantity setting.");
return list;
}
}
}