// Entry with controller state Validated or in a running state after a game load
        // Exit with InitializationError (false) on error
        // Ok (true) if ready for game play
        // Hybernating (true) if system is ok and no frame updates are required
        public override bool                Initialize()
        {
            // Default class method for sub-classes which don't require initialization
            var errors        = false;
            var stringBuilder = new StringBuilder();

            CCL_Log.CaptureBegin(stringBuilder);

            var miniMapDefs = DefDatabase <MiniMap.MiniMapDef> .AllDefsListForReading;

            foreach (var miniMapDef in miniMapDefs)
            {
                var miniMapWorker = (MiniMap.MiniMap)Activator.CreateInstance(miniMapDef.miniMapClass, new System.Object[] { miniMapDef });
                if (miniMapWorker == null)
                {
                    CCL_Log.Trace(
                        Verbosity.NonFatalErrors,
                        string.Format("Unable to create instance of '{0}' for '{1}'", miniMapDef.miniMapClass.Name, miniMapDef.defName)
                        );
                    errors = true;
                }
                else
                {
                    Controller.Data.MiniMaps.Add(miniMapWorker);
                }
            }

            CCL_Log.CaptureEnd(stringBuilder, !errors ? "Initialized" : "Errors during intialization");
            strReturn = stringBuilder.ToString();

            State = errors ? SubControllerState.InitializationError : SubControllerState.Ok;
            return(!errors);
        }
        public override bool                Update()
        {
            var stringBuilder = new StringBuilder();

            CCL_Log.CaptureBegin(stringBuilder);

            foreach (var injector in updateInjectors)
            {
                // Inject the group into the system
                if (!Inject(injector))
                {
                    CCL_Log.CaptureEnd(stringBuilder, "Errors during injection");
                    strReturn = stringBuilder.ToString();
                    State     = SubControllerState.InitializationError;
                    return(false);
                }
#if DEBUG
                CCL_Log.Trace(
                    Verbosity.Injections,
                    injector.InjectString
                    );
#endif
            }

            // Post-load injections complete, stop calling this
            CCL_Log.CaptureEnd(stringBuilder, "Updated");
            strReturn = stringBuilder.ToString();
            State     = SubControllerState.Hybernating;
            return(true);
        }
        public override bool                Initialize()
        {
            LongEventHandler.SetCurrentEventText("LibraryInjection".Translate());

            var stringBuilder = new StringBuilder();

            CCL_Log.CaptureBegin(stringBuilder);

            // Initialize preload-MCMs
            if (!MCMHost.InitializeHosts(true))
            {
                CCL_Log.CaptureEnd(stringBuilder, "Errors initializing Mod Configuration Menus");
                strReturn = stringBuilder.ToString();
                State     = SubControllerState.InitializationError;
                return(false);
            }

            foreach (var injector in initInjectors)
            {
                // Inject the group into the system
                if (!Inject(injector))
                {
                    CCL_Log.CaptureEnd(stringBuilder, "Errors during injection");
                    strReturn = stringBuilder.ToString();
                    State     = SubControllerState.InitializationError;
                    return(false);
                }
#if DEBUG
                CCL_Log.Trace(
                    Verbosity.Injections,
                    injector.InjectString
                    );
#endif
            }

            MHD_Facilities.ReResolveDefs();

            // Everything's ok for updates
            CCL_Log.CaptureEnd(
                stringBuilder,
                "Initialized"
                );
            strReturn = stringBuilder.ToString();
            State     = SubControllerState.Ok;

            LongEventHandler.SetCurrentEventText("Initializing".Translate());

            return(true);
        }
Exemple #4
0
 internal static List <IntVec3> RadialPatternMiddleOutward()
 {
     if (_RadialPatternMiddleOutward == null)
     {
         _RadialPatternMiddleOutward = typeof(JoyGiver_SocialRelax).GetField("RadialPatternMiddleOutward", BindingFlags.Static | BindingFlags.NonPublic);
         if (_RadialPatternMiddleOutward == null)
         {
             CCL_Log.Trace(
                 Verbosity.FatalErrors,
                 "Unable to get field 'RadialPatternMiddleOutwards' in 'JoyGiver_SocialRelax'",
                 "Internal Detours");
         }
     }
     return((List <IntVec3>)_RadialPatternMiddleOutward.GetValue(null));
 }
