/// <summary> /// Creates a DynamicOptionAttribute using an object from another mod. /// </summary> /// <param name="attr">The attribute from the other mod.</param> /// <returns>A DynamicOptionAttribute object with the values from that object, where /// possible to retrieve; or null if none could be obtained.</returns> internal static DynamicOptionAttribute CreateFrom(object attr) { Type handler = null; string category = null; if (attr.GetType().Name == typeof(DynamicOptionAttribute).Name) { var trAttr = Traverse.Create(attr); try { handler = trAttr.GetProperty <Type>(nameof(Handler)); category = trAttr.GetProperty <string>(nameof(Category)); } catch (Exception e) { PUtil.LogExcWarn(e); } } return((handler == null) ? null : new DynamicOptionAttribute(handler, category)); }
/// <summary> /// Creates an OptionAttribute using an object from another mod. /// </summary> /// <param name="attr">The attribute from the other mod.</param> /// <returns>An OptionAttribute object with the values from that object, where /// possible to retrieve; or null if none could be obtained.</returns> internal static OptionAttribute CreateFrom(object attr) { string title = "", tt = "", cat = ""; if (attr.GetType().Name == typeof(OptionAttribute).Name) { var trAttr = Traverse.Create(attr); try { title = trAttr.GetProperty <string>(nameof(Title)); tt = trAttr.GetProperty <string>(nameof(Tooltip)) ?? ""; cat = trAttr.GetProperty <string>(nameof(Category)) ?? ""; } catch (Exception e) { PUtil.LogExcWarn(e); } } return(string.IsNullOrEmpty(title) ? null : new OptionAttribute(title, tt, cat)); }
/// <summary> /// Creates a ModInfoAttribute using an object from another mod. /// </summary> /// <param name="attr">The attribute from the other mod.</param> /// <returns>A ModInfoAttribute object with the values from that object, where /// possible to retrieve; or null if none could be obtained.</returns> internal static ModInfoAttribute CreateFrom(object attr) { string title = null, image = null, url = null; bool collapse = false; if (attr.GetType().Name == typeof(ModInfoAttribute).Name) { var trAttr = Traverse.Create(attr); try { title = trAttr.GetProperty <string>(nameof(Title)); image = trAttr.GetProperty <string>(nameof(Image)); url = trAttr.GetProperty <string>(nameof(URL)); collapse = trAttr.GetProperty <bool>(nameof(ForceCollapseCategories)); } catch (Exception e) { PUtil.LogExcWarn(e); } } return(string.IsNullOrEmpty(title) ? null : new ModInfoAttribute(title, url, image, collapse)); }
/// <summary> /// Retrieves a type using its full name (including namespace). However, the assembly /// name is optional, as this method searches all assemblies in the current /// AppDomain if it is null or empty. /// </summary> /// <param name="name">The type name to retrieve.</param> /// <param name="assemblyName">If specified, the name of the assembly that contains /// the type. No other assembly name will be searched if this parameter is not null /// or empty. The assembly name might not match the DLL name, use a decompiler to /// make sure.</param> /// <returns>The type, or null if the type is not found or cannot be loaded.</returns> public static Type GetTypeSafe(string name, string assemblyName = null) { Type type = null; if (string.IsNullOrEmpty(assemblyName)) { foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { try { type = assembly.GetType(name, false); } catch (System.IO.IOException) { // The common parent of exceptions when the type requires another type // that cannot be loaded } catch (BadImageFormatException) { } if (type != null) { break; } } } else { try { type = Type.GetType(name + ", " + assemblyName, false); } catch (TargetInvocationException e) { PUtil.LogWarning("Unable to load type {0} from assembly {1}:".F(name, assemblyName)); PUtil.LogExcWarn(e); } catch (ArgumentException e) { // A generic type is loaded with bad arguments PUtil.LogWarning("Unable to load type {0} from assembly {1}:".F(name, assemblyName)); PUtil.LogExcWarn(e); } catch (System.IO.IOException) { // The common parent of exceptions when the type requires another type that // cannot be loaded } catch (BadImageFormatException) { } } return(type); }
/// <summary> /// Creates a LimitAttribute using an object from another mod. /// </summary> /// <param name="attr">The attribute from the other mod.</param> /// <returns>A LimitAttribute object with the values from that object, where /// possible to retrieve; or null if none could be obtained.</returns> private static LimitAttribute CreateFrom(object attr) { LimitAttribute la = null; if (attr.GetType().Name == typeof(LimitAttribute).Name) { // Has limit type var trAttr = Traverse.Create(attr); double min = 0.0, max = 0.0; try { min = trAttr.GetProperty <double>(nameof(Minimum)); max = trAttr.GetProperty <double>(nameof(Maximum)); } catch (Exception e) { PUtil.LogExcWarn(e); } if (min != 0.0 || max != 0.0) { la = new LimitAttribute(min, max); } } return(la); }
/// <summary> /// Applies all patches. /// </summary> /// <param name="instance">The Harmony instance to use when patching.</param> private static void PatchAll(HarmonyInstance instance) { if (instance == null) { throw new ArgumentNullException("instance"); } // ColonyAchievementStatus instance.Patch(typeof(ColonyAchievementStatus), "Serialize", PatchMethod(nameof(Serialize_Prefix)), null); // Db instance.Patch(typeof(Db), "Initialize", PatchMethod(nameof(Initialize_Prefix)), PatchMethod(nameof(Initialize_Postfix))); // Game instance.Patch(typeof(Game), "DestroyInstances", null, PatchMethod(nameof( Game_DestroyInstances_Postfix))); instance.Patch(typeof(Game), "OnPrefabInit", null, PatchMethod(nameof( Game_OnPrefabInit_Postfix))); // GameInputMapping instance.Patch(typeof(GameInputMapping), "SetDefaultKeyBindings", null, PatchMethod(nameof(SetDefaultKeyBindings_Postfix))); // GameUtil instance.Patch(typeof(GameUtil), "GetKeycodeLocalized", PatchMethod(nameof(GetKeycodeLocalized_Prefix)), null); // KInputController instance.PatchConstructor(typeof(KInputController.KeyDef), new Type[] { typeof(KKeyCode), typeof(Modifier) }, null, PatchMethod(nameof(CKeyDef_Postfix))); instance.Patch(typeof(KInputController), "IsActive", PatchMethod(nameof(IsActive_Prefix)), null); instance.Patch(typeof(KInputController), "QueueButtonEvent", PatchMethod(nameof(QueueButtonEvent_Prefix)), null); if (PLightManager.InitInstance()) { // DiscreteShadowCaster instance.Patch(typeof(DiscreteShadowCaster), "GetVisibleCells", PatchMethod(nameof(GetVisibleCells_Prefix)), null); // Light2D instance.Patch(typeof(Light2D), "AddToScenePartitioner", PatchMethod(nameof(AddToScenePartitioner_Prefix)), null); instance.Patch(typeof(Light2D), "RefreshShapeAndPosition", null, PatchMethod(nameof(RefreshShapeAndPosition_Postfix))); // LightGridEmitter instance.Patch(typeof(LightGridEmitter), "AddToGrid", null, PatchMethod(nameof(AddToGrid_Postfix))); instance.Patch(typeof(LightGridEmitter), "ComputeLux", PatchMethod(nameof(ComputeLux_Prefix)), null); instance.Patch(typeof(LightGridEmitter), "RemoveFromGrid", null, PatchMethod(nameof(RemoveFromGrid_Postfix))); instance.Patch(typeof(LightGridEmitter), "UpdateLitCells", PatchMethod(nameof(UpdateLitCells_Prefix)), null); // LightGridManager instance.Patch(typeof(LightGridManager), "CreatePreview", PatchMethod(nameof(CreatePreview_Prefix)), null); // LightShapePreview instance.Patch(typeof(LightShapePreview), "Update", PatchMethod(nameof(LightShapePreview_Update_Prefix)), null); // Rotatable instance.Patch(typeof(Rotatable), "OrientVisualizer", null, PatchMethod(nameof(OrientVisualizer_Postfix))); } // MainMenu instance.Patch(typeof(MainMenu), "OnSpawn", null, PatchMethod( nameof(MainMenu_OnSpawn_Postfix))); // PBuilding instance.Patch(typeof(BuildingTemplates), "CreateBuildingDef", null, PatchMethod(nameof(CreateBuildingDef_Postfix))); instance.Patch(typeof(EquipmentTemplates), "CreateEquipmentDef", null, PatchMethod(nameof(CreateEquipmentDef_Postfix))); if (PBuilding.CheckBuildings()) { instance.Patch(typeof(GeneratedBuildings), "LoadGeneratedBuildings", PatchMethod(nameof(LoadGeneratedBuildings_Prefix)), null); } // PCodex instance.Patch(typeof(CodexCache), "CollectEntries", null, PatchMethod(nameof(CollectEntries_Postfix))); instance.Patch(typeof(CodexCache), "CollectSubEntries", null, PatchMethod(nameof(CollectSubEntries_Postfix))); // PLocalization var locale = Localization.GetLocale(); if (locale != null) { PLocalization.LocalizeAll(locale); } // ModsScreen POptions.Init(); instance.Patch(typeof(ModsScreen), "BuildDisplay", null, PatchMethod(nameof(BuildDisplay_Postfix))); // SteamUGCService var ugc = PPatchTools.GetTypeSafe("SteamUGCService", "Assembly-CSharp"); if (ugc != null) { try { instance.PatchTranspile(ugc, "LoadPreviewImage", PatchMethod(nameof( LoadPreviewImage_Transpile))); } catch (Exception e) { PUtil.LogExcWarn(e); } } // TMPro.TMP_InputField try { instance.Patch(typeof(TMPro.TMP_InputField), "OnEnable", null, PatchMethod(nameof(OnEnable_Postfix))); } catch (Exception) { PUtil.LogWarning("Unable to patch TextMeshPro bug, text fields may display " + "improperly inside scroll areas"); } // Postload, legacy and normal PPatchManager.ExecuteLegacyPostload(); PPatchManager.RunAll(RunAt.AfterModsLoad); }