using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
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.InteropTypes.Arrays;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
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("GovernmentTerminal")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.6.9.0")]
[assembly: AssemblyInformationalVersion("0.6.9+0a581adfabc2f8489e595075d1a671771681d055")]
[assembly: AssemblyProduct("GovernmentTerminal")]
[assembly: AssemblyTitle("GovernmentTerminal")]
[assembly: AssemblyVersion("0.6.9.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 GovernmentTerminal
{
[HarmonyPatch(typeof(DesktopIconController), "Setup")]
internal static class DesktopIconPatch
{
private static Sprite? sprite;
[HarmonyPostfix]
private static void Postfix(DesktopIconController __instance, CruncherAppPreset __1)
{
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Expected O, but got Unknown
ConfigEntry<bool>? enabled = Plugin.Enabled;
if (enabled == null || !enabled.Value || (Object)(object)__instance == (Object)null || (Object)(object)__instance.icon == (Object)null)
{
return;
}
try
{
if (IsGovernmentDatabase(__1))
{
Sprite val = Load();
if (!((Object)(object)val == (Object)null))
{
__instance.icon.sprite = val;
__instance.icon.preserveAspect = true;
}
}
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
if (logger != null)
{
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(35, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Terminal desktop icon not applied: ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
}
logger.LogWarning(val2);
}
}
}
private static bool IsGovernmentDatabase(CruncherAppPreset? preset)
{
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Expected I4, but got Unknown
if ((SoCustomComparison)(object)preset == (SoCustomComparison)null || preset.appContent == null)
{
return false;
}
Enumerator<GameObject> enumerator = preset.appContent.GetEnumerator();
while (enumerator.MoveNext())
{
GameObject current = enumerator.Current;
if (!((Object)(object)current == (Object)null))
{
DatabaseApp componentInChildren = current.GetComponentInChildren<DatabaseApp>(true);
if ((Object)(object)componentInChildren != (Object)null && TerminalCommands.ReplacesPool((int)componentInChildren.citizenPool))
{
return true;
}
}
}
return false;
}
private static Sprite? Load()
{
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Expected O, but got Unknown
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)sprite != (Object)null)
{
return sprite;
}
using Stream stream = typeof(DesktopIconPatch).Assembly.GetManifestResourceStream("GovernmentTerminal.TerminalIcon.png");
if (stream == null)
{
ManualLogSource? logger = Plugin.Logger;
if (logger != null)
{
logger.LogWarning((object)"Terminal icon resource missing.");
}
return null;
}
using MemoryStream memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false)
{
filterMode = (FilterMode)1
};
if (!ImageConversion.LoadImage(val, new Il2CppStructArray<byte>(memoryStream.ToArray()), false))
{
return null;
}
((Object)val).hideFlags = (HideFlags)32;
sprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
((Object)sprite).hideFlags = (HideFlags)32;
return sprite;
}
}
[BepInPlugin("chris.governmentterminal", "Government Terminal", "0.6.7")]
public sealed class Plugin : BasePlugin
{
public const string Id = "chris.governmentterminal";
internal static ManualLogSource? Logger;
internal static ConfigEntry<bool>? Enabled;
private Harmony? harmony;
public override void Load()
{
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Expected O, but got Unknown
Logger = ((BasePlugin)this).Log;
Enabled = ((BasePlugin)this).Config.Bind<bool>("General", "Enabled", true, "Replace only the Government Database with a keyboard terminal. F8 restores its original interface for the current window.");
harmony = new Harmony("chris.governmentterminal");
harmony.PatchAll(typeof(Plugin).Assembly);
((BasePlugin)this).Log.LogInfo((object)"Government Terminal 0.6.7 loaded; full-display terminal compiled against supplied 42.04 interop.");
}
public override bool Unload()
{
TerminalWindow.RestoreAll();
Harmony? obj = harmony;
if (obj != null)
{
obj.UnpatchSelf();
}
return true;
}
}
[HarmonyPatch(typeof(DatabaseApp), "OnSetup")]
internal static class SetupPatch
{
[HarmonyPostfix]
private static void Postfix(DatabaseApp __instance)
{
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Expected O, but got Unknown
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Expected I4, but got Unknown
ConfigEntry<bool>? enabled = Plugin.Enabled;
if (enabled == null || !enabled.Value || !TerminalCommands.ReplacesPool((int)__instance.citizenPool))
{
return;
}
try
{
TerminalWindow.Attach(__instance);
}
catch (Exception ex)
{
TerminalWindow.Restore(__instance);
ManualLogSource logger = Plugin.Logger;
if (logger != null)
{
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(51, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Terminal setup failed; original database retained: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
}
logger.LogError(val);
}
}
}
}
[HarmonyPatch(typeof(DatabaseApp), "Update")]
internal static class UpdatePatch
{
[HarmonyPrefix]
private static bool Prefix(DatabaseApp __instance)
{
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Expected O, but got Unknown
TerminalWindow terminalWindow = TerminalWindow.Find(__instance);
if (terminalWindow == null)
{
return true;
}
ConfigEntry<bool>? enabled = Plugin.Enabled;
if (enabled == null || !enabled.Value)
{
TerminalWindow.Restore(__instance);
return true;
}
try
{
terminalWindow.Tick();
return TerminalWindow.Find(__instance) == null;
}
catch (Exception ex)
{
TerminalWindow.Restore(__instance);
ManualLogSource logger = Plugin.Logger;
if (logger != null)
{
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(45, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Terminal failed; original database restored: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
}
logger.LogError(val);
}
return true;
}
}
}
[HarmonyPatch(typeof(DatabaseApp), "OnDestroy")]
internal static class DestroyPatch
{
[HarmonyPrefix]
private static void Prefix(DatabaseApp __instance)
{
TerminalWindow.Forget(__instance);
}
}
[HarmonyPatch(typeof(DatabaseApp), "KeyboardButton")]
internal static class KeyboardPatch
{
[HarmonyPrefix]
private static bool Prefix(DatabaseApp __instance, string __0)
{
TerminalWindow terminalWindow = TerminalWindow.Find(__instance);
if (terminalWindow == null)
{
return true;
}
terminalWindow.Type(__0);
return false;
}
}
[HarmonyPatch(typeof(DatabaseApp), "BackspaceButton")]
internal static class BackspacePatch
{
[HarmonyPrefix]
private static bool Prefix(DatabaseApp __instance)
{
TerminalWindow terminalWindow = TerminalWindow.Find(__instance);
if (terminalWindow == null)
{
return true;
}
terminalWindow.Backspace();
return false;
}
}
[HarmonyPatch(typeof(BioScreenController), "SelectSlot")]
internal static class SlotHotkeyPatch
{
[HarmonyPrefix]
private static bool Prefix()
{
return !TerminalWindow.CapturingInput();
}
}
[HarmonyPatch(typeof(SessionData), "PauseGame")]
internal static class CaseBoardHotkeyPatch
{
[HarmonyPrefix]
private static bool Prefix(bool openDesktopMode)
{
if (openDesktopMode)
{
return !TerminalWindow.TypingAtScreen();
}
return true;
}
}
[HarmonyPatch(typeof(BioScreenController), "SetInventoryOpen")]
internal static class WeaponWheelHotkeyPatch
{
[HarmonyPrefix]
private static bool Prefix(bool val)
{
if (val)
{
return !TerminalWindow.TypingAtScreen();
}
return true;
}
}
public readonly record struct TerminalCommand(string Verb, string Argument);
public static class TerminalCommands
{
public const int MaximumCommandLength = 120;
public const int ResultsPerPage = 10;
public const int Columns = 46;
public const int Rows = 15;
public const int VisibleLines = 12;
public const int ListingLines = 12;
public const int MaximumListingLines = 21;
public static readonly string[] Help = new string[11]
{
"HELP List commands", "SEARCH <name> Citizen data", "SHOWALL All citizens A-Z", "SIFT <clues> e.g. sift eyes green shoe 12", "SIFTHELP Sift filter list", "OPEN <n> Open a record", "PRINT Prints the record", "NEXT/PREV Page results", "CLEAR/CLS Clear screen", "QUIT/Q Close database",
"OLDDB/F8 Original window"
};
public static readonly string[] SiftHelp = new string[15]
{
"SIFT <filter> <value> [filter value ...]", "age 30", "gender m / f / nb", "height tall / medium / short", "build skinny / average / large", "hair bald / short / long; brown", "eyes blue / green / brown ...", "shoe 12", "glasses yes / no", "facialhair yes / no",
"bloodtype a / a+ / o ...", "job title \"police officer\"", "salary 30000 Crows (¢r)", "Numbers: 12 / 20-30 / >40 ", "Combine: SIFT eyes green, shoes 12"
};
public static readonly IReadOnlyDictionary<string, string> FilterFields = new Dictionary<string, string>
{
["eyes"] = "eyes",
["eye"] = "eyes",
["shoe"] = "shoe",
["shoes"] = "shoe",
["blood"] = "blood",
["gender"] = "gender",
["sex"] = "gender",
["height"] = "height",
["hair"] = "hair",
["build"] = "build",
["age"] = "age",
["job"] = "job",
["work"] = "job",
["address"] = "address",
["home"] = "address",
["name"] = "name",
["initial"] = "initials",
["initials"] = "initials",
["bloodtype"] = "blood",
["title"] = "job",
["jobtitle"] = "job",
["glasses"] = "glasses",
["facialhair"] = "facialhair",
["beard"] = "facialhair",
["salary"] = "salary",
["pay"] = "salary"
};
public static bool ReplacesPool(int pool)
{
return pool == 0;
}
public static int ListingPages(int count, int lines)
{
int num = Math.Max(1, lines);
return Math.Max(1, (count + num - 1) / num);
}
public static IEnumerable<string> Banner(string? city, string title = "GOVERNMENT DATABASE")
{
string text = (city ?? string.Empty).Trim();
if (text.Length == 0)
{
yield return title;
yield break;
}
text = text.ToUpperInvariant();
if ((text + " " + title).Length <= 46)
{
yield return text + " " + title;
yield break;
}
yield return text;
yield return title;
}
public static TerminalCommand Parse(string line)
{
line = (line ?? string.Empty).Trim();
int num = line.IndexOf(' ');
TerminalCommand terminalCommand;
if (num >= 0)
{
string verb = line.Substring(0, num).ToLowerInvariant();
string text = line;
int num2 = num + 1;
terminalCommand = new TerminalCommand(verb, text.Substring(num2, text.Length - num2).Trim().Trim('"'));
}
else
{
terminalCommand = new TerminalCommand(line.ToLowerInvariant(), string.Empty);
}
TerminalCommand terminalCommand2 = terminalCommand;
return terminalCommand2 with
{
Verb = terminalCommand2.Verb switch
{
"find" => "sift",
"filter" => "sift",
"close" => "quit",
"exit" => "quit",
"q" => "quit",
"cls" => "clear",
"vanilla" => "olddb",
_ => terminalCommand2.Verb,
}
};
}
public static int AutoOpenIndex(IReadOnlyList<string> names, string query)
{
if (names.Count == 1)
{
return 0;
}
int num = -1;
for (int i = 0; i < names.Count; i++)
{
if (string.Equals(names[i].Trim(), query.Trim(), StringComparison.OrdinalIgnoreCase))
{
if (num >= 0)
{
return -1;
}
num = i;
}
}
return num;
}
public static string PrintIdentifier(int loop)
{
if (loop < 0)
{
return "Unknown";
}
if (loop < 26)
{
return ((char)(65 + loop)).ToString();
}
int num = loop - 26;
int num2 = num / 26;
if (num2 <= 25)
{
return $"{(ushort)(65 + num2)}{(ushort)(65 + num % 26)}";
}
return loop.ToString();
}
public static string BloodType(string value)
{
return value switch
{
"Apos" => "A+",
"Aneg" => "A-",
"Bpos" => "B+",
"Bneg" => "B-",
"ABpos" => "AB+",
"ABneg" => "AB-",
"Opos" => "O+",
"Oneg" => "O-",
_ => "Unknown",
};
}
public static string Label(string value, string suffix = "")
{
if (suffix.Length > 0 && value.EndsWith(suffix, StringComparison.OrdinalIgnoreCase) && value.Length > suffix.Length)
{
string text = value;
int length = suffix.Length;
value = text.Substring(0, text.Length - length);
}
if (value.Length > 1 && value[0] == 'h' && char.IsUpper(value[1]))
{
string text = value;
value = text.Substring(1, text.Length - 1);
}
StringBuilder stringBuilder = new StringBuilder();
char value2;
for (int i = 0; i < value.Length; stringBuilder.Append(value2), i++)
{
char c = value[i];
if (i > 0 && char.IsUpper(c) && !char.IsUpper(value[i - 1]))
{
stringBuilder.Append(' ');
}
if (stringBuilder.Length != 0)
{
if (stringBuilder[stringBuilder.Length - 1] != ' ')
{
value2 = c;
continue;
}
}
value2 = char.ToUpperInvariant(c);
}
return stringBuilder.ToString();
}
public static List<string> Tokenize(string text)
{
List<string> tokens = new List<string>();
StringBuilder sb = new StringBuilder();
bool flag = false;
bool wasQuoted = false;
string text2 = text ?? "";
foreach (char c in text2)
{
if (c == '"' || c == '“' || c == '”')
{
if (flag)
{
flag = false;
continue;
}
Flush();
flag = true;
wasQuoted = true;
}
else if (!flag && (c == ' ' || c == ','))
{
Flush();
}
else
{
sb.Append(c);
}
}
Flush();
return tokens;
void Flush()
{
if (sb.Length > 0 || wasQuoted)
{
tokens.Add(wasQuoted ? ("\"" + sb?.ToString() + "\"") : sb.ToString());
}
sb.Clear();
wasQuoted = false;
}
}
public static List<(string Field, string Value)>? ParseFilters(string argument, out string error)
{
List<(string, string)> list = new List<(string, string)>();
error = "";
foreach (string item in Tokenize(argument ?? ""))
{
bool num = item.StartsWith("\"");
string text = (num ? item.Trim('"') : item);
string text2 = text.ToLowerInvariant();
if (!num && FilterFields.TryGetValue(text2, out string value))
{
if (list.Count > 0)
{
if (list[list.Count - 1].Item1 == value)
{
if (list[list.Count - 1].Item2.Length == 0)
{
continue;
}
}
}
list.Add((value, ""));
}
else if (text.Length != 0 && ((!(text2 == "and") && !(text2 == "&")) || 1 == 0))
{
if (list.Count == 0)
{
error = "Unknown filter '" + text + "'.";
return null;
}
(string, string) tuple = list[list.Count - 1];
list[list.Count - 1] = (tuple.Item1, (tuple.Item2.Length == 0) ? text : (tuple.Item2 + " " + text));
}
}
if (list.Count == 0)
{
error = "No filters given.";
return null;
}
foreach (var item2 in list)
{
if (item2.Item2.Length == 0)
{
error = "Missing value for '" + item2.Item1 + "'.";
return null;
}
}
return list;
}
public static bool Matches(IReadOnlyDictionary<string, string> p, string field, string value)
{
switch (field)
{
case "shoe":
case "age":
return NumberMatches(Get(field).Replace(",", ""), value.Replace(",", ""));
case "salary":
return NumberMatches(Get(field).Replace(",", ""), value.Replace(",", "").Replace("¢r", "", StringComparison.OrdinalIgnoreCase).Replace("crows", "", StringComparison.OrdinalIgnoreCase)
.Trim());
case "height":
{
if (NumberMatches(Get("height"), value))
{
return true;
}
if (IsNumeric(value))
{
return false;
}
string text5 = value.ToLowerInvariant().Trim();
bool flag;
switch (text5)
{
case "medium":
case "average":
case "avg":
flag = true;
break;
default:
flag = false;
break;
}
if (flag)
{
text5 = "average";
}
return WordsMatch(Get("heightclass"), text5);
}
case "gender":
{
string text6 = Squash(value).Replace("-", "");
string text7 = Squash(Get("gender")).Replace("-", "");
string text4;
switch (text6)
{
case "m":
text4 = "male";
break;
case "f":
text4 = "female";
break;
case "nb":
case "n":
case "enby":
case "nonbinary":
text4 = "nonbinary";
break;
default:
text4 = text6;
break;
}
text6 = text4;
return text7 == text6;
}
case "build":
{
string text8 = value.ToLowerInvariant().Trim();
string text9 = Get("build").ToLowerInvariant();
bool flag;
switch (text8)
{
case "large":
case "big":
case "heavy":
flag = true;
break;
default:
flag = false;
break;
}
if (flag)
{
if (text9 == "overweight" || text9 == "muscular")
{
return true;
}
return false;
}
if ((text8 == "thin" || text8 == "slim") ? true : false)
{
text8 = "skinny";
}
if (text8 == "medium")
{
text8 = "average";
}
return text9 == text8;
}
case "hair":
{
string[] words = (Get("hair") + " " + Get("hairstyle")).ToLowerInvariant().Split(' ', StringSplitOptions.RemoveEmptyEntries);
return value.ToLowerInvariant().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(delegate(string w)
{
bool flag5;
switch (w)
{
case "none":
case "nohair":
case "no":
case "shaved":
flag5 = true;
break;
default:
flag5 = false;
break;
}
return (!flag5) ? w : "bald";
})
.All((string w) => words.Contains(w));
}
case "glasses":
case "facialhair":
{
string text10 = value.ToLowerInvariant().Trim();
bool flag;
switch (text10)
{
case "yes":
case "y":
case "true":
flag = true;
break;
default:
flag = false;
break;
}
bool? flag2;
if (flag)
{
flag2 = true;
}
else
{
bool flag3;
switch (text10)
{
case "no":
case "n":
case "none":
case "false":
flag3 = true;
break;
default:
flag3 = false;
break;
}
flag2 = (flag3 ? new bool?(false) : ((bool?)null));
}
bool? flag4 = flag2;
if (flag4.HasValue)
{
return Get(field) == "yes" == flag4.Value;
}
return false;
}
case "blood":
{
string text11 = Squash(value.ToLowerInvariant().Replace("positive", "+").Replace("negative", "-")
.Replace("pos", "+")
.Replace("neg", "-"));
string text12 = Squash(Get("blood"));
if (text12.Length == 0)
{
return false;
}
if (!text11.EndsWith("+") && !text11.EndsWith("-"))
{
return text12.TrimEnd('+', '-') == text11;
}
return text12 == text11;
}
case "name":
case "job":
case "address":
return Get(field).IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0;
case "initials":
{
string text = Squash(value).Replace(".", "");
string text2 = Squash(Get("first"));
string text3 = Squash(Get("last"));
if (text.Length == 1)
{
if (!text2.StartsWith(text))
{
return text3.StartsWith(text);
}
return true;
}
if (text.Length == 2 && text2.StartsWith(text.Substring(0, 1)))
{
string text4 = text;
return text3.StartsWith(text4.Substring(1, text4.Length - 1));
}
return false;
}
default:
return WordsMatch(Get(field), value);
}
string Get(string key)
{
if (!p.TryGetValue(key, out string value2) || value2 == null)
{
return "";
}
return value2;
}
}
private static string Squash(string s)
{
return s.Replace(" ", "").ToLowerInvariant();
}
private static bool IsNumeric(string s)
{
if (!double.TryParse(s.Trim().TrimStart('<', '>', '='), NumberStyles.Float, CultureInfo.InvariantCulture, out var _))
{
double result2;
if (s.Contains('-'))
{
return s.Split('-').All((string x) => double.TryParse(x, NumberStyles.Float, CultureInfo.InvariantCulture, out result2));
}
return false;
}
return true;
}
private static bool WordsMatch(string label, string value)
{
string[] words = label.ToLowerInvariant().Split(' ', StringSplitOptions.RemoveEmptyEntries);
return value.ToLowerInvariant().Split(' ', StringSplitOptions.RemoveEmptyEntries).All((string w) => words.Contains(w));
}
public static bool NumberMatches(string actual, string query)
{
CultureInfo inv = CultureInfo.InvariantCulture;
NumberStyles style = NumberStyles.Float;
if (!double.TryParse(actual, style, inv, out var result))
{
return false;
}
query = query.Replace(" ", "");
if (query.StartsWith(">="))
{
string text = query;
if (Num(text.Substring(2, text.Length - 2), out var n))
{
return result >= n;
}
}
if (query.StartsWith("<="))
{
string text = query;
if (Num(text.Substring(2, text.Length - 2), out var n2))
{
return result <= n2;
}
}
if (query.StartsWith(">"))
{
string text = query;
if (Num(text.Substring(1, text.Length - 1), out var n3))
{
return result > n3;
}
}
if (query.StartsWith("<"))
{
string text = query;
if (Num(text.Substring(1, text.Length - 1), out var n4))
{
return result < n4;
}
}
int num = query.IndexOf('-', 1);
if (num > 0 && Num(query.Substring(0, num), out var n5))
{
string text = query;
int num2 = num + 1;
if (Num(text.Substring(num2, text.Length - num2), out var n6))
{
if (result >= Math.Min(n5, n6))
{
return result <= Math.Max(n5, n6);
}
return false;
}
}
if (Num(query, out var n7))
{
return Math.Abs(result - n7) < 0.01;
}
return false;
bool Num(string s, out double result2)
{
return double.TryParse(s, style, inv, out result2);
}
}
public static int PageCount(int count)
{
return Math.Max(1, (count + 10 - 1) / 10);
}
public static IEnumerable<string> Wrap(string text, int width)
{
if (width < 1)
{
throw new ArgumentOutOfRangeException("width");
}
string[] array = text.Replace("\r", "").Replace("\t", " ").Split('\n');
foreach (string text2 in array)
{
string line = text2;
while (line.Length > width)
{
int cut = line.LastIndexOf(' ', width - 1, width);
if (cut < 1)
{
cut = width;
}
yield return line.Substring(0, cut);
string text3 = line;
int num = cut;
line = text3.Substring(num, text3.Length - num).TrimStart();
}
yield return line;
}
}
}
internal sealed class TerminalWindow
{
private const int Columns = 46;
private const int Rows = 15;
private static readonly Dictionary<int, TerminalWindow> Windows = new Dictionary<int, TerminalWindow>();
private readonly DatabaseApp app;
private readonly List<(GameObject Object, bool Active)> originals = new List<(GameObject, bool)>();
private readonly List<string> output = new List<string>();
private readonly List<string> history = new List<string>();
private readonly List<Human> matches = new List<Human>();
private GameObject? panel;
private TextMeshProUGUI? text;
private string buffer = "";
private string draft = "";
private int historyIndex;
private int page;
private int? siftHelpPage;
private int scroll;
private int listingLines = 12;
private Human? selected;
private bool cursor;
private bool closing;
private static readonly DataKey[] RevealedKeys;
private TerminalWindow(DatabaseApp app)
{
this.app = app;
}
internal static TerminalWindow? Find(DatabaseApp app)
{
if (!Windows.TryGetValue(((Object)app).GetInstanceID(), out TerminalWindow value))
{
return null;
}
return value;
}
internal static void Attach(DatabaseApp app)
{
if (Find(app) == null)
{
TerminalWindow terminalWindow = new TerminalWindow(app);
Windows.Add(((Object)app).GetInstanceID(), terminalWindow);
terminalWindow.CreateScreen();
}
}
private void CreateScreen()
{
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Expected O, but got Unknown
//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
//IL_012a: Unknown result type (might be due to invalid IL or missing references)
//IL_013f: Unknown result type (might be due to invalid IL or missing references)
//IL_0145: Expected O, but got Unknown
//IL_016f: Unknown result type (might be due to invalid IL or missing references)
//IL_0184: Unknown result type (might be due to invalid IL or missing references)
//IL_018f: Unknown result type (might be due to invalid IL or missing references)
//IL_0194: Unknown result type (might be due to invalid IL or missing references)
//IL_0195: Unknown result type (might be due to invalid IL or missing references)
//IL_019c: Unknown result type (might be due to invalid IL or missing references)
//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
//IL_0242: Unknown result type (might be due to invalid IL or missing references)
//IL_0247: Unknown result type (might be due to invalid IL or missing references)
//IL_025e: Unknown result type (might be due to invalid IL or missing references)
//IL_0263: Unknown result type (might be due to invalid IL or missing references)
RectTransform component = ((Component)app).GetComponent<RectTransform>();
if ((Object)(object)component == (Object)null || (Object)(object)app.searchText == (Object)null)
{
throw new InvalidOperationException("Database screen or font unavailable.");
}
ComputerController controller = ((CruncherAppContent)app).controller;
object obj;
if (controller == null)
{
obj = null;
}
else
{
Canvas osCanvas = controller.osCanvas;
obj = ((osCanvas != null) ? ((Component)osCanvas).GetComponent<RectTransform>() : null);
}
if (obj == null)
{
obj = component;
}
RectTransform val = (RectTransform)obj;
for (int i = 0; i < ((Transform)component).childCount; i++)
{
GameObject gameObject = ((Component)((Transform)component).GetChild(i)).gameObject;
originals.Add((gameObject, gameObject.activeSelf));
}
panel = new GameObject("GovernmentTerminal");
panel.layer = ((Component)app).gameObject.layer;
RectTransform val2 = panel.AddComponent<RectTransform>();
((Transform)val2).SetParent((Transform)(object)val, false);
val2.anchorMin = Vector2.zero;
val2.anchorMax = Vector2.one;
Vector2 offsetMin = (val2.offsetMax = Vector2.zero);
val2.offsetMin = offsetMin;
((Transform)val2).SetAsLastSibling();
Image obj2 = panel.AddComponent<Image>();
((Graphic)obj2).color = new Color(0.035f, 0.035f, 0.035f, 1f);
((Graphic)obj2).raycastTarget = true;
GameObject val3 = new GameObject("TerminalText");
val3.layer = panel.layer;
RectTransform obj3 = val3.AddComponent<RectTransform>();
((Transform)obj3).SetParent((Transform)(object)val2, false);
obj3.anchorMin = new Vector2(0.025f, 0.02f);
obj3.anchorMax = new Vector2(0.975f, 0.985f);
offsetMin = (obj3.offsetMax = Vector2.zero);
obj3.offsetMin = offsetMin;
text = val3.AddComponent<TextMeshProUGUI>();
((TMP_Text)text).font = ((TMP_Text)app.searchText).font;
((TMP_Text)text).fontSharedMaterial = ((TMP_Text)app.searchText).fontSharedMaterial;
((Graphic)text).color = Color.white;
((Graphic)text).raycastTarget = false;
((TMP_Text)text).alignment = (TextAlignmentOptions)257;
((TMP_Text)text).enableAutoSizing = false;
((TMP_Text)text).enableWordWrapping = false;
((TMP_Text)text).overflowMode = (TextOverflowModes)3;
((TMP_Text)text).richText = true;
Rect rect = val.rect;
float num = Math.Abs(((Rect)(ref rect)).height) * 0.965f;
rect = val.rect;
float num2 = Math.Abs(((Rect)(ref rect)).width) * 0.95f;
if (num <= 0f || num2 <= 0f)
{
throw new InvalidOperationException("Database screen has zero size.");
}
((TMP_Text)text).fontSize = Math.Min(num / 24f, num2 / 30.36f);
MeasureListingLines(num);
foreach (var original in originals)
{
original.Object.SetActive(false);
}
foreach (string item in TerminalCommands.Banner(CityName()))
{
Write(item);
}
Write(new string('-', 46));
Write("SECURE SESSION ESTABLISHED");
Write("Type HELP for commands. F8 restores the original screen.");
Write("Up/Down: earlier commands. PageUp: scroll.");
Write("");
Render();
}
private void MeasureListingLines(float areaHeight)
{
//IL_0114: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Expected O, but got Unknown
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)this.text == (Object)null)
{
return;
}
try
{
float num;
if ((Object)(object)((TMP_Text)this.text).rectTransform != (Object)null)
{
Rect rect = ((TMP_Text)this.text).rectTransform.rect;
if (((Rect)(ref rect)).height > 0f)
{
rect = ((TMP_Text)this.text).rectTransform.rect;
num = Math.Abs(((Rect)(ref rect)).height);
goto IL_0064;
}
}
num = areaHeight;
goto IL_0064;
IL_0064:
float num2 = num;
if (!(num2 <= 0f))
{
string text = ((TMP_Text)this.text).text;
((TMP_Text)this.text).text = string.Join("\n", Enumerable.Repeat("M", 6));
((TMP_Text)this.text).ForceMeshUpdate(false, false);
float num3 = ((TMP_Text)this.text).preferredHeight / 6f;
((TMP_Text)this.text).text = text;
if (!(num3 <= 0f) && !float.IsNaN(num3) && !float.IsInfinity(num3))
{
int value = (int)Math.Floor(num2 / num3) - 2;
listingLines = Math.Clamp(value, 12, 21);
}
}
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
if (logger != null)
{
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(31, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Line count measurement failed: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
}
logger.LogWarning(val);
}
}
}
private static string CityName()
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Expected O, but got Unknown
try
{
CityData instance = CityData.Instance;
return ((instance != null) ? instance.cityName : null) ?? "";
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
if (logger != null)
{
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(23, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("City name unavailable: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
}
logger.LogWarning(val);
}
return "";
}
}
private void Close()
{
if (!closing)
{
closing = true;
Forget(app);
app.ExitButton();
}
}
internal static bool CapturingInput()
{
foreach (TerminalWindow value in Windows.Values)
{
try
{
if ((Object)(object)value.app != (Object)null && (Object)(object)((CruncherAppContent)value.app).controller != (Object)null && ((CruncherAppContent)value.app).controller.playerControlled && value.PlayerUsesScreen())
{
return true;
}
}
catch
{
}
}
return false;
}
internal static bool TypingAtScreen()
{
foreach (TerminalWindow value in Windows.Values)
{
try
{
if ((Object)(object)value.app != (Object)null && (Object)(object)((CruncherAppContent)value.app).controller != (Object)null && ((CruncherAppContent)value.app).controller.playerControlled && value.LookingAtScreen())
{
return true;
}
}
catch
{
}
}
return false;
}
internal void Tick()
{
if ((Object)(object)((CruncherAppContent)app).controller == (Object)null || !((CruncherAppContent)app).controller.playerControlled || (Object)(object)SessionData.Instance == (Object)null || !SessionData.Instance.play || !LookingAtScreen())
{
return;
}
if (Input.GetKeyDown((KeyCode)289))
{
Restore(app);
return;
}
if (Input.GetKeyDown((KeyCode)273))
{
History(-1);
}
if (Input.GetKeyDown((KeyCode)274))
{
History(1);
}
if (Input.GetKeyDown((KeyCode)280))
{
scroll = Math.Min(Math.Max(0, output.Count - listingLines), scroll + 10);
Render();
}
if (Input.GetKeyDown((KeyCode)281))
{
scroll = Math.Max(0, scroll - 10);
Render();
}
if ((Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305)) && Input.GetKeyDown((KeyCode)108))
{
output.Clear();
scroll = 0;
Render();
}
Type(Input.inputString ?? "", physical: true);
bool flag = (int)(Time.unscaledTime * 2f) % 2 == 0;
if (flag != cursor)
{
cursor = flag;
Render();
}
}
private bool LookingAtScreen()
{
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_010b: Unknown result type (might be due to invalid IL or missing references)
try
{
ComputerController controller = ((CruncherAppContent)app).controller;
MeshCollider val = ((controller != null) ? controller._screenCollider : null);
if ((Object)(object)val == (Object)null)
{
return false;
}
InteractionController instance = InteractionController.Instance;
RaycastHit? val2 = ((instance != null) ? new RaycastHit?(instance.playerCurrentRaycastHit) : ((RaycastHit?)null));
RaycastHit value = default(RaycastHit);
if (val2.HasValue)
{
value = val2.Value;
if ((Object)(object)((RaycastHit)(ref value)).collider != (Object)null)
{
value = val2.Value;
if ((Object)(object)((RaycastHit)(ref value)).collider == (Object)(object)val)
{
return true;
}
}
}
InteractionController instance2 = InteractionController.Instance;
InteractableController obj = ((instance2 != null) ? instance2.currentLookingAtInteractable : null);
ComputerController controller2 = ((CruncherAppContent)app).controller;
if ((Object)(object)obj == (Object)(object)((controller2 != null) ? controller2.ic : null))
{
return true;
}
CameraController instance3 = CameraController.Instance;
Camera val3 = ((instance3 != null) ? instance3.cam : null);
if ((Object)(object)val3 == (Object)null)
{
val3 = Camera.main;
}
if ((Object)(object)val3 == (Object)null)
{
return false;
}
Ray val4 = default(Ray);
((Ray)(ref val4))..ctor(((Component)val3).transform.position, ((Component)val3).transform.forward);
return ((Collider)val).Raycast(val4, ref value, 3f);
}
catch
{
return false;
}
}
private bool PlayerUsesScreen()
{
if (LookingAtScreen())
{
return true;
}
try
{
ComputerController controller = ((CruncherAppContent)app).controller;
InteractableController val = ((controller != null) ? controller.ic : null);
InteractionController instance = InteractionController.Instance;
if ((Object)(object)val == (Object)null || (Object)(object)instance == (Object)null)
{
return false;
}
return (Object)(object)instance.currentInteractable == (Object)(object)val || (Object)(object)instance.currentLookingAtInteractable == (Object)(object)val;
}
catch
{
return false;
}
}
private void KeySound()
{
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Expected O, but got Unknown
//IL_0063: 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)
try
{
ComputerController controller = ((CruncherAppContent)app).controller;
object obj;
if (controller == null)
{
obj = null;
}
else
{
InteractableController ic = controller.ic;
obj = ((ic != null) ? ic.interactable : null);
}
Interactable val = (Interactable)obj;
AudioControls instance = AudioControls.Instance;
AudioEvent val2 = ((instance != null) ? instance.computerKeyboardKey : null);
if (val != null && !((SoCustomComparison)(object)val2 == (SoCustomComparison)null) && !((Object)(object)AudioController.Instance == (Object)null))
{
AudioController.Instance.PlayWorldOneShot(val2, (Actor)(object)Player.Instance, val.node, val.wPos, (Interactable)null, (List<FMODParam>)null, 1f, (List<NewNode>)null, false, (SoundMaterialOverride)null, false);
}
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
if (logger != null)
{
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(18, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Key sound failed: ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(ex.Message);
}
logger.LogWarning(val3);
}
}
}
internal void Type(string value, bool physical = false)
{
if (physical && value.Length > 0)
{
KeySound();
}
for (int i = 0; i < value.Length; i++)
{
char c = value[i];
switch (c)
{
case '\b':
Backspace();
continue;
case '\n':
case '\r':
Submit();
continue;
}
if (!char.IsControl(c) && buffer.Length < 120)
{
buffer += c;
}
}
Render();
}
internal void Backspace()
{
if (buffer.Length > 0)
{
string text = buffer;
buffer = text.Substring(0, text.Length - 1);
}
Render();
}
private void History(int delta)
{
if (history.Count != 0)
{
if (historyIndex == history.Count)
{
draft = buffer;
}
historyIndex = Math.Clamp(historyIndex + delta, 0, history.Count);
buffer = ((historyIndex == history.Count) ? draft : history[historyIndex]);
Render();
}
}
private void Submit()
{
string text = buffer.Trim();
buffer = "";
scroll = 0;
if (text.Length == 0)
{
return;
}
Write("GOV> " + text);
history.Add(text);
if (history.Count > 100)
{
history.RemoveAt(0);
}
historyIndex = history.Count;
draft = "";
TerminalCommand terminalCommand = TerminalCommands.Parse(text);
if (terminalCommand.Verb != "next" && terminalCommand.Verb != "prev")
{
siftHelpPage = null;
}
switch (terminalCommand.Verb)
{
case "help":
{
string[] help = TerminalCommands.Help;
foreach (string message in help)
{
Write(message);
}
break;
}
case "sift":
Sift(terminalCommand.Argument);
break;
case "sifthelp":
SiftUsage();
break;
case "search":
Search(terminalCommand.Argument);
break;
case "show":
case "open":
Open(terminalCommand.Argument);
break;
case "print":
Print();
break;
case "next":
if (siftHelpPage.HasValue)
{
SiftUsage(siftHelpPage.Value + 1);
break;
}
page = Math.Min(TerminalCommands.PageCount(matches.Count) - 1, page + 1);
Results();
break;
case "prev":
if (siftHelpPage.HasValue)
{
SiftUsage(siftHelpPage.Value - 1);
break;
}
page = Math.Max(0, page - 1);
Results();
break;
case "clear":
output.Clear();
break;
case "olddb":
Restore(app);
return;
case "showall":
ShowAll();
break;
case "quit":
Close();
return;
default:
Write("UNKNOWN COMMAND. Type HELP.");
break;
}
Write("");
}
private void Search(string query)
{
if (string.IsNullOrWhiteSpace(query))
{
Write("USAGE: SEARCH <name>");
return;
}
matches.Clear();
selected = null;
page = 0;
app.selectedHuman = null;
if ((Object)(object)app.list != (Object)null)
{
app.list.allOptions = new List<OSMultiOption>();
}
app.searchString = query.ToUpperInvariant();
app.UpdateSearch();
ComputerOSMultiSelect list = app.list;
List<OSMultiOption> val = ((list != null) ? list.allOptions : null);
if (val != null)
{
for (int i = 0; i < val.Count; i++)
{
if ((Object)(object)val[i].human != (Object)null && !((Actor)val[i].human).isPlayer && ((Actor)val[i].human).evidenceEntry != null && !matches.Contains(val[i].human))
{
matches.Add(val[i].human);
}
}
}
foreach (var original in originals)
{
if ((Object)(object)original.Object != (Object)null)
{
original.Object.SetActive(false);
}
}
int num = TerminalCommands.AutoOpenIndex(matches.Select((Human human) => human.GetCitizenName()).ToArray(), query);
if (num >= 0)
{
Open((num + 1).ToString());
return;
}
Results();
if (matches.Count > 1)
{
Write("Multiple matches. Use OPEN <number> or SEARCH <full name>.");
}
}
private void ShowAll()
{
CityData instance = CityData.Instance;
List<Citizen> val = ((instance != null) ? instance.citizenDirectory : null);
if (val == null)
{
Write("Citizen directory unavailable.");
return;
}
matches.Clear();
selected = null;
page = 0;
app.selectedHuman = null;
for (int i = 0; i < val.Count; i++)
{
Human val2 = (Human)(object)val[i];
if ((Object)(object)val2 != (Object)null && !((Actor)val2).isPlayer && ((Actor)val2).evidenceEntry != null && !matches.Contains(val2))
{
matches.Add(val2);
}
}
matches.Sort((Human a, Human b) => string.Compare(a.GetCitizenName(), b.GetCitizenName(), StringComparison.OrdinalIgnoreCase));
Write("SHOWALL");
Results();
if (matches.Count > 0)
{
Write("Use OPEN <number> to view a record. NEXT/PREV to page.");
}
}
private void SiftUsage(int requestedPage = 0)
{
if (TerminalCommands.SiftHelp.Length <= listingLines)
{
siftHelpPage = null;
string[] siftHelp = TerminalCommands.SiftHelp;
foreach (string message in siftHelp)
{
Write(message);
}
return;
}
int num = Math.Max(1, listingLines - 1);
int num2 = TerminalCommands.ListingPages(TerminalCommands.SiftHelp.Length, num);
int num3 = Math.Clamp(requestedPage, 0, num2 - 1);
siftHelpPage = num3;
Write($"SIFT HELP {num3 + 1}/{num2} (NEXT/PREV)");
foreach (string item in TerminalCommands.SiftHelp.Skip(num3 * num).Take(num))
{
Write(item);
}
}
private void Sift(string argument)
{
//IL_0114: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Expected O, but got Unknown
//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
string error;
List<(string, string)> list = TerminalCommands.ParseFilters(argument, out error);
if (list == null)
{
Write(error);
SiftUsage();
return;
}
CityData instance = CityData.Instance;
List<Citizen> val = ((instance != null) ? instance.citizenDirectory : null);
if (val == null)
{
Write("Citizen directory unavailable.");
return;
}
matches.Clear();
selected = null;
page = 0;
app.selectedHuman = null;
bool flag = default(bool);
for (int i = 0; i < val.Count; i++)
{
Human val2 = (Human)(object)val[i];
try
{
if (!((Object)(object)val2 == (Object)null) && !((Actor)val2).isPlayer && ((Actor)val2).evidenceEntry != null)
{
if (list.Any<(string, string)>(((string Field, string Value) f) => f.Field == "blood") && (int)val2.bloodType == 0)
{
val2.GenerateBloodType();
}
Dictionary<string, string> profile = Profile(val2);
if (list.All<(string, string)>(((string Field, string Value) f) => TerminalCommands.Matches(profile, f.Field, f.Value)))
{
matches.Add(val2);
}
}
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
if (logger != null)
{
BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(26, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Filter skipped a citizen: ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(ex.Message);
}
logger.LogWarning(val3);
}
}
}
matches.Sort((Human a, Human b) => string.Compare(a.GetCitizenName(), b.GetCitizenName(), StringComparison.OrdinalIgnoreCase));
Write("SIFT: " + string.Join(", ", list.Select<(string, string), string>(((string Field, string Value) f) => f.Field.ToUpperInvariant() + "=" + f.Value)));
Results();
if (matches.Count > 0)
{
Write("Use OPEN <number> to view a record. NEXT/PREV to page.");
}
}
private static Dictionary<string, string> Profile(Human h)
{
Dictionary<string, string> p = new Dictionary<string, string>();
Descriptors d = h.descriptors;
Add("name", () => h.GetCitizenName());
Add("first", () => h.firstName);
Add("last", () => h.surName);
Add("gender", () => TerminalCommands.Label(((object)h.gender/*cast due to .constrained prefix*/).ToString()));
Add("eyes", () => TerminalCommands.Label(((object)d.eyeColour/*cast due to .constrained prefix*/).ToString(), "Eyes"));
Add("height", () => Math.Round(d.heightCM).ToString(CultureInfo.InvariantCulture));
Add("heightclass", () => TerminalCommands.Label(((object)d.height/*cast due to .constrained prefix*/).ToString()));
Add("shoe", () => Convert.ToDouble(d.shoeSize).ToString(CultureInfo.InvariantCulture));
Add("hair", () => TerminalCommands.Label(((object)d.hairColourCategory/*cast due to .constrained prefix*/).ToString()));
Add("hairstyle", () => TerminalCommands.Label(((object)d.hairType/*cast due to .constrained prefix*/).ToString()));
Add("glasses", () => (!HasFeature((FacialFeature)5)) ? "no" : "yes");
Add("facialhair", () => (!HasFeature((FacialFeature)1) && !HasFeature((FacialFeature)2)) ? "no" : "yes");
Add("salary", () => (h.job == null) ? "0" : Math.Round(h.job.salary).ToString(CultureInfo.InvariantCulture));
Add("build", () => TerminalCommands.Label(((object)d.build/*cast due to .constrained prefix*/).ToString()));
Add("age", () => h.GetAge().ToString(CultureInfo.InvariantCulture));
Add("blood", () => ((int)h.bloodType != 0) ? TerminalCommands.BloodType(((object)h.bloodType/*cast due to .constrained prefix*/).ToString()) : "");
Add("job", () => (h.job == null) ? "Unemployed" : h.job.name);
Add("address", () => (!((Object)(object)h.home != (Object)null)) ? "" : ((Object)h.home).name);
Add("fingerprint", () => (h.fingerprintLoop < 0) ? "" : TerminalCommands.PrintIdentifier(h.fingerprintLoop));
return p;
void Add(string key, Func<string> get)
{
try
{
p[key] = get() ?? "";
}
catch
{
p[key] = "";
}
}
bool HasFeature(FacialFeature f)
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: 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)
List<FacialFeaturesSetting> facialFeatures = d.facialFeatures;
if (facialFeatures == null)
{
return false;
}
for (int i = 0; i < facialFeatures.Count; i++)
{
if (facialFeatures[i].feature == f)
{
return true;
}
}
return false;
}
}
private void Results()
{
Write($"{matches.Count} RECORD(S) / PAGE {page + 1} OF {TerminalCommands.PageCount(matches.Count)}");
int num = page * 10;
for (int i = num; i < Math.Min(num + 10, matches.Count); i++)
{
Write($"{i + 1,4} {matches[i].GetCitizenName()}");
}
if (matches.Count == 0)
{
Write("No records returned by database.");
}
}
private void Open(string argument)
{
if (!int.TryParse(argument, out var result) || result < 1 || result > matches.Count)
{
Write("USAGE: OPEN <number from the last search>");
return;
}
selected = matches[result - 1];
app.selectedHuman = selected;
Write("RECORD / " + selected.GetCitizenName());
Reveal(selected);
Descriptors d = selected.descriptors;
int fingerprintLoop = selected.fingerprintLoop;
Write("Name: " + Safe(() => selected.GetCitizenName()));
Write("Date of Birth: " + Safe(() => selected.birthday));
Write("Gender: " + Safe(() => TerminalCommands.Label(((object)selected.gender/*cast due to .constrained prefix*/).ToString())));
Write("Eyes: " + Safe(() => TerminalCommands.Label(((object)d.eyeColour/*cast due to .constrained prefix*/).ToString(), "Eyes")));
Write("Height: " + Safe(() => $"{Math.Round(d.heightCM)} cm ({TerminalCommands.Label(((object)d.height/*cast due to .constrained prefix*/).ToString())})"));
Write("Fingerprint: " + TerminalCommands.PrintIdentifier(fingerprintLoop));
Write("Shoe Size: " + Safe(() => d.shoeSize.ToString()));
Write("Blood Type: " + Safe(() => TerminalCommands.BloodType(((object)selected.bloodType/*cast due to .constrained prefix*/).ToString())));
Write("Address: " + Safe(() => (!((Object)(object)selected.home != (Object)null)) ? "No fixed address" : ((Object)selected.home).name));
Write("Job Title: " + Safe(() => (selected.job == null) ? "Unemployed" : selected.job.name));
static string Safe(Func<string> get)
{
try
{
string text = get();
return string.IsNullOrWhiteSpace(text) ? "Unknown" : text;
}
catch
{
return "Unknown";
}
}
}
private static void Reveal(Human human)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Expected O, but got Unknown
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: Expected O, but got Unknown
//IL_00a4: 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)
bool flag = default(bool);
try
{
if ((int)human.bloodType == 0)
{
try
{
human.GenerateBloodType();
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
if (logger != null)
{
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(30, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Blood type generation failed: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
}
logger.LogWarning(val);
}
}
}
if (human.fingerprintLoop < 0 && (Object)(object)GameplayController.Instance != (Object)null)
{
int num = (human.fingerprintLoop = Math.Max(0, GameplayController.Instance.printsLetterLoop));
GameplayController.Instance.printsLetterLoop = num + 1;
}
EvidenceWitness evidenceEntry = ((Actor)human).evidenceEntry;
if (evidenceEntry != null)
{
DataKey[] revealedKeys = RevealedKeys;
foreach (DataKey val2 in revealedKeys)
{
((Evidence)evidenceEntry).MergeDataKeys((DataKey)0, val2);
}
}
}
catch (Exception ex2)
{
ManualLogSource logger = Plugin.Logger;
if (logger != null)
{
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(22, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Record reveal failed: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex2.Message);
}
logger.LogWarning(val);
}
}
}
private void Print()
{
if ((Object)(object)selected == (Object)null)
{
Write("No selected record. Use SEARCH, then OPEN <number>.");
return;
}
if ((Object)(object)((CruncherAppContent)app).controller == (Object)null || ((CruncherAppContent)app).controller.printTimer > 0f || ((CruncherAppContent)app).controller.printedDocument != null)
{
Write("PRINTER BUSY. Collect the previous document first.");
return;
}
Reveal(selected);
app.selectedHuman = selected;
app.OnPrintEntry();
Write("Print request sent.");
}
private void Write(string message)
{
output.AddRange(TerminalCommands.Wrap(message, 46));
if (output.Count > 500)
{
output.RemoveRange(0, output.Count - 500);
}
}
private void Render()
{
if (!((Object)(object)this.text == (Object)null))
{
int num = Math.Max(0, output.Count - scroll);
int num2 = Math.Max(0, num - listingLines);
string obj = string.Join("\n", output.Skip(num2).Take(num - num2));
string obj2;
if (buffer.Length <= 39)
{
obj2 = buffer;
}
else
{
string obj3 = buffer;
int length = obj3.Length;
int num3 = length - 39;
obj2 = obj3.Substring(num3, length - num3);
}
string text = obj2;
string text2 = (obj + "\n\nGOV> " + text + (cursor ? "_" : " ")).Replace("<", "‹").Replace(">", "›");
((TMP_Text)this.text).text = "<mspace=0.65em>" + text2 + "</mspace>";
}
}
internal static void Restore(DatabaseApp app)
{
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Expected O, but got Unknown
TerminalWindow terminalWindow = Find(app);
if (terminalWindow == null)
{
return;
}
Windows.Remove(((Object)app).GetInstanceID());
foreach (var original in terminalWindow.originals)
{
if ((Object)(object)original.Object != (Object)null)
{
original.Object.SetActive(original.Active);
}
}
if ((Object)(object)terminalWindow.panel != (Object)null)
{
Object.Destroy((Object)(object)terminalWindow.panel);
}
app.searchString = "";
app.selectedHuman = null;
try
{
app.UpdateSearch();
app.UpdateSelected();
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
if (logger != null)
{
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(34, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Original database refresh failed: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
}
logger.LogWarning(val);
}
}
}
internal static void Forget(DatabaseApp app)
{
TerminalWindow terminalWindow = Find(app);
if (terminalWindow != null)
{
Windows.Remove(((Object)app).GetInstanceID());
if ((Object)(object)terminalWindow.panel != (Object)null)
{
Object.Destroy((Object)(object)terminalWindow.panel);
}
terminalWindow.panel = null;
terminalWindow.text = null;
}
}
internal static void RestoreAll()
{
TerminalWindow[] array = Windows.Values.ToArray();
for (int i = 0; i < array.Length; i++)
{
Restore(array[i].app);
}
}
static TerminalWindow()
{
DataKey[] array = new DataKey[9];
RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
RevealedKeys = (DataKey[])(object)array;
}
}
}