using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.Json;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using SOD.Common;
using SOD.Common.BepInEx;
using SOD.Common.Helpers;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("VmailAttachments")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("My first plugin")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("VmailAttachments")]
[assembly: AssemblyTitle("VmailAttachments")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 VmailAttachments
{
public class AttachmentButton : MonoBehaviour
{
private VMailApp _app;
private AttachmentButtonHandler _handler;
private Button _button;
private TextMeshProUGUI _label;
private bool _currentAttachmentExists = false;
private string _currentAttachmentInteractablePresetName = string.Empty;
private int _currentAttachmentWriterID = -1;
private int _currentAttachmentReceiverID = -1;
private void Awake()
{
NukeAutoTextController();
SetupLabel();
SetupButton();
}
private void OnEnable()
{
AddButtonListeners();
}
private void OnDisable()
{
RemoveButtonListeners();
}
public void Initialize(VMailApp app, Component handlerComponent)
{
_app = app;
if (handlerComponent is AttachmentButtonHandler handler)
{
_handler = handler;
}
SetCurrentAttachment(exists: false);
}
private void NukeAutoTextController()
{
ComputerAutoTextController componentInChildren = ((Component)this).gameObject.GetComponentInChildren<ComputerAutoTextController>();
if ((Object)(object)componentInChildren != (Object)null)
{
Object.DestroyImmediate((Object)(object)componentInChildren);
}
else
{
Utilities.Log("AttachmentButton.NukeAutoTextController: Expected autoTextController but it was null.", (LogLevel)32);
}
}
private void SetupLabel()
{
_label = ((Component)this).gameObject.GetComponentInChildren<TextMeshProUGUI>();
if ((Object)(object)_label != (Object)null)
{
((TMP_Text)_label).text = "Attached";
((TMP_Text)_label).overflowMode = (TextOverflowModes)0;
((TMP_Text)_label).enableWordWrapping = false;
}
else
{
Utilities.Log("AttachmentButton.SetupLabel: Expected textMeshPro but it was null.", (LogLevel)32);
}
}
private void SetupButton()
{
_button = ((Component)this).gameObject.GetComponentInChildren<Button>();
if ((Object)(object)_button == (Object)null)
{
Utilities.Log("AttachmentButton.SetupButton: Expected attachmentButton but it was null.", (LogLevel)32);
}
}
private void RemoveButtonListeners()
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Expected O, but got Unknown
if ((Object)(object)_button != (Object)null)
{
_button.onClick = new ButtonClickedEvent();
}
}
private void AddButtonListeners()
{
RemoveButtonListeners();
if ((Object)(object)_button != (Object)null)
{
Action action = OnAttachmentButtonClicked;
((UnityEvent)_button.onClick).AddListener(UnityAction.op_Implicit(action));
}
}
private void OnAttachmentButtonClicked()
{
VMailApp app = _app;
PrintCurrentDatabaseEntry((app != null) ? ((CruncherAppContent)app).controller : null);
}
private void PrintCurrentDatabaseEntry(ComputerController currentCruncher)
{
//IL_016d: Unknown result type (might be due to invalid IL or missing references)
//IL_017d: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: 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_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
if (_currentAttachmentExists)
{
if ((Object)(object)currentCruncher == (Object)null)
{
Utilities.Log("AttachmentButton.PrintCurrentDatabaseEntry: Tried to print an attachment, but not at a computer!", (LogLevel)32);
}
else if (currentCruncher.printedDocument == null && currentCruncher.printTimer <= 0f)
{
currentCruncher.printTimer = 1f;
Vector3 localPosition = currentCruncher.printerParent.localPosition;
currentCruncher.printerParent.localPosition = new Vector3(localPosition.x, localPosition.y, -0.05f);
AudioController.Instance.PlayWorldOneShot(AudioControls.Instance.computerPrint, (Actor)(object)Player.Instance, currentCruncher.ic.interactable.node, currentCruncher.ic.interactable.wPos, (Interactable)null, (List<FMODParam>)null, 1f, (List<NewNode>)null, false, (SoundMaterialOverride)null, false);
currentCruncher.printedDocument = CreateAttachmentDocument(currentCruncher.printerParent.position, ((Component)currentCruncher.ic).transform.eulerAngles);
Action action = ((CruncherAppContent)_app).OnPlayerTakePrint;
Interactable printedDocument = currentCruncher.printedDocument;
printedDocument.OnRemovedFromWorld += RemovedFromWorld.op_Implicit(action);
Utilities.Log("AttachmentButton.PrintCurrentDatabaseEntry: Successfully printed an attachment!", (LogLevel)32);
}
else
{
AudioController.Instance.PlayWorldOneShot(AudioControls.Instance.computerInvalidPasscode, (Actor)(object)Player.Instance, currentCruncher.ic.interactable.node, currentCruncher.ic.interactable.wPos, (Interactable)null, (List<FMODParam>)null, 1f, (List<NewNode>)null, false, (SoundMaterialOverride)null, false);
Utilities.Log("AttachmentButton.PrintCurrentDatabaseEntry: Tried to print an attachment, but the print cooldown isn't done!", (LogLevel)32);
}
}
}
public void SetCurrentAttachment(bool exists, string interactablePresetName = "", int writerID = -1, int receiverID = -1)
{
_currentAttachmentExists = exists;
_currentAttachmentInteractablePresetName = interactablePresetName;
_currentAttachmentWriterID = writerID;
_currentAttachmentReceiverID = receiverID;
}
private InteractablePreset GetInteractablePreset()
{
return Toolbox.Instance.GetInteractablePreset(_currentAttachmentInteractablePresetName);
}
private Human GetWriterHuman()
{
return (Human)(object)CityData.Instance.citizenDirectory.Find(Predicate<Citizen>.op_Implicit((Func<Citizen, bool>)FindWriterPredicate));
}
private Human GetReceiverHuman()
{
return (Human)(object)CityData.Instance.citizenDirectory.Find(Predicate<Citizen>.op_Implicit((Func<Citizen, bool>)FindReceiverPredicate));
}
private bool FindWriterPredicate(Citizen item)
{
return ((Human)item).humanID == _currentAttachmentWriterID;
}
private bool FindReceiverPredicate(Citizen item)
{
return ((Human)item).humanID == _currentAttachmentReceiverID;
}
private Interactable CreateAttachmentDocument(Vector3 worldPosition, Vector3 worldRotation)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
Interactable val = InteractableCreator.Instance.CreateWorldInteractable(GetInteractablePreset(), (Human)(object)Player.Instance, GetWriterHuman(), GetReceiverHuman(), worldPosition, worldRotation, (List<Passed>)null, (Object)null, "");
if (val != null)
{
val.MarkAsTrash(true, false, 0f);
}
return val;
}
}
public class AttachmentButtonHandler : MonoBehaviour
{
public static Action<VMailApp, MessageThreadSave> OnVmailSelected;
private VMailApp _app;
private AttachmentButton _button;
private void OnEnable()
{
RefreshCurrentAppState();
OnVmailSelected = (Action<VMailApp, MessageThreadSave>)Delegate.Remove(OnVmailSelected, new Action<VMailApp, MessageThreadSave>(OnVmailSelection));
OnVmailSelected = (Action<VMailApp, MessageThreadSave>)Delegate.Combine(OnVmailSelected, new Action<VMailApp, MessageThreadSave>(OnVmailSelection));
}
private void OnDisable()
{
OnVmailSelected = (Action<VMailApp, MessageThreadSave>)Delegate.Remove(OnVmailSelected, new Action<VMailApp, MessageThreadSave>(OnVmailSelection));
}
public void Initialize(VMailApp app)
{
_app = app;
_button = FindOrCreateButton();
_button.Initialize(app, (Component)(object)this);
RefreshCurrentAppState();
}
private void RefreshCurrentAppState()
{
if ((Object)(object)_app != (Object)null)
{
VMailApp app = _app;
VMailApp app2 = _app;
OnVmailSelection(app, (app2 != null) ? app2.selectedThread : null);
}
}
private void OnVmailSelection(VMailApp app, MessageThreadSave vmail)
{
if ((Object)(object)app == (Object)(object)_app)
{
CheckButtonVisibility(vmail);
}
}
private void CheckButtonVisibility(MessageThreadSave vmail)
{
AttachmentDatabaseEntry attachment;
if (vmail == null)
{
_button.SetCurrentAttachment(exists: false);
((Component)_button).gameObject.SetActive(false);
}
else if (VmailAttachmentsPlugin.TryGetAttachment(vmail.threadID, out attachment))
{
_button.SetCurrentAttachment(exists: true, attachment.InteractablePresetName, attachment.WriterID, attachment.ReceiverID);
((Component)_button).gameObject.SetActive(true);
}
else
{
_button.SetCurrentAttachment(exists: false);
((Component)_button).gameObject.SetActive(false);
}
}
private AttachmentButton FindOrCreateButton()
{
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: 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)
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
AttachmentButton componentInChildren = ((Component)this).gameObject.GetComponentInChildren<AttachmentButton>();
if ((Object)(object)componentInChildren != (Object)null)
{
return componentInChildren;
}
Button val = null;
foreach (Button componentsInChild in ((Component)this).gameObject.GetComponentsInChildren<Button>())
{
if (((Object)((Component)componentsInChild).gameObject).name != "Print")
{
continue;
}
val = componentsInChild;
break;
}
if ((Object)(object)val == (Object)null)
{
Utilities.Log("AttachmentButtonHandler.FindOrCreateButton: Needed to create attachment button but print button doesn't exist!", (LogLevel)32);
return null;
}
GameObject gameObject = ((Component)val).gameObject;
GameObject val2 = Object.Instantiate<GameObject>(gameObject, gameObject.transform.parent);
Vector3 localPosition = val2.transform.localPosition;
val2.transform.localPosition = new Vector3(localPosition.x, localPosition.y + 0.06f, localPosition.z);
return val2.AddComponent<AttachmentButton>();
}
}
[HarmonyPatch]
public class VmailSelectionPatch
{
[HarmonyPatch(typeof(VMailApp), "SetSelectedVmail")]
private static void Postfix(VMailApp __instance)
{
Utilities.Log("VmailSelectionPatch.Postfix: Triggered!", (LogLevel)32);
AttachmentButtonHandler.OnVmailSelected?.Invoke(__instance, (__instance != null) ? __instance.selectedThread : null);
}
}
[HarmonyPatch]
public class VmailSetupPatch
{
[HarmonyPatch(typeof(VMailApp), "OnSetup")]
private static void Postfix(VMailApp __instance)
{
Utilities.Log("VmailSetupPatch.Postfix: Triggered!", (LogLevel)32);
GameObject gameObject = ((Component)__instance).gameObject;
AttachmentButtonHandler attachmentButtonHandler = gameObject.GetComponent<AttachmentButtonHandler>() ?? gameObject.AddComponent<AttachmentButtonHandler>();
attachmentButtonHandler.Initialize(__instance);
}
}
[Serializable]
public class AttachmentDatabase
{
public Dictionary<int, AttachmentDatabaseEntry> Database = new Dictionary<int, AttachmentDatabaseEntry>();
}
[Serializable]
public class AttachmentDatabaseEntry
{
public string InteractablePresetName;
public int WriterID;
public int ReceiverID;
public override string ToString()
{
return $"AttachmentDatabaseEntry: {InteractablePresetName}, {WriterID}, {ReceiverID}";
}
}
public static class Utilities
{
public const bool DEBUG_BUILD = false;
public static void Log(string message, LogLevel level = 16)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0004: Invalid comparison between Unknown and I4
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
if ((int)level == 32)
{
bool flag = false;
}
else
{
PluginController<VmailAttachmentsPlugin, IEmptyBindings>.Log.Log(level, (object)message);
}
}
}
[BepInPlugin("VmailAttachments", "VmailAttachments", "1.0.0")]
public class VmailAttachmentsPlugin : PluginController<VmailAttachmentsPlugin>
{
private static AttachmentDatabase _db = new AttachmentDatabase();
public override void Load()
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Expected O, but got Unknown
Utilities.Log("Plugin VmailAttachments is loaded!", (LogLevel)16);
Harmony val = new Harmony("VmailAttachments");
val.PatchAll();
Utilities.Log("Plugin VmailAttachments is patched!", (LogLevel)16);
ClassInjector.RegisterTypeInIl2Cpp<AttachmentButton>();
ClassInjector.RegisterTypeInIl2Cpp<AttachmentButtonHandler>();
Utilities.Log("Plugin VmailAttachments has added custom types!", (LogLevel)16);
Lib.SaveGame.OnAfterSave -= OnAfterSave;
Lib.SaveGame.OnAfterSave += OnAfterSave;
Lib.SaveGame.OnAfterLoad -= OnAfterLoad;
Lib.SaveGame.OnAfterLoad += OnAfterLoad;
Lib.SaveGame.OnAfterNewGame -= OnAfterNewGame;
Lib.SaveGame.OnAfterNewGame += OnAfterNewGame;
}
public override bool Unload()
{
Lib.SaveGame.OnAfterSave -= OnAfterSave;
Lib.SaveGame.OnAfterLoad -= OnAfterLoad;
Lib.SaveGame.OnAfterNewGame -= OnAfterNewGame;
return ((PluginController<VmailAttachmentsPlugin, IEmptyBindings>)(object)this).Unload();
}
public static void AddAttachment(int vmailID, string preset, int writer, int receiver)
{
AttachmentDatabaseEntry attachmentDatabaseEntry = new AttachmentDatabaseEntry
{
InteractablePresetName = preset,
WriterID = writer,
ReceiverID = receiver
};
_db.Database[vmailID] = attachmentDatabaseEntry;
Utilities.Log($"VmailAttachmentsPlugin.AddAttachment: Added {attachmentDatabaseEntry.ToString()} to vmail {vmailID}!", (LogLevel)32);
}
public static void AddAttachment(MessageThreadSave vmail, InteractablePreset preset, Human writer, Human receiver)
{
AddAttachment(vmail.threadID, ((SoCustomComparison)preset).presetName, writer.humanID, receiver.humanID);
}
public static bool TryGetAttachment(int vmailID, out AttachmentDatabaseEntry attachment)
{
bool result = _db.Database.TryGetValue(vmailID, out attachment);
if (attachment != null)
{
Utilities.Log($"VmailAttachmentsPlugin.TryGetAttachment: Vmail {vmailID}...found {attachment.ToString()}!", (LogLevel)32);
}
else
{
Utilities.Log($"VmailAttachmentsPlugin.TryGetAttachment: Vmail {vmailID}...found NULL!", (LogLevel)32);
}
return result;
}
private void OnAfterSave(object sender, SaveGameArgs args)
{
SaveToJsonAsync(args.FilePath);
}
private void OnAfterLoad(object sender, SaveGameArgs args)
{
LoadFromJsonAsync(args.FilePath);
}
private void OnAfterNewGame(object sender, EventArgs args)
{
_db = new AttachmentDatabase();
Utilities.Log("VmailAttachmentsPlugin.OnAfterNewGame: Initializing new attachment database!", (LogLevel)16);
}
private static string GetPluginSavePath(string savePath)
{
string uniqueString = Lib.SaveGame.GetUniqueString(savePath);
string text = "VmailAttachments_" + uniqueString + ".json";
return Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), text);
}
private async Task SaveToJsonAsync(string savePath)
{
if (_db == null)
{
Utilities.Log("VmailAttachmentsPlugin.OnAfterSave: Cannot save a null map.", (LogLevel)2);
return;
}
string pluginPath = GetPluginSavePath(savePath);
try
{
string json = JsonSerializer.Serialize(options: new JsonSerializerOptions
{
IncludeFields = true
}, value: _db);
await File.WriteAllTextAsync(pluginPath, json);
Utilities.Log($"VmailAttachmentsPlugin.OnAfterSave: Successfully saved {_db.Database.Count} attachments to database at {pluginPath}!", (LogLevel)16);
}
catch (Exception e)
{
Utilities.Log("VmailAttachmentsPlugin.OnAfterSave: " + e.Message, (LogLevel)2);
}
}
private async Task LoadFromJsonAsync(string savePath)
{
string pluginPath = GetPluginSavePath(savePath);
try
{
_db = JsonSerializer.Deserialize<AttachmentDatabase>(options: new JsonSerializerOptions
{
IncludeFields = true
}, json: await File.ReadAllTextAsync(pluginPath));
Utilities.Log($"VmailAttachmentsPlugin.OnAfterLoad: Successfully loaded {_db.Database.Count} attachments from database at {pluginPath}!", (LogLevel)16);
}
catch (Exception ex)
{
Exception e = ex;
_db = new AttachmentDatabase();
Utilities.Log("VmailAttachmentsPlugin.OnAfterLoad: " + e.Message, (LogLevel)2);
}
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "VmailAttachments";
public const string PLUGIN_NAME = "VmailAttachments";
public const string PLUGIN_VERSION = "1.0.0";
}
}