/// <summary> /// Registers a method which will be run after PLib and all mods load. It will be /// passed a HarmonyInstance which can be used to make late patches. /// </summary> /// <param name="callback">The method to invoke.</param> public static void RegisterPostload(PostLoadHandler callback) { if (callback == null) { throw new ArgumentNullException("callback"); } // Some others used this call before the library was initialized if (!PLibInit) { InitLibrary(false); LogWarning("PUtil.InitLibrary was not called before using RegisterPostload!"); } lock (PSharedData.GetLock(PRegistry.KEY_POSTLOAD_LOCK)) { // Get list holding postload information var list = PSharedData.GetData <IList <PostLoadHandler> >(PRegistry. KEY_POSTLOAD_TABLE); if (list == null) { PSharedData.PutData(PRegistry.KEY_POSTLOAD_TABLE, list = new List <PostLoadHandler>(16)); } list.Add(callback); string name = Assembly.GetCallingAssembly()?.GetName()?.Name; if (name != null) { PRegistry.LogPatchDebug("Registered post-load handler for " + name); } } }
/// <summary> /// Registers a PAction with the action manager. There is no corresponding Unregister /// call, so avoid spamming PActions. /// /// This call should occur after PUtil.InitLibrary() during the mod OnLoad(). If called /// earlier, it may fail with InvalidOperationException, and if called later, the /// user's custom key bind (if applicable) will be discarded. /// </summary> /// <param name="identifier">The identifier for this action.</param> /// <param name="title">The action's title.</param> /// <param name="binding">The default key binding for this action.</param> /// <returns>The action thus registered.</returns> /// <exception cref="InvalidOperationException">If PLib is not yet initialized.</exception> public static PAction Register(string identifier, LocString title, PKeyBinding binding = null) { // In case this call is used before the library was initialized if (!PUtil.PLibInit) { PUtil.InitLibrary(false); PUtil.LogWarning("PUtil.InitLibrary was not called before using " + "PAction.Register!"); } int actionID; PAction action; lock (PSharedData.GetLock(PRegistry.KEY_ACTION_LOCK)) { actionID = PSharedData.GetData <int>(PRegistry.KEY_ACTION_ID); if (actionID <= 0) { throw new InvalidOperationException("PAction action ID is not set!"); } PSharedData.PutData(PRegistry.KEY_ACTION_ID, actionID + 1); } action = new PAction(actionID, identifier, title); PActionManager.ConfigureTitle(action); action.AddKeyBinding(binding ?? new PKeyBinding()); return(action); }
/// <summary> /// Executes all post-load handlers. /// </summary> internal static void ExecutePostload() { IList <PostLoadHandler> postload = null; lock (PSharedData.GetLock(PRegistry.KEY_POSTLOAD_LOCK)) { // Get list holding postload information var list = PSharedData.GetData <IList <PostLoadHandler> >(PRegistry. KEY_POSTLOAD_TABLE); if (list != null) { postload = new List <PostLoadHandler>(list); } } // If there were any, run them if (postload != null) { var hInst = Harmony.HarmonyInstance.Create("PLib.PostLoad"); PRegistry.LogPatchDebug("Executing {0:D} post-load handler(s)".F(postload. Count)); foreach (var handler in postload) { handler?.Invoke(hInst); } } }
/// <summary> /// Registers a PAction with the action manager. There is no corresponding Unregister /// call, so avoid spamming PActions. /// /// This call should occur after PUtil.LogModInit() during the mod OnLoad(). If called /// earlier, it may fail with InvalidOperationException, and if called later, the /// user's custom key bind (if applicable) will be discarded. /// </summary> /// <param name="identifier">The identifier for this action.</param> /// <param name="title">The action's title.</param> /// <param name="binding">The default key binding for this action.</param> /// <returns>The action thus registered.</returns> /// <exception cref="InvalidOperationException">If PLib is not yet initialized.</exception> public static PAction Register(string identifier, LocString title, PKeyBinding binding = null) { object locker = PSharedData.GetData <object>(PRegistry.KEY_ACTION_LOCK); int actionID; if (locker == null) { throw new InvalidOperationException("PAction.Register called before PLib loaded!"); } PAction action; lock (locker) { actionID = PSharedData.GetData <int>(PRegistry.KEY_ACTION_ID); if (actionID <= 0) { throw new InvalidOperationException("PAction action ID is not set!"); } PSharedData.PutData(PRegistry.KEY_ACTION_ID, actionID + 1); } action = new PAction(actionID, identifier, title); PActionManager.ConfigureTitle(action); action.AddKeyBinding(binding ?? new PKeyBinding()); return(action); }
/// <summary> /// Updates the action system based on the current actions registered. /// </summary> public void UpdateMaxAction() { object locker = PSharedData.GetData <object>(PRegistry.KEY_ACTION_LOCK); if (locker != null) { lock (locker) { maxPAction = Math.Max(0, PSharedData.GetData <int>(PRegistry. KEY_ACTION_ID)); } } }
/// <summary> /// Initializes the master list of post load patches to apply. /// </summary> private static void InitMaster() { if (master == null) { var newMaster = PSharedData.GetData <IDictionary <uint, SharedRunList> >( PRegistry.KEY_POSTLOAD_ENHANCED); if (newMaster == null) { PSharedData.PutData(PRegistry.KEY_POSTLOAD_ENHANCED, newMaster = new Dictionary <uint, SharedRunList>(8)); } master = newMaster; } }
/// <summary> /// Registers a method which will be run after PLib and all mods load. It will be /// passed a HarmonyInstance which can be used to make late patches. /// </summary> /// <param name="callback">The method to invoke.</param> public static void RegisterPostload(PostLoadHandler callback) { if (callback == null) { throw new ArgumentNullException("callback"); } lock (PSharedData.GetLock(PRegistry.KEY_POSTLOAD_LOCK)) { // Get list holding postload information var list = PSharedData.GetData <IList <PostLoadHandler> >(PRegistry. KEY_POSTLOAD_TABLE); if (list == null) { PSharedData.PutData(PRegistry.KEY_POSTLOAD_TABLE, list = new List <PostLoadHandler>(16)); } list.Add(callback); string name = Assembly.GetCallingAssembly()?.GetName()?.Name; if (name != null) { PRegistry.LogPatchDebug("Registered post-load handler for " + name); } } }
/// <summary> /// Executes all post-load handlers. /// </summary> internal static void ExecutePostload() { IList <PostLoadHandler> postload = null; lock (PSharedData.GetLock(PRegistry.KEY_POSTLOAD_LOCK)) { // Get list holding postload information var list = PSharedData.GetData <IList <PostLoadHandler> >(PRegistry. KEY_POSTLOAD_TABLE); if (list != null) { postload = new List <PostLoadHandler>(list); } } // If there were any, run them if (postload != null) { var hInst = Harmony.HarmonyInstance.Create("PLib.PostLoad"); PRegistry.LogPatchDebug("Executing {0:D} post-load handler(s)".F(postload. Count)); foreach (var handler in postload) { try { handler?.Invoke(hInst); } catch (Exception e) { var method = handler.Method; // Say which mod's postload crashed if (method != null) { PRegistry.LogPatchWarning("Postload handler for {0} failed:".F( method.DeclaringType.Assembly?.GetName()?.Name ?? "?")); } LogException(e); } } } }