Exemple #5
0
 internal static int NumRadiusCells()
 {
     if (_NumRadiusCells == null)
     {
         _NumRadiusCells = typeof(JoyGiver_SocialRelax).GetField("NumRadiusCells", BindingFlags.Static | BindingFlags.NonPublic);
         if (_NumRadiusCells == null)
         {
             CCL_Log.Trace(
                 Verbosity.FatalErrors,
                 "Unable to get field 'NumRadiusCells' in 'JoyGiver_SocialRelax'",
                 "Internal Detours");
         }
     }
     return((int)_NumRadiusCells.GetValue(null));
 }
Exemple #6
0
 internal static List <CompGatherSpot> workingSpots()
 {
     if (_workingSpots == null)
     {
         _workingSpots = typeof(JoyGiver_SocialRelax).GetField("workingSpots", BindingFlags.Static | BindingFlags.NonPublic);
         if (_workingSpots == null)
         {
             CCL_Log.Trace(
                 Verbosity.FatalErrors,
                 "Unable to get field 'workingSpots' in 'JoyGiver_SocialRelax'",
                 "Internal Detours");
         }
     }
     return((List <CompGatherSpot>)_workingSpots.GetValue(null));
 }
Exemple #7
0
        public MiniMap(MiniMapDef miniMapDef)
        {
            this.miniMapDef = miniMapDef;
            this._hidden    = this.miniMapDef.hiddenByDefault;

            overlayWorkers = new List <MiniMapOverlay>();

            for (int index = 0; index < this.miniMapDef.overlays.Count; ++index)
            {
                var overlayData = this.miniMapDef.overlays[index];
                if (
                    (overlayData.overlayClass == null) ||
                    (
                        (overlayData.overlayClass != typeof(MiniMapOverlay)) &&
                        (!overlayData.overlayClass.IsSubclassOf(typeof(MiniMapOverlay)))
                    )
                    )
                {
                    CCL_Log.Trace(
                        Verbosity.NonFatalErrors,
                        string.Format("Unable to resolve overlayClass for '{0}' at index {1} to 'CommunityCoreLibrary.MiniMapOverlay'", miniMapDef.defName, index)
                        );
                    return;
                }
                else
                {
                    var overlayWorker = (MiniMapOverlay)Activator.CreateInstance(overlayData.overlayClass, new System.Object[] { this, overlayData });
                    if (overlayWorker == null)
                    {
                        CCL_Log.Trace(
                            Verbosity.NonFatalErrors,
                            string.Format("Unable to create instance of '{0}' for '{1}'", overlayData.overlayClass.Name, miniMapDef.defName)
                            );
                        return;
                    }
                    else
                    {
                        overlayWorkers.Add(overlayWorker);
                        CCL_Log.Trace(
                            Verbosity.Injections,
                            string.Format("Added overlay '{0}' to '{1}' at draw position {2}", overlayData.overlayClass.Name, this.miniMapDef.defName, (this.miniMapDef.drawOrder + overlayData.drawOffset))
                            );
                    }
                }
            }

            dirty = true;
        }
Exemple #8
0
 internal static Pawn_DrawTracker GetPawnDrawTracker(this Pawn pawn)
 {
     if (_GetPawnDrawTracker == null)
     {
         _GetPawnDrawTracker = typeof(Pawn).GetField("drawer", BindingFlags.Instance | BindingFlags.NonPublic);
         if (_GetPawnDrawTracker == null)
         {
             CCL_Log.Trace(
                 Verbosity.FatalErrors,
                 "Unable to get 'drawer' in class 'Pawn'",
                 "CommunityCoreLibrary.Detour.JobDriver_SocialRelax");
             return(null);
         }
     }
     return((Pawn_DrawTracker)_GetPawnDrawTracker.GetValue(pawn));
 }
