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 BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppSystem.Collections.Generic;
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("DocumentScanner")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+931376c72df42be3ca58535415d58d93cd8863b6")]
[assembly: AssemblyProduct("DocumentScanner")]
[assembly: AssemblyTitle("DocumentScanner")]
[assembly: AssemblyVersion("0.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[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 DocumentScanner
{
[BepInPlugin("sm3gm.documentscanner", "Document Scanner", "1.0.9")]
public class DocumentScannerPlugin : BasePlugin
{
internal const string VER = "1.0.9";
internal static ManualLogSource LogSource;
internal static ConfigEntry<MessageMode> Messages;
internal static ConfigEntry<bool> AssignLetters;
public override void Load()
{
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Expected O, but got Unknown
LogSource = ((BasePlugin)this).Log;
Messages = ((BasePlugin)this).Config.Bind<MessageMode>("Messages", "ScannerPopups", MessageMode.Game, "Game (default): popups appear the moment the scanner reveals something. Batch: hold them while you flip and show them all at once when you pause (other mods that add to popups still work). Summary: one line instead, such as 37 new details.");
Harmony.CreateAndPatchAll(typeof(ReadingOverlayPatch), (string)null);
AssignLetters = ((BasePlugin)this).Config.Bind<bool>("Fingerprints", "AssignLetters", true, "When a scanned record reveals someone's fingerprints (an employee record, for example), give those prints their letter, as opening the record would. On by default. Mods that remove fingerprints from records are respected: no prints revealed, no letter.");
Harmony.CreateAndPatchAll(typeof(MessageBatch), (string)null);
Harmony.CreateAndPatchAll(typeof(PrintLetters), (string)null);
((BasePlugin)this).AddComponent<LookWatcher>();
ManualLogSource log = ((BasePlugin)this).Log;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(24, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Document Scanner ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.0.9");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded");
}
log.LogInfo(val);
}
}
internal static class Scanner
{
private static readonly HashSet<string> OverlayItems = new HashSet<string> { "WorkRota" };
private static readonly HashSet<string> LookItems = new HashSet<string> { "PrintedEmployeeRecord", "WorkDocument", "IDCard", "WorkID", "EmployeePhoto" };
private static readonly HashSet<string> Excluded = new HashSet<string> { "CityDirectory" };
private static bool loggedError;
private static int loggedBox;
internal static void OnReadingOverlay(Interactable interactable)
{
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Expected O, but got Unknown
InteractablePreset preset = interactable.preset;
Evidence evidence = interactable.evidence;
if ((SoCustomComparison)(object)preset == (SoCustomComparison)null || evidence == null || Excluded.Contains(((Object)preset).name))
{
return;
}
EvidenceMultiPage val = ((Il2CppObjectBase)evidence).TryCast<EvidenceMultiPage>();
if (val != null)
{
bool flag = ((Object)preset).name.StartsWith("StorageBox") && !interactable.sw0;
if (((Object)preset).name.StartsWith("StorageBox") && loggedBox++ < 3)
{
ManualLogSource logSource = DocumentScannerPlugin.LogSource;
bool flag2 = default(bool);
BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(20, 3, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[BOX] ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)preset).name);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" open=");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(interactable.sw0);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" locked=");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(interactable.locked);
}
logSource.LogInfo(val2);
}
RevealVisiblePage(val, !flag);
}
else if (OverlayItems.Contains(((Object)preset).name))
{
MarkFound(evidence);
}
}
internal static void OnLookedAt(Interactable interactable)
{
InteractablePreset preset = interactable.preset;
Evidence evidence = interactable.evidence;
if (!((SoCustomComparison)(object)preset == (SoCustomComparison)null) && evidence != null && !Excluded.Contains(((Object)preset).name) && LookItems.Contains(((Object)preset).name))
{
MarkFound(evidence);
}
}
private static void RevealVisiblePage(EvidenceMultiPage multiPage, bool contents)
{
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
List<MultiPageContent> pageContent = multiPage.pageContent;
if (pageContent == null)
{
return;
}
int page = multiPage.page;
for (int i = 0; i < pageContent.Count; i++)
{
MultiPageContent val = pageContent[i];
if (val == null || val.page != page)
{
continue;
}
if (!string.IsNullOrEmpty(val.discEvID) && TryGetEvidence(val.discEvID, out Evidence evidence))
{
MessageBatch.depth++;
try
{
evidence.AddDiscovery(val.disc);
}
finally
{
MessageBatch.depth--;
}
}
if (!string.IsNullOrEmpty(val.evID) && TryGetEvidence(val.evID, out Evidence evidence2))
{
MarkFound(evidence2);
}
if (contents && val.meta != 0)
{
CityData instance = CityData.Instance;
object obj;
if (instance == null)
{
obj = null;
}
else
{
MetaObject obj2 = instance.FindMetaObject(val.meta);
obj = ((obj2 != null) ? obj2.GetEvidence(false, default(Vector3Int)) : null);
}
Evidence val2 = (Evidence)obj;
if (val2 != null)
{
MarkFound(val2);
}
}
}
}
private static bool TryGetEvidence(string id, out Evidence evidence)
{
evidence = null;
if ((Object)(object)Toolbox.Instance != (Object)null && Toolbox.Instance.TryGetEvidence(id, ref evidence))
{
return evidence != null;
}
return false;
}
private static void MarkFound(Evidence ev)
{
if (((CaseComponent)ev).isFound)
{
return;
}
MessageBatch.depth++;
try
{
((CaseComponent)ev).SetFound(true);
}
finally
{
MessageBatch.depth--;
}
}
internal static void Guard(Action action)
{
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Expected O, but got Unknown
try
{
action();
}
catch (Exception ex)
{
if (!loggedError)
{
loggedError = true;
ManualLogSource logSource = DocumentScannerPlugin.LogSource;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(52, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Document Scanner error (further errors suppressed): ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
}
logSource.LogError(val);
}
}
}
}
[HarmonyPatch(typeof(InteractionController), "SetReadingMode")]
internal static class ReadingOverlayPatch
{
private static void Postfix(bool val)
{
if (!val)
{
return;
}
Scanner.Guard(delegate
{
InteractionController instance = InteractionController.Instance;
object obj;
if (instance == null)
{
obj = null;
}
else
{
InteractableController currentLookingAtReadingRange = instance.currentLookingAtReadingRange;
obj = ((currentLookingAtReadingRange != null) ? currentLookingAtReadingRange.interactable : null);
}
Interactable val2 = (Interactable)obj;
if (val2 != null)
{
Scanner.OnReadingOverlay(val2);
}
});
}
}
public class LookWatcher : MonoBehaviour
{
private IntPtr last;
private IntPtr lastFile;
private int lastPage = -1;
public LookWatcher(IntPtr ptr)
: base(ptr)
{
}
private void Update()
{
Scanner.Guard(MessageBatch.Flush);
Scanner.Guard(delegate
{
InteractionController instance = InteractionController.Instance;
object obj;
if (instance == null)
{
obj = null;
}
else
{
InteractableController currentLookingAtReadingRange = instance.currentLookingAtReadingRange;
obj = ((currentLookingAtReadingRange != null) ? currentLookingAtReadingRange.interactable : null);
}
Interactable val = (Interactable)obj;
object obj2;
if (val == null)
{
obj2 = null;
}
else
{
Evidence evidence = val.evidence;
obj2 = ((evidence != null) ? ((Il2CppObjectBase)evidence).TryCast<EvidenceMultiPage>() : null);
}
EvidenceMultiPage val2 = (EvidenceMultiPage)obj2;
if (val2 == null)
{
lastFile = IntPtr.Zero;
}
else if (!(((Il2CppObjectBase)val2).Pointer == lastFile) || val2.page != lastPage)
{
lastFile = ((Il2CppObjectBase)val2).Pointer;
lastPage = val2.page;
Scanner.OnReadingOverlay(val);
}
});
Scanner.Guard(delegate
{
InteractionController instance = InteractionController.Instance;
InteractableController val = ((instance != null) ? instance.currentLookingAtInteractable : null);
IntPtr intPtr = (((Object)(object)val == (Object)null) ? IntPtr.Zero : ((Il2CppObjectBase)val).Pointer);
if (!(intPtr == last))
{
last = intPtr;
Interactable val2 = ((val != null) ? val.interactable : null);
if (val2 != null)
{
Scanner.OnLookedAt(val2);
}
}
});
}
}
public enum MessageMode
{
Batch,
Summary,
Game
}
[HarmonyPatch(typeof(InterfaceController), "NewGameMessage")]
internal static class MessageBatch
{
internal static int depth;
private static bool releasing;
private static float lastHeld;
private static readonly List<object[]> held = new List<object[]>();
private static MethodBase? method;
private static bool Prefix(GameMessageType newType, int newMergeType, string newMessage, MethodBase __originalMethod, object[] __args)
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Invalid comparison between Unknown and I4
if (releasing || depth <= 0 || DocumentScannerPlugin.Messages.Value == MessageMode.Game)
{
return true;
}
if ((int)newType != 0 && (int)newType != 2)
{
return true;
}
method = __originalMethod;
held.Add((object[])__args.Clone());
lastHeld = Time.realtimeSinceStartup;
return false;
}
internal static void Flush()
{
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
if (held.Count == 0 || Time.realtimeSinceStartup - lastHeld < 1.5f)
{
return;
}
object[][] array = held.ToArray();
held.Clear();
InterfaceController instance = InterfaceController.Instance;
if ((Object)(object)instance == (Object)null)
{
return;
}
if (DocumentScannerPlugin.Messages.Value == MessageMode.Summary || method == null)
{
instance.NewGameMessage((GameMessageType)0, 0, (array.Length == 1) ? "Document Scanner: 1 new detail" : $"Document Scanner: {array.Length} new details", (Icon)3, (AudioEvent)null, false, default(Color), -1, 0f, (RectTransform)null, (PingOnComplete)0, (Evidence)null, (List<DataKey>)null, (Sprite)null);
return;
}
releasing = true;
try
{
object[][] array2 = array;
foreach (object[] parameters in array2)
{
method.Invoke(instance, parameters);
}
}
finally
{
releasing = false;
}
}
}
[HarmonyPatch]
internal static class PrintLetters
{
private static int logged;
private static IEnumerable<MethodBase> TargetMethods()
{
foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(typeof(Evidence)))
{
if (declaredMethod.Name == "MergeDataKeys" && declaredMethod.GetParameters().Length == 2)
{
yield return declaredMethod;
}
}
}
private static void Postfix(Evidence __instance, DataKey keyOne, DataKey keyTwo)
{
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Invalid comparison between Unknown and I4
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Invalid comparison between Unknown and I4
if (MessageBatch.depth <= 0 || !DocumentScannerPlugin.AssignLetters.Value || ((int)keyOne != 2 && (int)keyTwo != 2))
{
return;
}
Scanner.Guard(delegate
{
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Expected O, but got Unknown
EvidenceCitizen obj = ((Il2CppObjectBase)__instance).TryCast<EvidenceCitizen>();
Human val = ((obj != null) ? obj.witnessController : null);
GameplayController instance = GameplayController.Instance;
if (!((Object)(object)val == (Object)null) && !((Object)(object)instance == (Object)null) && val.fingerprintLoop <= -1)
{
val.fingerprintLoop = instance.printsLetterLoop;
int printsLetterLoop = instance.printsLetterLoop;
instance.printsLetterLoop = printsLetterLoop + 1;
if (logged++ < 20)
{
ManualLogSource logSource = DocumentScannerPlugin.LogSource;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(28, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[PRINTS] ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(val.GetCitizenName());
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" gets print letter ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(val.fingerprintLoop);
}
logSource.LogInfo(val2);
}
}
});
}
}
}