public static void DrawThing(Texture2D texture, Thing thing, Color color) { #if DEVELOPER CCL_Log.Message("Painting cells for " + thing.LabelCap + thing.Position + color); #endif // check if this makes sense if (texture == null) { CCL_Log.Error("Tried to draw to NULL texture"); return; } if (thing == null) { CCL_Log.Error("Tried to get occupied rect for NULL thing"); return; } if ( (thing.OccupiedRect().Cells == null) || (thing.OccupiedRect().Cells.Count() == 0) ) { CCL_Log.Error("Tried to get occupier rect for " + thing.LabelCap + " but it is NULL or empty"); return; } // paint all cells occupied by thing in 'color'. foreach (var cell in thing.OccupiedRect().Cells) { if (cell.InBounds()) { texture.SetPixel(cell.x, cell.z, color); } } }
// 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 void ReIntialize() { // Call controller Initialize() on game load var subControllers = Controller.Data.SubControllers.ToList(); subControllers.Sort((x, y) => (x.InitializationPriority > y.InitializationPriority) ? -1 : 1); foreach (var subsys in subControllers) { if (subsys.InitializationPriority != SubController.DontProcessThisPhase) { if ( (subsys.State >= SubControllerState._BaseOk) && (subsys.ReinitializeOnGameLoad) ) { if (!subsys.Initialize()) { CCL_Log.Error(subsys.strReturn, subsys.Name + " :: Reinitialization"); gameValid = false; enabled = false; return; } if (subsys.strReturn != string.Empty) { CCL_Log.Message(subsys.strReturn, subsys.Name + " :: Reinitialization"); } } } } ticks = 0; }
public void UpdateSubControllers() { if (UpdateControllers == null) { // Create a list of sub controllers in update order UpdateControllers = Controller.Data.SubControllers.ToList(); UpdateControllers.Sort((x, y) => (x.UpdatePriority > y.UpdatePriority) ? -1 : 1); } foreach (var subsys in UpdateControllers) { if (subsys.UpdatePriority != SubController.DontProcessThisPhase) { if ( (subsys.State == SubControllerState.Ok) && (subsys.IsHashIntervalTick(ticks)) ) { if (!subsys.Update()) { CCL_Log.Error(subsys.strReturn, subsys.Name + " :: Update"); return; } if (subsys.strReturn != string.Empty) { CCL_Log.Message(subsys.strReturn, subsys.Name + " :: Update"); } } } } }
public override bool Initialize() { // Don't auto-gen help if "quicktest" or "nohelp" command line switches are used if ( (!GenCommandLine.CommandLineArgPassed("quicktest")) && (!GenCommandLine.CommandLineArgPassed("nohelp")) ) { LongEventHandler.SetCurrentEventText("LibraryHelpGen".Translate()); var stringBuilder = new StringBuilder(); CCL_Log.CaptureBegin(stringBuilder); var startTime = DateTime.Now; if (!HelpBuilder.ResolveImpliedDefs()) { strReturn = "Unexpected error in HelpBuilder.ResolveImpliedDefs()"; State = SubControllerState.InitializationError; return(false); } var finishTime = DateTime.Now; var finalTime = finishTime - startTime; CCL_Log.CaptureEnd(stringBuilder, string.Format("Completed in {0}", finalTime.ToString())); CCL_Log.Message(stringBuilder.ToString(), "Help System"); LongEventHandler.SetCurrentEventText("Initializing".Translate()); } strReturn = "Initialized"; State = SubControllerState.Hybernating; return(true); }
public static void CreateMonoBehaviour() { var gameObject = new GameObject(Controller.Data.UnityObjectName); if (gameObject == null) { CCL_Log.Error("Unable to create GameObject"); initOk = false; return; } else { if (gameObject.AddComponent <Controller.MainMonoBehaviour>() == null) { CCL_Log.Error("Unable to create MonoBehaviour"); initOk = false; return; } else { UnityEngine.Object.DontDestroyOnLoad(gameObject); Controller.Data.UnityObject = gameObject; } } CCL_Log.Message("Queueing Library Initialization"); LongEventHandler.QueueLongEvent(Initialize, "LibraryStartup", true, null); }
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); }
internal static void DumpThingsRequestedForGroup(ThingRequest thingRequest, List <Thing> thingsRequested) { var str = string.Format("ListerThings.ThingsMatching( {0} ) ::\n", thingRequest); foreach (var thing in thingsRequested) { str += string.Format("\t{0} - {1}\n", thing.ThingID, thing.def.defName); } CCL_Log.Message(str); }
static Data() { Assembly_CSharp = Assembly.Load("Assembly-CSharp.dll"); #if DEBUG if (Assembly_CSharp == null) { CCL_Log.Error("Unable to load 'Assembly-CSharp'"); return; } #endif }
internal static void ResetInjectionSubController() { MHD_PostLoadInjectors.Reset(); var injectionSubController = GetController(typeof(InjectionSubController)); if (injectionSubController == null) { CCL_Log.Error("Unable to get InjectionSubController!"); return; } injectionSubController.State = SubControllerState.Ok; }
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 <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)); }
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 <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)); }
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)); }
private bool OpenWindow() { var window = GetWindow; if (window != null) { return(true); } Window_MiniMap.windowRect = new Rect(Screen.width - windowSize.x, 0f, windowSize.y, windowSize.x); window = new Window_MiniMap(Window_MiniMap.windowRect); if (window == null) { CCL_Log.Error("Unable to create Window_MiniMap", "MiniMap"); return(false); } Find.WindowStack.Add(window); return(true); }
/** * 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); }
// Validate ModHelperDefs, CCL load order, CCL versioning public override bool Validate() { // Hopefully... var stringBuilder = new StringBuilder(); var rVal = true; CCL_Log.CaptureBegin(stringBuilder); // Limit one ModHelperDef per mod // Create the ordered list by inserting dummies for mods which don't have one var allMods = LoadedModManager.LoadedMods.ToList(); // Find Core and CCL in the mod order coreModIndex = -1; cclModIndex = -1; for (int i = 0; i < allMods.Count; ++i) { LoadedMod mod = allMods[i]; if (mod.name == "Core") { coreModIndex = i; } if (mod.name == Controller.Data.UnityObjectName) { cclModIndex = i; } } if (coreModIndex == -1) { LongEventHandler.ExecuteWhenFinished(ShowLoadOrderWindow); stringBuilder.AppendLine("\tUnable to find 'Core' in mod load order!"); //rVal = false; // Don't throw as an error, will be caught special } else if (coreModIndex != 0) { LongEventHandler.ExecuteWhenFinished(ShowLoadOrderWindow); stringBuilder.AppendLine("\t'Core' must be first in mod load order!"); //rVal = false; // Don't throw as an error, will be caught special } if (cclModIndex == -1) { LongEventHandler.ExecuteWhenFinished(ShowLoadOrderWindow); stringBuilder.Append("\tUnable to find '"); stringBuilder.Append(Controller.Data.UnityObjectName); stringBuilder.AppendLine("' in mod load order!"); //rVal = false; // Don't throw as an error, will be caught special } else if (cclModIndex != 1) { LongEventHandler.ExecuteWhenFinished(ShowLoadOrderWindow); stringBuilder.Append("\t'"); stringBuilder.Append(Controller.Data.UnityObjectName); stringBuilder.AppendLine("' must be second in mod load order, immediately after 'Core'! :: Current position is #" + (cclModIndex + 1).ToString()); //rVal = false; // Don't throw as an error, will be caught special } if (rVal) { for (int i = 0; i < allMods.Count; i++) { var modHelperDef = (ModHelperDef)null; var mod = allMods[i]; var modHelperDefs = Find_Extensions.DefListOfTypeForMod <ModHelperDef>(mod); if (!modHelperDefs.NullOrEmpty()) { if (modHelperDefs.Count > 1) { stringBuilder.Append("\t" + mod.name); CCL_Log.AppendSectionNewLine(ref stringBuilder, "Multiple ModHelperDefs detected"); rVal = false; } else { // Validate the def modHelperDef = modHelperDefs.First(); if (!modHelperDef.IsValid) { // Don't do anything special with broken mods stringBuilder.Append("\t" + mod.name); CCL_Log.AppendSectionNewLine(ref stringBuilder, "ModHelperDef is invalid"); rVal = false; } else if (!modHelperDef.dummy) { // Don't show validation message for dummy defs stringBuilder.Append("\t" + mod.name); CCL_Log.AppendSection(ref stringBuilder, "ModHelperDef"); CCL_Log.AppendSectionNewLine(ref stringBuilder, "Passed validation, requesting v" + modHelperDef.minCCLVersion); } } } else if (rVal == true) { // Doesn't exist, create a dummy for logging but only // create if we're not just checking for remaining errors modHelperDef = new ModHelperDef(); modHelperDef.defName = mod.name + "_ModHelperDef"; modHelperDef.minCCLVersion = Version.Minimum.ToString(); modHelperDef.ModName = mod.name; modHelperDef.Verbosity = Verbosity.NonFatalErrors; modHelperDef.dummy = true; } if (rVal == true) { // No errors, def is valid or a dummy // Associate the def with the mod (the dictionary is to go the other way) modHelperDef.mod = mod; // Insert it into it's ordered place in the lists Controller.Data.Mods.Insert(i, mod); Controller.Data.ModHelperDefs.Insert(i, modHelperDef); // Add a dictionary entry Controller.Data.DictModHelperDefs.Add(mod, modHelperDef); } } // Should now be a complete pair of lists in mod load order // as well as a dictionary of mods and their defs #if DEVELOPER //Dump ordered list of mods and their defs string dump = "Mod load order:\n"; for (int i = 0; i < Controller.Data.Mods.Count; i++) { dump += "\t[" + i + "] - " + Controller.Data.Mods[i].name + " - " + Controller.Data.ModHelperDefs[i].defName + (Controller.Data.ModHelperDefs[i].dummy ? " - dummy" : "") + "\n"; } CCL_Log.Write(dump); #endif if (rVal) { LoadedMod CCL_Mod = Controller.Data.Mods[cclModIndex]; ModHelperDef CCL_HelperDef = Find_Extensions.ModHelperDefForMod(CCL_Mod); // Validate xml version with assembly version var vc = Version.Compare(CCL_HelperDef.minCCLVersion); if (vc != Version.VersionCompare.ExactMatch) { stringBuilder.AppendLine("\tModHelperDef version mismatch for Community Core Library!"); rVal = false; } // CCL rank is #2 in load order and def version matches library Controller.Data.cclMod = CCL_Mod; Controller.Data.cclHelperDef = CCL_HelperDef; } } // Should be all good or up until the first error encountered 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); }
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"); }
public static void Initialize() { //enabled = false; gameValid = false; if (!initOk) { return; } var subControllers = Controller.Data.SubControllers.ToList(); if (subControllers.NullOrEmpty()) { CCL_Log.Error("SubControllers array is empty!"); return; } LongEventHandler.SetCurrentEventText("LibraryValidation".Translate()); // Validate all subs-systems subControllers.Sort((x, y) => (x.ValidationPriority > y.ValidationPriority) ? -1 : 1); foreach (var subsys in subControllers) { if (subsys.ValidationPriority != SubController.DontProcessThisPhase) { if (!subsys.Validate()) { CCL_Log.Error(subsys.strReturn, subsys.Name + " :: Validation"); return; } if (subsys.strReturn != string.Empty) { CCL_Log.Message(subsys.strReturn, subsys.Name + " :: Validations"); } } else { subsys.State = SubControllerState.Validated; } } LongEventHandler.SetCurrentEventText("Initializing".Translate()); // Initialize all sub-systems subControllers.Sort((x, y) => (x.InitializationPriority > y.InitializationPriority) ? -1 : 1); foreach (var subsys in subControllers) { if (subsys.InitializationPriority != SubController.DontProcessThisPhase) { if (!subsys.Initialize()) { CCL_Log.Error(subsys.strReturn, subsys.Name + " :: Initialization"); return; } if (subsys.strReturn != string.Empty) { CCL_Log.Message(subsys.strReturn, subsys.Name + " :: Initialization"); } } else { subsys.State = SubControllerState.Ok; } } CCL_Log.Message("Initialized"); // Yay! gameValid = true; //enabled = true; ticks = 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; }
// 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); }
// 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); }
// This method is to remove the hard-coded references allowing more flexibility in // building placements. Specifically, it removes the steam geyser/geothermal generator // lock. internal static bool _CanPlaceBlueprintOver(BuildableDef newDef, ThingDef oldDef) { if (oldDef.EverHaulable) { return(true); } // Handle steam geysers in a mod friendly way (not geothermal exclusive) // By default, nothing can be placed on steam geysers without a place worker which allows it if (oldDef == ThingDefOf.SteamGeyser) { if (newDef.placeWorkers.NullOrEmpty()) { // No place workers means nothing to allow it return(false); } if (newDef.placeWorkers.Contains(typeof(PlaceWorker_OnSteamGeyser))) { return(true); } if (newDef.placeWorkers.Contains(typeof(PlaceWorker_OnlyOnThing))) { var Restrictions = newDef.RestrictedPlacement_Properties(); #if DEBUG if (Restrictions == null) { CCL_Log.Error("PlaceWorker_OnlyOnThing unable to get properties!", newDef.defName); return(false); } #endif if (Restrictions.RestrictedThing.Contains(ThingDefOf.SteamGeyser)) { return(true); } } return(false); } ThingDef newThingDef = newDef as ThingDef; ThingDef oldThingDef = oldDef; BuildableDef buildableDef = GenSpawn.BuiltDefOf(oldDef); ThingDef resultThingDef = buildableDef as ThingDef; if ( (oldDef.category == ThingCategory.Plant) && (oldDef.passability == Traversability.Impassable) && ( (newThingDef != null) && (newThingDef.category == ThingCategory.Building) ) && (!newThingDef.building.canPlaceOverImpassablePlant) ) { return(false); } if ( (oldDef.category != ThingCategory.Building) && (!oldDef.IsBlueprint) && (!oldDef.IsFrame) ) { return(true); } if (newThingDef != null) { if (!EdificeUtility.IsEdifice((BuildableDef)newThingDef)) { return (( (oldDef.building == null) || (oldDef.building.canBuildNonEdificesUnder) ) && ( (!newThingDef.EverTransmitsPower) || (!oldDef.EverTransmitsPower) )); } if ( (EdificeUtility.IsEdifice((BuildableDef)newThingDef)) && (oldThingDef != null) && ( (oldThingDef.category == ThingCategory.Building) && (!EdificeUtility.IsEdifice((BuildableDef)oldThingDef)) ) ) { return ((newThingDef.building == null) || (newThingDef.building.canBuildNonEdificesUnder)); } if ( (resultThingDef != null) && (resultThingDef == ThingDefOf.Wall) && ( (newThingDef.building != null) && (newThingDef.building.canPlaceOverWall) ) || (newDef != ThingDefOf.PowerConduit) && (buildableDef == ThingDefOf.PowerConduit) ) { return(true); } } return (( (newDef is TerrainDef) && (buildableDef is ThingDef) && (((ThingDef)buildableDef).CoexistsWithFloors) ) || ( (buildableDef is TerrainDef) && (!(newDef is TerrainDef)) )); }