public void ThreadSafeLogger_SaveMultiThreadLog()
        {
            var messages = new List <string>();

            var logger = new LambdaLogger(m => { messages.Add(m.Message); });

            var saveLogger = new ThreadSafeLogger(logger);

            var task1 = Task.Run(() =>
            {
                Enumerable.Range(1, 1500).Each(x =>
                {
                    saveLogger.Log(new LogRecord {
                        Message = "1"
                    });
                });
            });
            var task2 = Task.Run(() =>
            {
                Enumerable.Range(1, 1500).Each(x =>
                {
                    saveLogger.Log(new LogRecord {
                        Message = "2"
                    });
                });
            });

            Task.WaitAll(task1, task2);

            Assert.AreEqual(3000, messages.Count);
            Assert.AreEqual(messages.Count(x => x == "1"), messages.Count(x => x == "2"));
        }
        public override void OnGameLoaded(Game g, Harmony h)
        {
            var factionManger = g.World.factionManager;

            foreach (var fac in factionManger.allFactions.Where(f => f.def == null))
            {
                fac.def = FactionDef.Named("OutlanderCivil");
            }

            foreach (var wo in g.World.worldObjects.worldObjects.Where(w => w.factionInt.def == null))
            {
                var faction = factionManger.allFactions.Where(f => !f.IsPlayer && (!f.hidden ?? true)).RandomElement();

                ThreadSafeLogger.Warning($"[Analyzer] Changed the world object {wo.Label}'s faction from {wo.factionInt.name}(Removed) to {faction.name}");
                wo.factionInt = faction;
            }

            foreach (var wp in g.World.worldPawns.AllPawnsAliveOrDead.Where(p => p.factionInt.def == null))
            {
                var faction = factionManger.allFactions.Where(f => !f.IsPlayer && (!f.hidden ?? true)).RandomElement();

                ThreadSafeLogger.Warning($"[Analyzer] Changed the pawn {wp.Label}'s faction from {wp.factionInt.name}(Removed) to {faction.name}");
                wp.factionInt = faction;
            }

            Active = false;
        }
Beispiel #3
0
        public Modbase(ModContentPack content) : base(content)
        {
            Settings = GetSettings <Settings>();

            ThreadSafeLogger.Message($"[Analyzer] Loaded version {analyzerVersion.Major}.{analyzerVersion.Minor}.{analyzerVersion.Build} rev {analyzerVersion.Revision}");


            { // Profiling
                ModInfoCache.PopulateCache(Content.Name);

                GUIController.InitialiseTabs();

                // GUI needs to be initialised before xml (the tabs need to exist for entries to be inserted into them)
                XmlParser.CollectXmlData();
            }

            { // Always Running
                StaticHarmony.Patch(AccessTools.Method(typeof(GlobalControlsUtility), nameof(GlobalControlsUtility.DoTimespeedControls)),
                                    prefix: new HarmonyMethod(typeof(GUIElement_TPS), nameof(GUIElement_TPS.Prefix)));
            }

            { // Performance Patches
                PerformancePatches.InitialisePatches();
            }

#if DEBUG
            ThreadSafeLogger.Warning("==========================================================================");
            ThreadSafeLogger.Warning("                          Analyzer Running In Debug Mode                  ");
            ThreadSafeLogger.Warning("==========================================================================");
#endif
        }
Beispiel #4
0
        public static void OnGUI()
        {
            if (restartkey.KeyDownEvent)
            {
                GenCommandLine.Restart();
            }

            try
            {
                if (key != null && key.KeyDownEvent)
                {
                    if (Find.WindowStack.WindowOfType <Window_Analyzer>() != null)
                    {
                        Find.WindowStack.RemoveWindowsOfType(typeof(Window_Analyzer));
                    }
                    else
                    {
                        Find.WindowStack.Add(new Window_Analyzer());
                    }
                }
            }
            catch (Exception e)
            {
                ThreadSafeLogger.Error(e.ToString());
            }

            if (alertKey.KeyDownEvent)
            {
                H_AlertsReadoutUpdate.DisableAlerts = !H_AlertsReadoutUpdate.DisableAlerts;
            }
        }
