// 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); }
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)); }
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)); }
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)); }
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; }
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)); }
/** * 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); }
// 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); }
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; }
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"); }