Exemple #9
0
        /**
         *  This is a basic first implementation of the IL method 'hooks' (detours) made possible by RawCode's work;
         *  https://ludeon.com/forums/index.php?topic=17143.0
         *
         *  Performs detours, spits out basic logs and warns if a method is detoured multiple times.
         **/
        public static unsafe bool TryDetourFromTo(MethodInfo source, MethodInfo destination)
        {
            // error out on null arguments
            if (source == null)
            {
                Log.Error("Detours - Source MethodInfo is null");
                return(false);
            }

            if (destination == null)
            {
                Log.Error("Detours - Destination MethodInfo is null");
                return(false);
            }

            // keep track of detours and spit out some messaging
            string sourceString      = source.DeclaringType.FullName + "." + source.Name + " @ 0x" + source.MethodHandle.GetFunctionPointer().ToString("X" + (IntPtr.Size * 2).ToString());
            string destinationString = destination.DeclaringType.FullName + "." + destination.Name + " @ 0x" + destination.MethodHandle.GetFunctionPointer().ToString("X" + (IntPtr.Size * 2).ToString());

#if DEBUG
            if (detoured.Contains(sourceString))
            {
                CCL_Log.Trace(Verbosity.Warnings,
                              "Source method ('" + sourceString + "') is previously detoured to '" + destinations[detoured.IndexOf(sourceString)] + "'",
                              "Detours"
                              );
            }
            CCL_Log.Trace(Verbosity.Injections,
                          "Detouring '" + sourceString + "' to '" + destinationString + "'",
                          "Detours"
                          );
#endif

            detoured.Add(sourceString);
            destinations.Add(destinationString);

            if (IntPtr.Size == sizeof(Int64))
            {
                // 64-bit systems use 64-bit absolute address and jumps
                // 12 byte destructive

                // Get function pointers
                long Source_Base      = source.MethodHandle.GetFunctionPointer().ToInt64();
                long Destination_Base = destination.MethodHandle.GetFunctionPointer().ToInt64();

                // Native source address
                byte *Pointer_Raw_Source = (byte *)Source_Base;

                // Pointer to insert jump address into native code
                long *Pointer_Raw_Address = (long *)(Pointer_Raw_Source + 0x02);

                // Insert 64-bit absolute jump into native code (address in rax)
                // mov rax, immediate64
                // jmp [rax]
                *(Pointer_Raw_Source + 0x00) = 0x48;
                *(Pointer_Raw_Source + 0x01) = 0xB8;
                *Pointer_Raw_Address = Destination_Base;           // ( Pointer_Raw_Source + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 )
                *(Pointer_Raw_Source + 0x0A) = 0xFF;
                *(Pointer_Raw_Source + 0x0B) = 0xE0;
            }
            else
            {
                // 32-bit systems use 32-bit relative offset and jump
                // 5 byte destructive

                // Get function pointers
                int Source_Base      = source.MethodHandle.GetFunctionPointer().ToInt32();
                int Destination_Base = destination.MethodHandle.GetFunctionPointer().ToInt32();

                // Native source address
                byte *Pointer_Raw_Source = (byte *)Source_Base;

                // Pointer to insert jump address into native code
                int *Pointer_Raw_Address = (int *)(Pointer_Raw_Source + 1);

                // Jump offset (less instruction size)
                int offset = (Destination_Base - Source_Base) - 5;

                // Insert 32-bit relative jump into native code
                *Pointer_Raw_Source  = 0xE9;
                *Pointer_Raw_Address = offset;
            }

            // done!
            return(true);
        }
        // Entry with controller state Uninitialized
        // Exit with ValidationError (false) on error
        // Validated (true) if ready for initialization
        public override bool                Validate()
        {
            var errors        = false;
            var stringBuilder = new StringBuilder();

            CCL_Log.CaptureBegin(stringBuilder);

            var miniMapDefs = DefDatabase <MiniMap.MiniMapDef> .AllDefsListForReading;

            foreach (var miniMapDef in miniMapDefs)
            {
                if (
                    (miniMapDef.miniMapClass == null) ||
                    (
                        (miniMapDef.miniMapClass != typeof(MiniMap.MiniMap)) &&
                        (!miniMapDef.miniMapClass.IsSubclassOf(typeof(MiniMap.MiniMap)))
                    )
                    )
                {
                    CCL_Log.Trace(
                        Verbosity.NonFatalErrors,
                        string.Format("Unable to resolve miniMapClass for '{0}' to 'CommunityCoreLibrary.MiniMap'", miniMapDef.defName)
                        );
                    errors = true;
                }
                else
                {
                    // Make sure the minimap def has a list of overlay defs
                    if (miniMapDef.overlays == null)
                    {
                        miniMapDef.overlays = new List <MiniMap.MiniMapOverlayDef>();
                    }
                    // Fetch any overlays which may want to add-in
                    var overlayDefs =
                        DefDatabase <MiniMap.MiniMapOverlayDef>
                        .AllDefs
                        .Where(overlayDef => (
                                   (overlayDef.miniMapDef != null) &&
                                   (overlayDef.miniMapDef == miniMapDef)
                                   ));

                    if (overlayDefs.Count() > 0)
                    {   // Add-in the overlay defs
                        foreach (var overlayDef in overlayDefs)
                        {
                            miniMapDef.overlays.AddUnique(overlayDef);
                        }
                    }
                    if (miniMapDef.overlays.NullOrEmpty() && !miniMapDef.dynamicOverlays)
                    {
                        CCL_Log.Trace(
                            Verbosity.NonFatalErrors,
                            string.Format("MiniMap '{0}' has no overlays", miniMapDef.defName)
                            );
                        errors = true;
                    }
                }
            }

            CCL_Log.CaptureEnd(stringBuilder, !errors ? "Validated" : "Errors during validation");
            strReturn = stringBuilder.ToString();

            State = errors ? SubControllerState.ValidationError : SubControllerState.Validated;
            return(!errors);
        }