Beispiel #5
0
        public static bool CheckAddOrRemoveAlert(AlertsReadout __instance, Alert alert, bool forceRemove)
        {
            if (DisableAlerts)
            {
                return(false);
            }
            if (!OverrideAlerts)
            {
                return(true);
            }

            try
            {
                var alertActive = false;
                var alertType   = alert.GetType();

                if (AlertFilter.TryGetValue(alertType, out var active))
                {
                    if (!active)
                    {
                        alert.Recalculate();
                        alertActive = alert.Active;
                    }
                    else // We ensure alerts show up so you can re-enable disabled alerts.
                    {
                        if (AlertRecalculate.Active)
                        {
                            var prof = ProfileController.Start(alertType.Name, () => alertType.FullName, alertType, AlertRecalculate.recalculate);

                            prof?.Stop();
                        }
                    }
                }
                else
                {
                    alert.Recalculate();
                    alertActive = alert.Active;
                }

                if (!forceRemove && alertActive)
                {
                    if (!__instance.activeAlerts.Contains(alert))
                    {
                        __instance.activeAlerts.Add(alert);
                        alert.Notify_Started();
                    }
                }
                else
                {
                    __instance.activeAlerts.Remove(alert);
                }
            }
            catch (Exception e)
            {
                ThreadSafeLogger.ReportExceptionOnce(e, $"Exception processing alert {alert}", alert.GetHashCode());
                __instance.activeAlerts.Remove(alert);
            }

            return(false);
        }
Beispiel #6
0
 public void Initialise(Type subType)
 {
     EnabledRefAccess = AccessTools.StaticFieldRefAccess <bool>(subType.GetField("Active", BindingFlags.Public | BindingFlags.Static));
     if (EnabledRefAccess == null)
     {
         ThreadSafeLogger.Error("Add an 'Active' field you bloody muppet");
     }
 }
Beispiel #7
0
 //Thread safe
 public static ThreadSafeLogger GetInstance()
 {
     lock (obj)
     {
         if (logger == null)
         {
             logger = new ThreadSafeLogger();
         }
     }
     return(logger);
 }
Beispiel #8
0
        public static bool Load(UnityModManager.ModEntry modEntry)
        {
            var harmony = HarmonyInstance.Create(modEntry.Info.Id);

            harmony.PatchAll(Assembly.GetExecutingAssembly());
            Logger             = new ThreadSafeLogger(modEntry.Logger);
            settings           = UnityModManager.ModSettings.Load <Settings>(modEntry);
            modEntry.OnToggle  = OnToggle;
            modEntry.OnGUI     = OnGUI;
            modEntry.OnSaveGUI = OnSaveGUI;

            return(true);
        }
Beispiel #9
0
        public override void PreOpen()
        {
            if (Analyzer.CurrentlyCleaningUp)
            {
                Find.WindowStack.TryRemove(this);
                ThreadSafeLogger.Error("[Analyzer] Analyzer is currently in the process of cleaning up - This is unlikely to happen, and shouldn't take long. please attempt to re-open the window in a couple seconds");
                return;
            }

            base.PreOpen();

            if (firstOpen)             // If we have not been opened yet, load all our entries
            {
                LoadEntries();
                firstOpen = false;
            }

            Analyzer.BeginProfiling();

            if (Modbase.isPatched)
            {
                return;
            }


            Modbase.Harmony.Patch(AccessTools.Method(typeof(Root_Play), nameof(Root_Play.Update)),
                                  prefix: new HarmonyMethod(typeof(H_RootUpdate), nameof(H_RootUpdate.Prefix)),
                                  postfix: new HarmonyMethod(typeof(H_RootUpdate), nameof(H_RootUpdate.Postfix)));

            Modbase.Harmony.Patch(AccessTools.Method(typeof(TickManager), nameof(TickManager.DoSingleTick)),
#if DEBUG
                                  prefix: new HarmonyMethod(typeof(H_DoSingleTickUpdate), nameof(H_DoSingleTickUpdate.Prefix)),
#endif
                                  postfix: new HarmonyMethod(typeof(H_DoSingleTickUpdate), nameof(H_DoSingleTickUpdate.Postfix)));

            Modbase.isPatched = true;

            if (Settings.SavedPatches_Tick == null)
            {
                Settings.SavedPatches_Tick   = new HashSet <string>();
                Settings.SavedPatches_Update = new HashSet <string>();
            }
            foreach (var patch in Settings.SavedPatches_Tick)
            {
                Panel_DevOptions.ExecutePatch(CurrentInput.Method, patch, Category.Tick);
            }
            foreach (var patch in Settings.SavedPatches_Update)
            {
                Panel_DevOptions.ExecutePatch(CurrentInput.Method, patch, Category.Update);
            }
        }
