using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using Microsoft.CodeAnalysis;
using SSSGame;
using SSSGame.AI;
using SSSGame.UI;
using SandSailorStudio.Inventory;
using SandSailorStudio.Storage;
using SandSailorStudio.UI;
using SmolkrPenGenderTargets.Core;
using SmolkrPenGenderTargets.Runtime;
using SmolkrPenGenderTargets.UI;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("SmolkrPenGenderTargets")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+6af857529bfa1b02257de924d3cff2337dd12044")]
[assembly: AssemblyProduct("SmolkrPenGenderTargets")]
[assembly: AssemblyTitle("SmolkrPenGenderTargets")]
[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 SmolkrPenGenderTargets
{
[BepInPlugin("aska.smolkr.pen.gender.targets", "Smolkr and Kyckling Pen Gender Limits", "1.1.1")]
public sealed class Plugin : BasePlugin
{
public const string PluginGuid = "aska.smolkr.pen.gender.targets";
public const string PluginName = "Smolkr and Kyckling Pen Gender Limits";
public const string PluginVersion = "1.1.1";
private Harmony _harmony;
internal static ManualLogSource Log { get; private set; }
internal static ConfigEntry<bool> Enabled { get; private set; }
internal static ConfigEntry<bool> ShowRow { get; private set; }
internal static ConfigEntry<float> RowOffsetX { get; private set; }
internal static ConfigEntry<float> RowOffsetY { get; private set; }
public override void Load()
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Expected O, but got Unknown
Log = ((BasePlugin)this).Log;
BindConfig();
InstallPatches();
ManualLogSource log = Log;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(20, 3, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("Smolkr and Kyckling Pen Gender Limits");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.1.1");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded (enabled=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(Enabled.Value);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(").");
}
log.LogInfo(val);
}
public override bool Unload()
{
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
return true;
}
private void BindConfig()
{
Enabled = ((BasePlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch. When false, every smolkr and kyckling pen slaughters exactly as in vanilla, whatever each pen's gender targets are set to. The targets themselves are kept.");
ShowRow = ((BasePlugin)this).Config.Bind<bool>("Interface", "ShowRow", true, "Add a 'Females to keep' row under the slaughter limit in a smolkr or kyckling pen's slaughter task. Turning this off hides the row only; pens keep using the targets they already have.");
RowOffsetX = ((BasePlugin)this).Config.Bind<float>("Interface", "RowOffsetX", 0f, "Moves the 'Females to keep' row sideways, in UI units. Only needed if the row overlaps something after a game update; the default places it directly under the slaughter limit.");
RowOffsetY = ((BasePlugin)this).Config.Bind<float>("Interface", "RowOffsetY", 0f, "Moves the 'Females to keep' row up (positive) or down (negative), in UI units. Only needed if the row overlaps something after a game update.");
}
private void InstallPatches()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Expected O, but got Unknown
try
{
_harmony = new Harmony("aska.smolkr.pen.gender.targets");
_harmony.PatchAll();
Log.LogInfo((object)"Harmony patches installed.");
}
catch (Exception value)
{
Log.LogError((object)("Failed to install Harmony patches - smolkr and kyckling pens will behave as vanilla. This usually means ASKA updated and the interop assemblies need regenerating. " + $"Details: {value}"));
}
}
}
}
namespace SmolkrPenGenderTargets.UI
{
internal static class FemalesToKeepRow
{
private sealed class RowState
{
internal GameObject Row;
internal IncreaseDecreasePanel Control;
internal TMP_Text Title;
internal TaskDataPanel Panel;
internal AnimalPen Pen;
}
private const int OffValue = -1;
private const float RowSpacing = 6f;
private static readonly Dictionary<IntPtr, RowState> RowsByPanel = new Dictionary<IntPtr, RowState>();
private static readonly Dictionary<IntPtr, RowState> RowsByControl = new Dictionary<IntPtr, RowState>();
private static bool _layoutLogged;
internal static void OnQuantitySet(TaskDataPanel panel, WorkstationTaskData task)
{
object obj;
if (task == null)
{
obj = null;
}
else
{
AnimalSlaughterTaskData obj2 = ((Il2CppObjectBase)task).TryCast<AnimalSlaughterTaskData>();
obj = ((obj2 != null) ? obj2.SmolkrPen : null);
}
AnimalPen val = (AnimalPen)obj;
if ((Object)(object)val == (Object)null || !Plugin.ShowRow.Value)
{
if (RowsByPanel.TryGetValue(((Il2CppObjectBase)panel).Pointer, out var value))
{
Hide(value);
}
return;
}
RowState orBuild = GetOrBuild(panel);
if (orBuild != null)
{
Show(orBuild, val);
}
}
internal static void OnLimitChanged(TaskDataPanel panel)
{
if (RowsByPanel.TryGetValue(((Il2CppObjectBase)panel).Pointer, out var value) && !((Object)(object)value.Pen == (Object)null) && !((Object)(object)value.Row == (Object)null))
{
Show(value, value.Pen);
}
}
internal static void OnControlTextRefreshed(IncreaseDecreasePanel control)
{
if (RowsByControl.TryGetValue(((Il2CppObjectBase)control).Pointer, out var _))
{
string text = ((control.Value <= -1) ? "Off" : control.Value.ToString());
if ((Object)(object)control.ValueText != (Object)null)
{
((TMP_Text)control.ValueText).text = text;
}
if ((Object)(object)control.InputField != (Object)null)
{
control.InputField.SetTextWithoutNotify(text);
}
}
}
private static void Show(RowState state, AnimalPen pen)
{
state.Pen = pen;
int num = CurrentLimit(state);
int femalesToKeep;
int num2 = (PenTargetStore.TryGet(pen, out femalesToKeep) ? Math.Min(femalesToKeep, num) : (-1));
state.Row.SetActive(true);
Place(state);
state.Control.MinValue = -1;
state.Control.MaxValue = num;
state.Control.SetValue(num2, true);
RefreshTitle(state);
}
private static void Hide(RowState state)
{
state.Pen = null;
if ((Object)(object)state.Row != (Object)null)
{
state.Row.SetActive(false);
}
}
private static int CurrentLimit(RowState state)
{
IncreaseDecreasePanel quantityControlPanel = state.Panel._quantityControlPanel;
if (!((Object)(object)quantityControlPanel != (Object)null))
{
return 0;
}
return Math.Max(0, quantityControlPanel.Value);
}
private static void RefreshTitle(RowState state)
{
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)state.Title == (Object)null))
{
if (state.Control.Value <= -1)
{
state.Title.text = "Females to keep (off - vanilla 50/50)";
return;
}
HerdTargets val = HerdTargets.Create(CurrentLimit(state), state.Control.Value);
state.Title.text = $"Females to keep (males: {((HerdTargets)(ref val)).MalesToKeep})";
}
}
private static void OnValueChanged(RowState state, int value)
{
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: Expected O, but got Unknown
try
{
AnimalPen pen = state.Pen;
if (!((Object)(object)pen == (Object)null))
{
if (value <= -1)
{
PenTargetStore.Clear(pen);
}
else
{
PenTargetStore.Set(pen, value);
}
RefreshTitle(state);
SlaughterLog.Write("targets_changed", $"{SlaughterLog.DescribePen(pen)} keep_f={((value <= -1) ? "off" : value.ToString())} limit={CurrentLimit(state)}");
}
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(37, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("SPGT event=row_change_failed details=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
}
log.LogError(val);
}
}
private static RowState GetOrBuild(TaskDataPanel panel)
{
if (RowsByPanel.TryGetValue(((Il2CppObjectBase)panel).Pointer, out var value))
{
if ((Object)(object)value.Row != (Object)null && (Object)(object)value.Control != (Object)null)
{
return value;
}
RowsByPanel.Remove(((Il2CppObjectBase)panel).Pointer);
if (value.Control != null)
{
RowsByControl.Remove(((Il2CppObjectBase)value.Control).Pointer);
}
}
value = Build(panel);
if (value == null)
{
return null;
}
RowsByPanel[((Il2CppObjectBase)panel).Pointer] = value;
RowsByControl[((Il2CppObjectBase)value.Control).Pointer] = value;
return value;
}
private static RowState Build(TaskDataPanel panel)
{
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Expected O, but got Unknown
GameObject quantityDiv = panel._quantityDiv;
IncreaseDecreasePanel quantityControlPanel = panel._quantityControlPanel;
if ((Object)(object)quantityDiv == (Object)null || (Object)(object)quantityControlPanel == (Object)null)
{
SlaughterLog.Write("row_unavailable", "reason=task_panel_has_no_quantity_row");
return null;
}
Transform parent = quantityDiv.transform.parent;
string text = RelativePath(quantityDiv.transform, ((Component)quantityControlPanel).transform);
string text2 = (((Object)(object)panel._quantityDivTitle != (Object)null) ? RelativePath(quantityDiv.transform, panel._quantityDivTitle.transform) : null);
if (text == null)
{
SlaughterLog.Write("row_unavailable", "reason=limit_control_is_not_inside_its_div");
return null;
}
GameObject val = new GameObject("SPGT_RowHolder");
val.SetActive(false);
val.transform.SetParent(parent, false);
GameObject val2 = Object.Instantiate<GameObject>(quantityDiv, val.transform);
((Object)val2).name = "SPGT_FemalesToKeepRow";
Transform obj = FindRelative(val2.transform, text);
IncreaseDecreasePanel val3 = ((obj != null) ? ((Component)obj).GetComponent<IncreaseDecreasePanel>() : null);
object obj2;
if (text2 == null)
{
obj2 = null;
}
else
{
Transform obj3 = FindRelative(val2.transform, text2);
obj2 = ((obj3 != null) ? ((Component)obj3).GetComponent<TMP_Text>() : null);
}
TMP_Text val4 = (TMP_Text)obj2;
if ((Object)(object)val3 == (Object)null)
{
Object.Destroy((Object)(object)val);
SlaughterLog.Write("row_unavailable", "reason=cloned_control_not_found");
return null;
}
HideClonedMaterials(panel, quantityDiv, val2);
val3.group = null;
SilencePersistentListeners((UnityEventBase)(object)val3.OnValueChanged);
SilencePersistentListeners((UnityEventBase)(object)val3.OnIncrease);
SilencePersistentListeners((UnityEventBase)(object)val3.OnDecrease);
if ((Object)(object)val4 != (Object)null)
{
RemoveLocalizers(((Component)val4).gameObject);
}
RowState state = new RowState
{
Row = val2,
Control = val3,
Title = val4,
Panel = panel
};
((UnityEvent<int>)(object)val3.OnValueChanged).AddListener(DelegateSupport.ConvertDelegate<UnityAction<int>>((Delegate)(Action<int>)delegate(int value)
{
OnValueChanged(state, value);
}));
val2.transform.SetParent(parent, false);
val2.transform.SetSiblingIndex(quantityDiv.transform.GetSiblingIndex() + 1);
Object.Destroy((Object)(object)val);
if (!_layoutLogged)
{
_layoutLogged = true;
LogLayout(quantityDiv, val4);
}
SlaughterLog.Write("row_built", $"panel={((Il2CppObjectBase)panel).Pointer.ToInt64():X}");
return state;
}
private static void Place(RowState state)
{
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: 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)
GameObject quantityDiv = state.Panel._quantityDiv;
if ((Object)(object)quantityDiv == (Object)null)
{
return;
}
Transform parent = quantityDiv.transform.parent;
if (!((Object)(object)parent != (Object)null) || !((Object)(object)((Component)parent).GetComponent<LayoutGroup>() != (Object)null))
{
RectTransform component = quantityDiv.GetComponent<RectTransform>();
RectTransform component2 = state.Row.GetComponent<RectTransform>();
if (!((Object)(object)component == (Object)null) && !((Object)(object)component2 == (Object)null))
{
Rect rect = component.rect;
float height = ((Rect)(ref rect)).height;
component2.anchoredPosition = component.anchoredPosition + new Vector2(Plugin.RowOffsetX.Value, 0f - (height + 6f) + Plugin.RowOffsetY.Value);
}
}
}
private static void HideClonedMaterials(TaskDataPanel panel, GameObject templateDiv, GameObject row)
{
GameObject materialsDiv = panel._materialsDiv;
if ((Object)(object)materialsDiv == (Object)null)
{
return;
}
string text = RelativePath(templateDiv.transform, materialsDiv.transform);
if (!string.IsNullOrEmpty(text))
{
Transform val = FindRelative(row.transform, text);
if ((Object)(object)val != (Object)null)
{
((Component)val).gameObject.SetActive(false);
}
}
}
private static void SilencePersistentListeners(UnityEventBase unityEvent)
{
if (unityEvent != null)
{
int persistentEventCount = unityEvent.GetPersistentEventCount();
for (int i = 0; i < persistentEventCount; i++)
{
unityEvent.SetPersistentListenerState(i, (UnityEventCallState)0);
}
}
}
private static void RemoveLocalizers(GameObject titleObject)
{
foreach (Component component in titleObject.GetComponents<Component>())
{
if (((MemberInfo)((Object)component).GetIl2CppType()).Name.IndexOf("Locali", StringComparison.OrdinalIgnoreCase) >= 0)
{
Behaviour val = ((Il2CppObjectBase)component).TryCast<Behaviour>();
if ((Object)(object)val != (Object)null)
{
val.enabled = false;
}
Object.Destroy((Object)(object)component);
}
}
}
private static string RelativePath(Transform ancestor, Transform descendant)
{
List<string> list = new List<string>();
Transform val = descendant;
while ((Object)(object)val != (Object)null)
{
if (((Il2CppObjectBase)val).Pointer == ((Il2CppObjectBase)ancestor).Pointer)
{
list.Reverse();
return string.Join("/", list);
}
list.Add(((Object)val).name);
val = val.parent;
}
return null;
}
private static Transform FindRelative(Transform root, string path)
{
if (path.Length != 0)
{
return root.Find(path);
}
return root;
}
private static void LogLayout(GameObject templateDiv, TMP_Text title)
{
//IL_0135: Unknown result type (might be due to invalid IL or missing references)
//IL_014f: Unknown result type (might be due to invalid IL or missing references)
//IL_0154: Unknown result type (might be due to invalid IL or missing references)
//IL_0158: Unknown result type (might be due to invalid IL or missing references)
try
{
Transform parent = templateDiv.transform.parent;
LayoutGroup val = ((parent != null) ? ((Component)parent).GetComponent<LayoutGroup>() : null);
StringBuilder stringBuilder = new StringBuilder();
StringBuilder stringBuilder2 = stringBuilder;
StringBuilder stringBuilder3 = stringBuilder2;
StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(21, 2, stringBuilder2);
handler.AppendLiteral("parent=");
handler.AppendFormatted((parent != null) ? ((Object)parent).name : null);
handler.AppendLiteral(" layout_group=");
handler.AppendFormatted(((Object)(object)val != (Object)null) ? ((MemberInfo)((Object)val).GetIl2CppType()).Name : "none");
stringBuilder3.Append(ref handler);
if ((Object)(object)parent != (Object)null)
{
for (int i = 0; i < parent.childCount; i++)
{
Transform child = parent.GetChild(i);
RectTransform component = ((Component)child).GetComponent<RectTransform>();
stringBuilder2 = stringBuilder;
StringBuilder stringBuilder4 = stringBuilder2;
handler = new StringBuilder.AppendInterpolatedStringHandler(14, 3, stringBuilder2);
handler.AppendLiteral(" | [");
handler.AppendFormatted(i);
handler.AppendLiteral("] ");
handler.AppendFormatted(((Object)child).name);
handler.AppendLiteral(" active=");
handler.AppendFormatted(((Component)child).gameObject.activeSelf);
stringBuilder4.Append(ref handler);
if ((Object)(object)component != (Object)null)
{
stringBuilder2 = stringBuilder;
StringBuilder stringBuilder5 = stringBuilder2;
handler = new StringBuilder.AppendInterpolatedStringHandler(11, 2, stringBuilder2);
handler.AppendLiteral(" pos=");
handler.AppendFormatted<Vector2>(component.anchoredPosition);
handler.AppendLiteral(" size=");
Rect rect = component.rect;
handler.AppendFormatted<Vector2>(((Rect)(ref rect)).size);
stringBuilder5.Append(ref handler);
}
}
}
if ((Object)(object)title != (Object)null)
{
stringBuilder.Append(" | title_components=");
foreach (Component component2 in ((Component)title).GetComponents<Component>())
{
stringBuilder.Append(((MemberInfo)((Object)component2).GetIl2CppType()).Name).Append(',');
}
}
SlaughterLog.Write("row_layout", stringBuilder.ToString());
}
catch (Exception ex)
{
SlaughterLog.Write("row_layout", "unavailable=" + ex.Message);
}
}
}
}
namespace SmolkrPenGenderTargets.Runtime
{
internal static class PenReader
{
internal sealed class PenSnapshot
{
internal readonly List<PenAnimal> Animals = new List<PenAnimal>();
internal readonly List<DomesticSmolkr> Smolkr = new List<DomesticSmolkr>();
internal int SlaughterLimit;
internal int MinimumPopulation;
internal int OwnedPetCount;
}
internal static PenSnapshot Read(AnimalPen pen)
{
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
List<PetWrapper> ownedPets = ((Kennel)pen)._ownedPets;
AnimalSlaughterTaskData slaughterTaskData = pen._slaughterTaskData;
ItemInfoQuantity val = ((slaughterTaskData != null) ? ((WorkstationTaskData)slaughterTaskData).itemInfoQuantity : null);
if (ownedPets == null || val == null)
{
return null;
}
PenSnapshot penSnapshot = new PenSnapshot
{
SlaughterLimit = val.quantity,
MinimumPopulation = pen.minimumPetPopulation,
OwnedPetCount = ownedPets.Count
};
for (int i = 0; i < ownedPets.Count; i++)
{
PetWrapper obj = ownedPets[i];
Pet val2 = ((obj != null) ? obj.pet : null);
if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).gameObject == (Object)null))
{
DomesticSmolkr component = ((Component)val2).GetComponent<DomesticSmolkr>();
if (!((Object)(object)component == (Object)null))
{
penSnapshot.Animals.Add(new PenAnimal(component.isFemale, val2._mature));
penSnapshot.Smolkr.Add(component);
}
}
}
return penSnapshot;
}
internal static CullDecision? Plan(AnimalPen pen, int femalesToKeep, out DomesticSmolkr victim)
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
victim = null;
PenSnapshot penSnapshot = Read(pen);
if (penSnapshot == null)
{
return null;
}
HerdTargets val = HerdTargets.Create(penSnapshot.SlaughterLimit, femalesToKeep);
CullDecision value = CullPlanner.Decide((IReadOnlyList<PenAnimal>)penSnapshot.Animals, val, penSnapshot.OwnedPetCount, penSnapshot.MinimumPopulation);
if (((CullDecision)(ref value)).HasVictim)
{
victim = penSnapshot.Smolkr[((CullDecision)(ref value)).VictimIndex];
}
return value;
}
}
internal static class PenTargetStore
{
private static readonly Dictionary<IntPtr, int> FemalesToKeepByPen = new Dictionary<IntPtr, int>();
internal static bool TryGet(AnimalPen pen, out int femalesToKeep)
{
femalesToKeep = 0;
if ((Object)(object)pen != (Object)null)
{
return FemalesToKeepByPen.TryGetValue(((Il2CppObjectBase)pen).Pointer, out femalesToKeep);
}
return false;
}
internal static void Set(AnimalPen pen, int femalesToKeep)
{
if (!((Object)(object)pen == (Object)null))
{
FemalesToKeepByPen[((Il2CppObjectBase)pen).Pointer] = Math.Max(0, femalesToKeep);
}
}
internal static void Clear(AnimalPen pen)
{
if (!((Object)(object)pen == (Object)null))
{
FemalesToKeepByPen.Remove(((Il2CppObjectBase)pen).Pointer);
}
}
internal static void Forget(IntPtr penPointer)
{
FemalesToKeepByPen.Remove(penPointer);
}
}
internal static class SlaughterLog
{
private static readonly Dictionary<IntPtr, IntPtr> SelectedSmolkrByPen = new Dictionary<IntPtr, IntPtr>();
private static bool _failureReported;
internal static void Write(string eventName, string details)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Expected O, but got Unknown
ManualLogSource log = Plugin.Log;
if (log != null)
{
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(12, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("SPGT event=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(eventName);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(details);
}
log.LogInfo(val);
}
}
internal static string DescribePen(AnimalPen pen)
{
return $"pen={((Il2CppObjectBase)pen).Pointer.ToInt64():X} kind={(pen.kycklingPen ? "kyckling" : "smolkr")}";
}
internal static void Selected(AnimalPen pen, CullDecision decision, DomesticSmolkr victim)
{
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
IntPtr intPtr = ((victim != null) ? ((Il2CppObjectBase)victim).Pointer : IntPtr.Zero);
if (!SelectedSmolkrByPen.TryGetValue(((Il2CppObjectBase)pen).Pointer, out var value) || !(value == intPtr))
{
SelectedSmolkrByPen[((Il2CppObjectBase)pen).Pointer] = intPtr;
HerdCensus census = ((CullDecision)(ref decision)).Census;
HerdTargets targets = ((CullDecision)(ref decision)).Targets;
Write(((Object)(object)victim != (Object)null) ? "slaughter_selected" : "slaughter_declined", $"{DescribePen(pen)} reason={((CullDecision)(ref decision)).Reason} victim_female={(((Object)(object)victim != (Object)null) ? victim.isFemale.ToString() : "-")} adults_f={((HerdCensus)(ref census)).AdultFemales} adults_m={((HerdCensus)(ref census)).AdultMales} pups_f={((HerdCensus)(ref census)).FemalePups} pups_m={((HerdCensus)(ref census)).MalePups} keep_f={((HerdTargets)(ref targets)).FemalesToKeep} keep_m={((HerdTargets)(ref targets)).MalesToKeep} limit={((HerdTargets)(ref targets)).SlaughterLimit}");
}
}
internal static void Died(AnimalPen pen, DomesticSmolkr smolkr)
{
int num;
object eventName;
if (SelectedSmolkrByPen.TryGetValue(((Il2CppObjectBase)pen).Pointer, out var value))
{
num = ((value == ((Il2CppObjectBase)smolkr).Pointer) ? 1 : 0);
if (num != 0)
{
eventName = "slaughter_confirmed";
goto IL_0032;
}
}
else
{
num = 0;
}
eventName = "smolkr_died_unselected";
goto IL_0032;
IL_0032:
Write((string)eventName, $"{DescribePen(pen)} female={smolkr.isFemale}");
if (num != 0)
{
SelectedSmolkrByPen.Remove(((Il2CppObjectBase)pen).Pointer);
}
}
internal static void Failed(Exception exception)
{
if (!_failureReported)
{
_failureReported = true;
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogError((object)("SPGT event=selection_failed - the vanilla slaughter choice is used whenever this " + $"happens; later failures are not reported again. Details: {exception}"));
}
}
}
internal static void Forget(IntPtr penPointer)
{
SelectedSmolkrByPen.Remove(penPointer);
}
}
}
namespace SmolkrPenGenderTargets.Patches
{
[HarmonyPatch(typeof(Kennel), "OnDestroy")]
internal static class KennelDestroyPatch
{
private static void Prefix(Kennel __instance)
{
if (!((Object)(object)__instance == (Object)null))
{
PenTargetStore.Forget(((Il2CppObjectBase)__instance).Pointer);
SlaughterLog.Forget(((Il2CppObjectBase)__instance).Pointer);
}
}
}
internal static class PenSaveKeys
{
internal const string FemalesToKeep = "spgt_femalesToKeep";
}
[HarmonyPatch(typeof(AnimalPen), "SerializeTaskData")]
internal static class PenSerializePatch
{
private static void Postfix(AnimalPen __instance, DataObject __result)
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Expected O, but got Unknown
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Expected O, but got Unknown
try
{
if (__result != null && PenTargetStore.TryGet(__instance, out var femalesToKeep))
{
__result.AddElement("spgt_femalesToKeep", (DataElement)new DataElementInt(femalesToKeep));
}
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(74, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("SPGT event=save_failed - this pen's gender target was not saved. Details: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
}
log.LogError(val);
}
}
}
[HarmonyPatch(typeof(AnimalPen), "DeserializeTaskData")]
internal static class PenDeserializePatch
{
private static void Postfix(AnimalPen __instance, DataObject __0)
{
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Expected O, but got Unknown
try
{
DataElement val = default(DataElement);
if (__0 != null && __0.TryGetElement("spgt_femalesToKeep", ref val))
{
DataElementInt val2 = ((val != null) ? ((Il2CppObjectBase)val).TryCast<DataElementInt>() : null);
if (val2 != null)
{
PenTargetStore.Set(__instance, val2.value);
SlaughterLog.Write("targets_loaded", $"{SlaughterLog.DescribePen(__instance)} keep_f={val2.value}");
}
}
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(74, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("SPGT event=load_failed - this pen will use vanilla slaughtering. Details: ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Exception>(ex);
}
log.LogError(val3);
}
}
}
[HarmonyPatch(typeof(AnimalPen), "GetSmolkrReadyForSlaughter")]
internal static class SlaughterSelectionPatch
{
private static bool Prefix(AnimalPen __instance, ref DomesticSmolkr __0, ref bool __result)
{
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
if (!Plugin.Enabled.Value)
{
return true;
}
if (!PenTargetStore.TryGet(__instance, out var femalesToKeep))
{
return true;
}
try
{
DomesticSmolkr victim;
CullDecision? val = PenReader.Plan(__instance, femalesToKeep, out victim);
if (!val.HasValue)
{
return true;
}
__0 = victim;
__result = (Object)(object)victim != (Object)null;
SlaughterLog.Selected(__instance, val.Value, victim);
return false;
}
catch (Exception exception)
{
SlaughterLog.Failed(exception);
return true;
}
}
}
[HarmonyPatch(typeof(DomesticSmolkr), "_HandleCreatureDead")]
internal static class SmolkrDeathPatch
{
private static void Prefix(DomesticSmolkr __instance)
{
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Expected O, but got Unknown
try
{
object obj;
if (__instance == null)
{
obj = null;
}
else
{
Kennel kennel = __instance._kennel;
obj = ((kennel != null) ? ((Il2CppObjectBase)kennel).TryCast<AnimalPen>() : null);
}
AnimalPen val = (AnimalPen)obj;
if (!((Object)(object)val == (Object)null) && PenTargetStore.TryGet(val, out var _))
{
SlaughterLog.Died(val, __instance);
}
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(36, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("SPGT event=death_log_failed details=");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
}
log.LogWarning(val2);
}
}
}
[HarmonyPatch(typeof(TaskDataPanel), "_SetQuantity")]
internal static class TaskDataPanelSetQuantityPatch
{
private static void Postfix(TaskDataPanel __instance, WorkstationTaskData __0)
{
RowGuard.Run(delegate
{
FemalesToKeepRow.OnQuantitySet(__instance, __0);
});
}
}
[HarmonyPatch(typeof(TaskDataPanel), "_onQuantityChanged")]
internal static class TaskDataPanelQuantityChangedPatch
{
private static void Postfix(TaskDataPanel __instance)
{
RowGuard.Run(delegate
{
FemalesToKeepRow.OnLimitChanged(__instance);
});
}
}
[HarmonyPatch(typeof(IncreaseDecreasePanel), "RefreshAutomaticText")]
internal static class IncreaseDecreaseTextPatch
{
private static void Postfix(IncreaseDecreasePanel __instance)
{
RowGuard.Run(delegate
{
FemalesToKeepRow.OnControlTextRefreshed(__instance);
});
}
}
internal static class RowGuard
{
private static bool _failureReported;
internal static void Run(Action action)
{
try
{
action();
}
catch (Exception value)
{
if (!_failureReported)
{
_failureReported = true;
Plugin.Log.LogError((object)("SPGT event=row_failed - the 'Females to keep' row may be missing or stale; pens keep " + $"their saved targets. Details: {value}"));
}
}
}
}
}