Exemple #11
0
        // Validate ...research...?
        public override bool                Validate()
        {
            // Hopefully...
            var stringBuilder = new StringBuilder();
            var rVal          = true;

            CCL_Log.CaptureBegin(stringBuilder);

            var AdvancedResearchDefs = Controller.Data.AdvancedResearchDefs;

            // Make sure the hidden research exists
            if (CommunityCoreLibrary.Research.Locker == null)
            {
                CCL_Log.Trace(Verbosity.FatalErrors, "Missing research locker!");
                rVal = false;
            }

            // Validate each advanced research def
            for (int index = AdvancedResearchDefs.Count - 1; index >= 0; index--)
            {
                var advancedResearchDef = AdvancedResearchDefs[index];

                if (!advancedResearchDef.IsValid())
                {
                    // Remove projects with errors from list of usable projects
                    AdvancedResearchDefs.Remove(advancedResearchDef);
                    rVal = false;
                    continue;
                }

                if (advancedResearchDef.IsLockedOut())
                {
                    // Remove locked out projects
                    CCL_Log.TraceMod(
                        advancedResearchDef,
                        Verbosity.Warnings,
                        "Def is locked out by one or more research prerequisites");
                    AdvancedResearchDefs.Remove(advancedResearchDef);
                    continue;
                }
            }

#if DEBUG
            if (rVal == true)
            {
                var allMods = Controller.Data.Mods;
                foreach (var mod in allMods)
                {
                    if (!Find_Extensions.DefListOfTypeForMod <AdvancedResearchDef>(mod).NullOrEmpty())
                    {
                        CCL_Log.TraceMod(
                            mod,
                            Verbosity.Validation,
                            "Passed validation"
                            );
                    }
                }
            }
#endif

            // Should be empty or a laundry list
            CCL_Log.CaptureEnd(
                stringBuilder,
                rVal ? "Validated" : "Errors during validation"
                );
            strReturn = stringBuilder.ToString();

            // Return true if all mods OK, false if any failed validation
            State = rVal ? SubControllerState.Validated : SubControllerState.ValidationError;
            return(rVal);
        }