Beispiel #10
0
        public static void LoadEntries()
        {
            List <Type> allEntries = GenTypes.AllTypes.Where(m => m.TryGetAttribute <Entry>(out _)).OrderBy(m => m.TryGetAttribute <Entry>().name).ToList();

            foreach (Type entryType in allEntries)
            {
                try
                {
                    Entry entry = entryType.TryGetAttribute <Entry>();
                    entry.Settings = new Dictionary <FieldInfo, Setting>();

                    foreach (FieldInfo fieldInfo in entryType.GetFields().Where(m => m.TryGetAttribute <Setting>(out _)))
                    {
                        Setting sett = fieldInfo.TryGetAttribute <Setting>();
                        entry.Settings.SetOrAdd(fieldInfo, sett);
                    }

                    entry.onMouseOver = AccessTools.Method(entryType, "MouseOver");
                    entry.onClick     = AccessTools.Method(entryType, "Clicked");
                    entry.onSelect    = AccessTools.Method(entryType, "Selected");
                    entry.checkBox    = AccessTools.Method(entryType, "Checkbox");

                    entry.type = entryType;

                    // Find and append Entry to the correct Tab
                    if (!GUIController.Tab(entry.category).entries.ContainsKey(entry))
                    {
                        GUIController.Tab(entry.category).entries.Add(entry, entryType);
                    }
                }
                catch (Exception e)
                {
                    ThreadSafeLogger.ReportException(e, "Failed to initialise entries");
                }
            }

            // Loop through our static instances and add them to the Correct Tab
            foreach (Entry entry in Entry.entries)
            {
                if (!GUIController.Tab(entry.category).entries.ContainsKey(entry))
                {
                    GUIController.Tab(entry.category).entries.Add(entry, entry.type);
                }
            }

            Panel_Logs.Initialise();
        }
        public void ThreadSafeLogger_OptionsPropagation()
        {
            var verifier        = new MinimumLogLevelVerifier(LogLevel.Debug);
            var oldSaveVerifier = default(ILogLevelVerifier);

            var loggerMock = new Mock <ILogger>()
                             .SetupProperty(x => x.IsEnabled, true)
                             .SetupProperty(x => x.LevelVerifier, verifier);

            var saveLogger = new ThreadSafeLogger(loggerMock.Object);

            oldSaveVerifier          = saveLogger.LevelVerifier;
            saveLogger.LevelVerifier = new MinimumLogLevelVerifier(LogLevel.Error);
            saveLogger.IsEnabled     = false;

            Assert.AreEqual(verifier, oldSaveVerifier);
            Assert.AreNotEqual(oldSaveVerifier, saveLogger.LevelVerifier);
            Assert.IsInstanceOf <MinimumLogLevelVerifier>(saveLogger.LevelVerifier);
            Assert.AreEqual(LogLevel.Error, saveLogger.LevelVerifier.CastTo <MinimumLogLevelVerifier>().MinimumLevel);
            Assert.AreEqual(false, loggerMock.Object.IsEnabled);
        }
        public static void OnGUI()
        {
            try
            {
                if (restartkey.KeyDownEvent)
                {
                    GenCommandLine.Restart();
                }

                if (key != null && key.KeyDownEvent)
                {
                    if (Find.WindowStack.WindowOfType <Window_Analyzer>() != null)
                    {
                        Find.WindowStack.RemoveWindowsOfType(typeof(Window_Analyzer));
                    }
                    else
                    {
                        Find.WindowStack.Add(new Window_Analyzer());
                    }
                }

                if (alertKey.KeyDownEvent)
                {
                    H_AlertsReadoutUpdate.DisableAlerts = !H_AlertsReadoutUpdate.DisableAlerts;
                }
            }
            catch (Exception e)
            {
                if ((attemptedInitialise is false) && AttemptToInitialiseKeys())
                {
                    return;
                }

                if (Settings.verboseLogging)
                {
                    ThreadSafeLogger.ReportException(e, "Error while handling analyzer keybindings");
                }
            }
        }
        public override void GameComponentUpdate()
        {
            // Display our logged messages that we may have recieved from other threads.
            ThreadSafeLogger.DisplayLogs();

            if (TimeTillCleanup == -1)
            {
                return;
            }

            if (Profiling.Analyzer.CurrentlyProfiling)
            {
                TimeTillCleanup = -1;
                return;
            }

            TimeTillCleanup -= Time.deltaTime;
            if (TimeTillCleanup <= 0)
            {
                Profiling.Analyzer.Cleanup();
                TimeTillCleanup = -1;
            }
        }
        public static bool AttemptToInitialiseKeys()
        {
            attemptedInitialise = true;
            try
            {
                key        = KeyBindingDef.Named("DubsOptimizerKey");
                restartkey = KeyBindingDef.Named("DubsOptimizerRestartKey");
                alertKey   = KeyBindingDef.Named("dpa_ToggleAlertBlock");

                var biff  = new HarmonyMethod(typeof(H_KeyPresses).GetMethod(nameof(OnGUI)));
                var skiff = typeof(UIRoot_Entry).GetMethod(nameof(UIRoot_Entry.UIRootOnGUI));
                Modbase.StaticHarmony.Patch(skiff, biff);

                skiff = typeof(UIRoot_Play).GetMethod(nameof(UIRoot_Play.UIRootOnGUI));
                Modbase.StaticHarmony.Patch(skiff, biff);
            }
            catch (Exception e)
            {
                ThreadSafeLogger.ReportException(e, "Failed to load keybindings");
                return(false);
            }

            return(true);
        }
        public Modbase(ModContentPack content) : base(content)
        {
            try
            {
                Settings = GetSettings <Settings>();

                ThreadSafeLogger.Message($"[Analyzer] Loaded version {analyzerVersion.Major}.{analyzerVersion.Minor}.{analyzerVersion.Build} rev {analyzerVersion.Revision}");

                staticHarmony = new Harmony("Dubwise.PerformanceAnalyzer");
                harmony       = new Harmony("Dubwise.DubsProfiler");;

                if (ModLister.HasActiveModWithName("Visual Exceptions"))
                {
                    var type  = AccessTools.TypeByName("VisualExceptions.ExceptionState");
                    var field = AccessTools.Field(type, "configuration");
                    type = AccessTools.TypeByName("VisualExceptions.Configuration");
                    var property = AccessTools.PropertyGetter(type, "Debugging");

                    visualExceptionIntegration = (bool)property.Invoke(field.GetValue(null), null);

                    var str = "Detected Visual Exceptions - " + (visualExceptionIntegration ? "Integrating" : "Is disabled, relying on inbuilt functionality");
                    ThreadSafeLogger.Message(str);
                }

                if (visualExceptionIntegration is false)
                {
                    // For registering harmony patches
                    StaticHarmony.Patch(AccessTools.Constructor(typeof(Harmony), new[] { typeof(string) }),
                                        new HarmonyMethod(typeof(RememberHarmonyIDs), nameof(RememberHarmonyIDs.Prefix)));

                    if (ModLister.HasActiveModWithName("HugsLib"))
                    {
                        StaticHarmony.Patch(AccessTools.Method("HugsLib.ModBase:ApplyHarmonyPatches"),
                                            transpiler: new HarmonyMethod(typeof(RememberHarmonyIDs), nameof(RememberHarmonyIDs.Transpiler)));
                    }
                }

                {
                    // Profiling
                    ModInfoCache.PopulateCache(Content.Name);

                    GUIController.InitialiseTabs();

                    // GUI needs to be initialised before xml (the tabs need to exist for entries to be inserted into them)
                    XmlParser.CollectXmlData();

                    StackTraceUtility.Initialise();
                }

                {
                    // Always Running
                    StaticHarmony.Patch(
                        AccessTools.Method(typeof(GlobalControlsUtility),
                                           nameof(GlobalControlsUtility.DoTimespeedControls)),
                        prefix: new HarmonyMethod(typeof(GUIElement_TPS), nameof(GUIElement_TPS.Prefix)));

                    var logError = AccessTools.Method(typeof(Log), nameof(Log.Error), new Type[] { typeof(string) });

                    StaticHarmony.Patch(logError,
                                        prefix: new HarmonyMethod(typeof(DebugLogenabler), nameof(DebugLogenabler.ErrorPrefix)),
                                        new HarmonyMethod(typeof(DebugLogenabler), nameof(DebugLogenabler.ErrorPostfix)));
                    StaticHarmony.Patch(AccessTools.Method(typeof(Prefs), "get_DevMode"),
                                        prefix: new HarmonyMethod(typeof(DebugLogenabler), nameof(DebugLogenabler.DevModePrefix)));
                    StaticHarmony.Patch(AccessTools.Method(typeof(DebugWindowsOpener), "DevToolStarterOnGUI"),
                                        prefix: new HarmonyMethod(typeof(DebugLogenabler), nameof(DebugLogenabler.DebugKeysPatch)));
                }

                {
                    // Performance Patches
                    PerformancePatches.InitialisePatches();
                }

#if DEBUG
                ThreadSafeLogger.Warning("==========================================================================");
                ThreadSafeLogger.Warning("                          Analyzer Running In Debug Mode                  ");
                ThreadSafeLogger.Warning("==========================================================================");
#endif
            }
            catch (Exception e)
            {
                ThreadSafeLogger.ReportException(e, "Failed to initialise analyzer, dumping messages to debug log");
            }
            finally
            {
                ThreadSafeLogger.DisplayLogs();
            }
        }