using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Text; using System.Xml.Linq; using BepInEx; using BepInEx.Configuration; using Coroner; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("CoronerCustomMessages")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("CoronerCustomMessages")] [assembly: AssemblyTitle("CoronerCustomMessages")] [assembly: AssemblyVersion("1.0.0.0")] [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 CoronerCustomMessages { [BepInPlugin("dowompi.coronercustommessages", "Coroner Custom Messages", "1.2.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "dowompi.coronercustommessages"; public const string PluginName = "Coroner Custom Messages"; public const string PluginVersion = "1.2.0"; private const string LanguageCode = "en-us"; private const string OutputFileName = "Strings_en-us_custom.xml"; private const string DiscoveryReportFileName = "dowompi.coronercustommessages.discovered-tags.txt"; private const string Separator = "||"; private ConfigEntry pluginEnabled; private readonly Dictionary> messageEntries = new Dictionary>(StringComparer.Ordinal); private readonly Dictionary defaultMessages = new Dictionary(StringComparer.Ordinal) { ["DeathEnemyBracken"] = "Was folded into a portable shape by a Bracken.||Learned too late that the Bracken wanted privacy.", ["DeathEnemyCoilHead"] = "Lost a staring contest with a Coil-Head.||Blinking was the last mistake they made.", ["DeathEnemyJester"] = "Stayed for the punchline. There was no survival after it.||Heard the music and still did not leave.", ["DeathOtherLandmine"] = "Conducted an unscheduled landmine inspection.||Proved the mine was active.", ["DeathPlayerJetpackBlast"] = "Turned the jetpack into a very brief career.||Misunderstood which end of the jetpack was the dangerous one.", ["DeathPlayerCruiserRanOver"] = "Became a speed bump for company transport.||Lost an argument with several tons of cruiser.", ["DeathOtherSpikeTrap"] = "Tested the spike trap so the team would not have to.||Found the trap the fast way.", ["DeathUnknown"] = "Died under unclear but probably embarrassing circumstances." }; private List discoveredTags = new List(); private void Awake() { BindGeneralConfig(); } private void Start() { DiscoverAndBindMessageConfig(); WriteLanguageFile(); WriteDiscoveryReport(); ReloadCoronerLanguage(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Coroner Custom Messages loaded."); } private void BindGeneralConfig() { pluginEnabled = ((BaseUnityPlugin)this).Config.Bind("General", "Enabled", true, "Enable writing the custom Coroner language file."); } private void DiscoverAndBindMessageConfig() { messageEntries.Clear(); discoveredTags = AdvancedCauseOfDeath.Registry.Keys.Where(IsDeathTag).OrderBy((string tag) => tag, StringComparer.Ordinal).ToList(); foreach (string discoveredTag in discoveredTags) { string defaultValue = (defaultMessages.ContainsKey(discoveredTag) ? defaultMessages[discoveredTag] : string.Empty); messageEntries[discoveredTag] = BindMessageList(discoveredTag, defaultValue); } ((BaseUnityPlugin)this).Config.Save(); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Discovered {discoveredTags.Count} Coroner death tags and created config entries for them."); } private ConfigEntry BindMessageList(string tag, string defaultValue) { return ((BaseUnityPlugin)this).Config.Bind("Messages", tag, defaultValue, "Messages for " + tag + ". Separate multiple variants with '||'. This entry was created from Coroner's registered death tags."); } private void WriteLanguageFile() { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Expected O, but got Unknown //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Expected O, but got Unknown //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Expected O, but got Unknown //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Expected O, but got Unknown //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Expected O, but got Unknown //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Expected O, but got Unknown //IL_0158: Expected O, but got Unknown //IL_0153: Unknown result type (might be due to invalid IL or missing references) string text = Path.Combine(Paths.ConfigPath, "EliteMasterEric-Coroner"); Directory.CreateDirectory(text); string text2 = Path.Combine(text, "Strings_en-us_custom.xml"); if (!pluginEnabled.Value) { if (File.Exists(text2)) { File.Delete(text2); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Deleted Strings_en-us_custom.xml because the plugin is disabled."); } return; } KeyValuePair[] source = (from entry in messageEntries.OrderBy>, string>((KeyValuePair> entry) => entry.Key, StringComparer.Ordinal) select CreateEntry(entry.Key, entry.Value.Value)).ToArray(); new XDocument(new XDeclaration("1.0", "utf-8", (string)null), new object[1] { (object)new XElement(XName.op_Implicit("base"), new object[3] { (object)new XAttribute(XName.op_Implicit("type"), (object)"string"), (object)new XElement(XName.op_Implicit("tags"), (object)new XElement(XName.op_Implicit("tag"), (object)new XAttribute(XName.op_Implicit("language"), (object)"en-us"))), (object)new XElement(XName.op_Implicit("strings"), (object)source.SelectMany(BuildElementsForEntry)) }) }).Save(text2); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Wrote " + text2)); } private void WriteDiscoveryReport() { List list = new List { "Coroner Custom Messages discovery report", $"Generated: {DateTime.Now:yyyy-MM-dd HH:mm:ss}", $"Discovered tags: {discoveredTags.Count}", string.Empty, "These are Coroner death tags that were registered when the game loaded.", "This does not guarantee a separate source mod per tag; it only shows what Coroner exposed to this plugin.", string.Empty }; foreach (string discoveredTag in discoveredTags) { int num = SplitMessages(messageEntries.ContainsKey(discoveredTag) ? messageEntries[discoveredTag].Value : string.Empty).Count(); list.Add($"{discoveredTag} | variants={num}"); } string text = Path.Combine(Paths.ConfigPath, "dowompi.coronercustommessages.discovered-tags.txt"); File.WriteAllLines(text, list, Encoding.UTF8); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Wrote discovery report to " + text)); } private static KeyValuePair CreateEntry(string tag, string rawValue) { return new KeyValuePair(tag, rawValue ?? string.Empty); } private static IEnumerable BuildElementsForEntry(KeyValuePair entry) { foreach (string item in SplitMessages(entry.Value)) { yield return new XElement(XName.op_Implicit(entry.Key), (object)new XAttribute(XName.op_Implicit("text"), (object)item)); } } private static IEnumerable SplitMessages(string rawValue) { return (from message in (rawValue ?? string.Empty).Split(new string[1] { "||" }, StringSplitOptions.None) select message.Trim() into message where !string.IsNullOrWhiteSpace(message) select message).Distinct(StringComparer.Ordinal); } private static bool IsDeathTag(string tag) { if (!string.IsNullOrWhiteSpace(tag)) { return tag.StartsWith("Death", StringComparison.Ordinal); } return false; } private void ReloadCoronerLanguage() { try { if ((Object)(object)Plugin.Instance == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Coroner instance was not available; custom messages will apply next launch."); return; } Plugin.Instance.LoadLanguageHandlers(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Reloaded Coroner language handlers."); } catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException || ex is SecurityException) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Failed to reload Coroner language handlers: {ex}"); } } } }