Exemple #12
0
        internal static void                PreLoad()
        {
            // This is a pre-start sequence to hook some deeper level functions.
            // These functions can be hooked later but it would be after the sequence
            // of operations which call them is complete.

#if DEVELOPER
            // Open a log file for CCL specific output
            // https://www.youtube.com/watch?v=jyaLZHiJJnE
            if (CCL_Log.OpenStream() == null)
            {
                Log.Error(string.Format("Unable to open file stream for {0}!", Controller.Data.UnityObjectName));
            }
#endif

            // Log CCL version
            Version.Log();

            bool InjectionsOk  = true;
            var  stringBuilder = new StringBuilder();
            CCL_Log.CaptureBegin(stringBuilder);

            // Find all sub-controllers
            var subControllerClasses = typeof(SubController).AllSubclasses();
            var subControllerCount   = subControllerClasses.Count();
            if (subControllerCount == 0)
            {
                InjectionsOk = false;
                CCL_Log.Error(
                    "Unable to find sub-controllers",
                    "PreLoader"
                    );
            }

            // Create sub-controllers
            if (InjectionsOk)
            {
                var subControllers = new SubController[subControllerCount];
                for (int index = 0; index < subControllerCount; ++index)
                {
                    var subControllerType = subControllerClasses.ElementAt(index);
                    var subController     = (SubController)Activator.CreateInstance(subControllerType);
                    if (subController == null)
                    {
                        CCL_Log.Error(
                            string.Format("Unable to create sub-controller {0}", subControllerType.Name),
                            "PreLoader"
                            );
                        InjectionsOk = false;
                        break;
                    }
                    else
                    {
                        subControllers[index] = subController;
                    }
                }
                if (InjectionsOk)
                {
                    Controller.Data.SubControllers = subControllers;
                }
            }

            // Detour Verse.PlayDataLoader.LoadAllPlayData
            if (InjectionsOk)
            {
                MethodInfo Verse_PlayDataLoader_LoadAllPlayData = typeof(PlayDataLoader).GetMethod("LoadAllPlayData", BindingFlags.Static | BindingFlags.Public);
                MethodInfo CCL_PlayDataLoader_LoadAllPlayData   = typeof(Detour._PlayDataLoader).GetMethod("_LoadAllPlayData", BindingFlags.Static | BindingFlags.NonPublic);
                InjectionsOk &= Detours.TryDetourFromTo(Verse_PlayDataLoader_LoadAllPlayData, CCL_PlayDataLoader_LoadAllPlayData);
            }

            // Detour Verse.PlayDataLoader.ClearAllPlayData
            if (InjectionsOk)
            {
                MethodInfo Verse_PlayDataLoader_ClearAllPlayData = typeof(PlayDataLoader).GetMethod("ClearAllPlayData", BindingFlags.Static | BindingFlags.Public);
                MethodInfo CCL_PlayDataLoader_ClearAllPlayData   = typeof(Detour._PlayDataLoader).GetMethod("_ClearAllPlayData", BindingFlags.Static | BindingFlags.NonPublic);
                InjectionsOk &= Detours.TryDetourFromTo(Verse_PlayDataLoader_ClearAllPlayData, CCL_PlayDataLoader_ClearAllPlayData);
            }

            // Detour Verse.UIRoot_Entry.ShouldDoMainMenu_get
            if (InjectionsOk)
            {
                PropertyInfo Verse_UIRoot_Entry_ShouldDoMainMenu     = typeof(UIRoot_Entry).GetProperty("ShouldDoMainMenu", BindingFlags.Instance | BindingFlags.NonPublic);
                MethodInfo   Verse_UIRoot_Entry_ShouldDoMainMenu_get = Verse_UIRoot_Entry_ShouldDoMainMenu.GetGetMethod(true);
                MethodInfo   CCL_UIRoot_Entry_ShouldDoMainMenu_get   = typeof(Detour._UIRoot_Entry).GetMethod("_ShouldDoMainMenu_get", BindingFlags.Static | BindingFlags.NonPublic);
                InjectionsOk &= Detours.TryDetourFromTo(Verse_UIRoot_Entry_ShouldDoMainMenu_get, CCL_UIRoot_Entry_ShouldDoMainMenu_get);
            }

            // Detour RimWorld.MainMenuDrawer.MainMenuOnGUI
            if (InjectionsOk)
            {
                MethodInfo RimWorld_MainMenuDrawer_MainMenuOnGUI = typeof(MainMenuDrawer).GetMethod("MainMenuOnGUI", BindingFlags.Static | BindingFlags.Public);
                MethodInfo CCL_MainMenuDrawer_MainMenuOnGUI      = typeof(Detour._MainMenuDrawer).GetMethod("_MainMenuOnGUI", BindingFlags.Static | BindingFlags.NonPublic);
                InjectionsOk &= Detours.TryDetourFromTo(RimWorld_MainMenuDrawer_MainMenuOnGUI, CCL_MainMenuDrawer_MainMenuOnGUI);
            }

            // Detour RimWorld.MainMenuDrawer.DoMainMenuButtons
            if (InjectionsOk)
            {
                MethodInfo RimWorld_MainMenuDrawer_DoMainMenuButtons = typeof(MainMenuDrawer).GetMethod("DoMainMenuButtons", BindingFlags.Static | BindingFlags.Public);
                MethodInfo CCL_MainMenuDrawer_DoMainMenuButtons      = typeof(Detour._MainMenuDrawer).GetMethod("_DoMainMenuButtons", BindingFlags.Static | BindingFlags.NonPublic);
                InjectionsOk &= Detours.TryDetourFromTo(RimWorld_MainMenuDrawer_DoMainMenuButtons, CCL_MainMenuDrawer_DoMainMenuButtons);
            }

            // Detour RimWorld.VersionControl.DrawInfoInCorner
            if (InjectionsOk)
            {
                MethodInfo RimWorld_VersionControl_DrawInfoInCorner = typeof(VersionControl).GetMethod("DrawInfoInCorner", BindingFlags.Static | BindingFlags.Public);
                MethodInfo CCL_VersionControl_DrawInfoInCorner      = typeof(Detour._VersionControl).GetMethod("_DrawInfoInCorner", BindingFlags.Static | BindingFlags.NonPublic);
                InjectionsOk &= Detours.TryDetourFromTo(RimWorld_VersionControl_DrawInfoInCorner, CCL_VersionControl_DrawInfoInCorner);
            }

            // Detour Verse.PostLoadInitter.DoAllPostLoadInits

            /*
             * if( InjectionsOk )
             * {
             *  MethodInfo Verse_PostLoadInitter_DoAllPostLoadInits = typeof( PostLoadInitter ).GetMethod( "DoAllPostLoadInits", BindingFlags.Static | BindingFlags.Public );
             *  MethodInfo CCL_PostLoadInitter_DoAllPostLoadInits = typeof( Detour._PostLoadInitter ).GetMethod( "_DoAllPostLoadInits", BindingFlags.Static | BindingFlags.NonPublic );
             *  InjectionsOk &= Detours.TryDetourFromTo( Verse_PostLoadInitter_DoAllPostLoadInits, CCL_PostLoadInitter_DoAllPostLoadInits );
             * }
             */

            if (InjectionsOk)
            {
                LongEventHandler.ExecuteWhenFinished(CreateMonoBehaviour);
            }

            CCL_Log.CaptureEnd(
                stringBuilder,
                InjectionsOk ? "Initialized" : "Errors during injection"
                );
            CCL_Log.Trace(
                Verbosity.Injections,
                stringBuilder.ToString(),
                "PreLoader");

            initOk = InjectionsOk;
        }
Exemple #13
0
        private static void                 PreLoad()
        {
            // This is a pre-start sequence to hook some deeper level functions.
            // These functions can be hooked later but it would be after the sequence
            // of operations which call them is complete.

            // Log CCL version
            Version.Log();

            bool          InjectionsOk  = true;
            StringBuilder stringBuilder = new StringBuilder();

            CCL_Log.CaptureBegin(stringBuilder);

            // Find all sub-controllers
            var subControllerClasses = typeof(SubController).AllSubclasses();
            var subControllerCount   = subControllerClasses.Count();

            if (subControllerCount == 0)
            {
                InjectionsOk = false;
                CCL_Log.Error(
                    "Unable to find sub-controllers",
                    "PreLoader"
                    );
            }

            // Create sub-controllers
            if (InjectionsOk)
            {
                var subControllers = new SubController[subControllerCount];
                for (int index = 0; index < subControllerCount; ++index)
                {
                    var subControllerType = subControllerClasses.ElementAt(index);
                    var subController     = (SubController)Activator.CreateInstance(subControllerType);
                    if (subController == null)
                    {
                        CCL_Log.Error(
                            string.Format("Unable to create sub-controller {0}", subControllerType.Name),
                            "PreLoader"
                            );
                        InjectionsOk = false;
                        break;
                    }
                    else
                    {
                        subControllers[index] = subController;
                    }
                }
                if (InjectionsOk)
                {
                    Controller.Data.SubControllers = subControllers;
                }
            }

            // Detour Verse.PlayDataLoader.LoadAllPlayData
            if (InjectionsOk)
            {
                MethodInfo Verse_PlayDataLoader_LoadAllPlayData = typeof(PlayDataLoader).GetMethod("LoadAllPlayData", BindingFlags.Static | BindingFlags.Public);
                MethodInfo CCL_PlayDataLoader_LoadAllPlayData   = typeof(Detour._PlayDataLoader).GetMethod("_LoadAllPlayData", BindingFlags.Static | BindingFlags.NonPublic);
                InjectionsOk &= Detours.TryDetourFromTo(Verse_PlayDataLoader_LoadAllPlayData, CCL_PlayDataLoader_LoadAllPlayData);
            }

            // Detour Verse.PlayDataLoader.ClearAllPlayData
            if (InjectionsOk)
            {
                MethodInfo Verse_PlayDataLoader_ClearAllPlayData = typeof(PlayDataLoader).GetMethod("ClearAllPlayData", BindingFlags.Static | BindingFlags.Public);
                MethodInfo CCL_PlayDataLoader_ClearAllPlayData   = typeof(Detour._PlayDataLoader).GetMethod("_ClearAllPlayData", BindingFlags.Static | BindingFlags.NonPublic);
                InjectionsOk &= Detours.TryDetourFromTo(Verse_PlayDataLoader_ClearAllPlayData, CCL_PlayDataLoader_ClearAllPlayData);
            }

            // Detour Verse.UIRoot_Entry.ShouldShowMainMenuGUI_get
            if (InjectionsOk)
            {
                PropertyInfo Verse_UIRoot_Entry_ShouldShowMainMenuGUI     = typeof(UIRoot_Entry).GetProperty("ShouldShowMainMenuGUI", BindingFlags.Instance | BindingFlags.NonPublic);
                MethodInfo   Verse_UIRoot_Entry_ShouldShowMainMenuGUI_get = Verse_UIRoot_Entry_ShouldShowMainMenuGUI.GetGetMethod(true);
                MethodInfo   CCL_UIRoot_Entry_ShouldShowMainMenuGUI_get   = typeof(Detour._UIRoot_Entry).GetMethod("_ShouldShowMainMenuGUI_get", BindingFlags.Static | BindingFlags.NonPublic);
                InjectionsOk &= Detours.TryDetourFromTo(Verse_UIRoot_Entry_ShouldShowMainMenuGUI_get, CCL_UIRoot_Entry_ShouldShowMainMenuGUI_get);
            }

            // Detour RimWorld.MainMenuDrawer.MainMenuOnGUI
            if (InjectionsOk)
            {
                MethodInfo RimWorld_MainMenuDrawer_MainMenuOnGUI = typeof(MainMenuDrawer).GetMethod("MainMenuOnGUI", BindingFlags.Static | BindingFlags.Public);
                MethodInfo CCL_MainMenuDrawer_MainMenuOnGUI      = typeof(Detour._MainMenuDrawer).GetMethod("_MainMenuOnGUI", BindingFlags.Static | BindingFlags.NonPublic);
                InjectionsOk &= Detours.TryDetourFromTo(RimWorld_MainMenuDrawer_MainMenuOnGUI, CCL_MainMenuDrawer_MainMenuOnGUI);
            }

            // Detour RimWorld.MainMenuDrawer.DoMainMenuButtons
            if (InjectionsOk)
            {
                MethodInfo RimWorld_MainMenuDrawer_DoMainMenuButtons = typeof(MainMenuDrawer).GetMethod("DoMainMenuButtons", BindingFlags.Static | BindingFlags.Public);
                MethodInfo CCL_MainMenuDrawer_DoMainMenuButtons      = typeof(Detour._MainMenuDrawer).GetMethod("_DoMainMenuButtons", BindingFlags.Static | BindingFlags.NonPublic);
                InjectionsOk &= Detours.TryDetourFromTo(RimWorld_MainMenuDrawer_DoMainMenuButtons, CCL_MainMenuDrawer_DoMainMenuButtons);
            }

            // Detour RimWorld.BiomeDef.CommonalityOfAnimal
            if (InjectionsOk)
            {
                MethodInfo RimwWorld_BiomeDef_CommonalityOfAnimal = typeof(BiomeDef).GetMethod("CommonalityOfAnimal", BindingFlags.Instance | BindingFlags.Public);
                MethodInfo CCL_BiomeDef_CommonalityOfAnimal       = typeof(Detour._BiomeDef).GetMethod("_CommonalityOfAnimal", BindingFlags.Static | BindingFlags.NonPublic);
                InjectionsOk &= Detours.TryDetourFromTo(RimwWorld_BiomeDef_CommonalityOfAnimal, CCL_BiomeDef_CommonalityOfAnimal);
            }

            // Detour RimWorld.BiomeDef.CommonalityOfPlant
            if (InjectionsOk)
            {
                MethodInfo RimwWorld_BiomeDef_CommonalityOfPlant = typeof(BiomeDef).GetMethod("CommonalityOfPlant", BindingFlags.Instance | BindingFlags.Public);
                MethodInfo CCL_BiomeDef_CommonalityOfPlant       = typeof(Detour._BiomeDef).GetMethod("_CommonalityOfPlant", BindingFlags.Static | BindingFlags.NonPublic);
                InjectionsOk &= Detours.TryDetourFromTo(RimwWorld_BiomeDef_CommonalityOfPlant, CCL_BiomeDef_CommonalityOfPlant);
            }
            // Detour RimWorld.BiomeDef.MTBDaysOfDisease
            if (InjectionsOk)
            {
                MethodInfo RimWorld_BiomeDef_MTBDaysOfDisease = typeof(BiomeDef).GetMethod("MTBDaysOfDisease", BindingFlags.Instance | BindingFlags.Public);
                MethodInfo CCL_BiomeDef_MTBDaysOfDisease      = typeof(Detour._BiomeDef).GetMethod("_MTBDaysOfDisease", BindingFlags.Static | BindingFlags.NonPublic);
                InjectionsOk &= Detours.TryDetourFromTo(RimWorld_BiomeDef_MTBDaysOfDisease, CCL_BiomeDef_MTBDaysOfDisease);
            }

            // Detour Verse.PostLoadInitter.DoAllPostLoadInits

            /*
             * if( InjectionsOk )
             * {
             *  MethodInfo Verse_PostLoadInitter_DoAllPostLoadInits = typeof( PostLoadInitter ).GetMethod( "DoAllPostLoadInits", BindingFlags.Static | BindingFlags.Public );
             *  MethodInfo CCL_PostLoadInitter_DoAllPostLoadInits = typeof( Detour._PostLoadInitter ).GetMethod( "_DoAllPostLoadInits", BindingFlags.Static | BindingFlags.NonPublic );
             *  InjectionsOk &= Detours.TryDetourFromTo( Verse_PostLoadInitter_DoAllPostLoadInits, CCL_PostLoadInitter_DoAllPostLoadInits );
             * }
             */

            if (InjectionsOk)
            {
                var gameObject = new GameObject(Controller.Data.UnityObjectName);
                if (gameObject == null)
                {
                    InjectionsOk = false;
                    CCL_Log.Error(
                        "Unable to create GameObject",
                        "PreLoader"
                        );
                }
                else
                {
                    if (gameObject.AddComponent <Controller.MainMonoBehaviour>() == null)
                    {
                        InjectionsOk = false;
                        CCL_Log.Error(
                            "Unable to create MonoBehaviour",
                            "PreLoader"
                            );
                    }
                    else
                    {
                        UnityEngine.Object.DontDestroyOnLoad(gameObject);
                        Controller.Data.UnityObject = gameObject;
                    }
                }
            }

            if (InjectionsOk)
            {
                CCL_Log.Message(
                    "Queueing Library Initialization",
                    "PreLoader"
                    );
                LongEventHandler.QueueLongEvent(Initialize, "LibraryStartup", true, null);
            }

            CCL_Log.CaptureEnd(
                stringBuilder,
                InjectionsOk ? "Initialized" : "Errors during injection"
                );
            CCL_Log.Trace(
                Verbosity.Injections,
                stringBuilder.ToString(),
                "PreLoader");
        }