public HookUID(HOOK_ID evt, object reg, bool once = false) { uid = LastID++; hook = evt; registrar = reg; SingleUse = once; }
/// <summary> /// Registers a hook that will fire only once and then be removed. /// </summary> /// <param name="evt">The event to hook.</param> /// <param name="cb">The callback to fire for this event.</param> /// <returns></returns> public static HookUID Once(HOOK_ID evt, Sisco_Hook_Delegate cb) { HookUID hook = register(evt, cb); hook.SingleUse = true; return(hook); }
/// <summary> /// Unhook a previous hook you installed. /// </summary> /// <param name="registrar">Unique identifier used for grouping many hooks into a category for efficient removal later.</param> /// <param name="hook">Id of the event to unhook.</param> /// <param name="cb">The function to call.</param> /// <returns>(BOOL) Whether the event was successfully unhooked.</returns> public static bool unregister(object registrar, HOOK_ID hook, Sisco_Hook_Delegate cb) { if (registrar == null) { registrar = Get_Assembly_Registrar(Assembly.GetCallingAssembly()); } HookUID UID = null; try { bool hk_success = false; if (SiscosHooks.Events.ContainsKey(hook)) { // Since all hooks are given a unique id and mapped to it in the events list now, we need to find this delegates id and remove it that way. UID = SiscosHooks.Events[hook].FirstOrDefault(kv => (kv.Value == cb)).Key; if (UID != null) { hk_success = SiscosHooks.Events[hook].Remove(UID); } if (!hk_success) { Log("Failed to remove hook from Events list: {0}", UID); return(false); } else { // Update the number of registered instances for this event. EventCounter[(int)hook] = SiscosHooks.Events[hook].Count; } } bool tr_success = false; if (SiscosHooks.Tracker.ContainsKey(registrar)) { //add this hook to their list. tr_success = SiscosHooks.Tracker[registrar].Remove(UID); if (!tr_success) { Log("Failed to remove {0} from tracker.", UID); } } return(tr_success && hk_success); } catch (Exception ex) { Log(ex); } return(false); }
// ugh, oh god is this awful. // Update: not so awful now that it caches the name... public override string ToString() { if (name != null) return name; Type type = typeof(HOOK_ID); FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public); foreach (FieldInfo field in fields) { if (field.FieldType != typeof(HOOK_ID)) continue; HOOK_ID hk = (HOOK_ID)field.GetValue(this); if (hk.id != id) continue; name = field.Name; break; } return name; }
/// <summary> /// Unhook ALL of the previous hooks you installed with a specified registrar object. /// </summary> /// <param name="registrar">Unique identifier used for grouping many hooks into a category for efficient removal later.</param> /// <param name="hook">Id of the event to unhook. Leave this blank to remove ALL hooked events.</param> /// <returns>(BOOL) Whether the events was successfully unhooked.</returns> public static bool unregister_all(object registrar, HOOK_ID hook) { if (registrar == null) { registrar = Get_Assembly_Registrar(Assembly.GetCallingAssembly()); } try { // create the callback list for this hook type if it doesn't exist. if (!SiscosHooks.Events.ContainsKey(hook)) { SiscosHooks.Events[hook] = new Dictionary <HookUID, Sisco_Hook_Delegate>(); } // create this registrar's hooks list if it doesn't exist. List <HookUID> hooks_list; if (!SiscosHooks.Tracker.ContainsKey(registrar)) { return(false); } SiscosHooks.Tracker.TryGetValue(registrar, out hooks_list); var trash = new List <HookUID>(hooks_list); foreach (HookUID UID in trash) { if (hook != HOOK_ID.NONE && UID.hook != hook) { continue; } bool b = unregister(UID); if (!b) { Log("Failed to unregister {0}", UID); } } } catch (Exception ex) { Log(ex.Message); } return(false); }
//[Obsolete("Use register(Hook_ID, Callback, Registrar) or register(Hook_ID, Callback) instead!", true)] //public static bool register(object registrar, HOOK_ID hook, Sisco_Hook_Delegate cb) { return (register(hook, cb, null) != null); } /// <summary> /// Register your own function to be called whenever a specified event triggers. /// </summary> /// <param name="registrar">Identifier used for grouping many hooks into a category for efficient removal later.</param> /// <param name="hook">The event to hook.</param> /// <param name="cb">The function to call.</param> /// <returns>A <see cref="HookUID"/> for the newly registered hook or <c>null</c> upon failure.</returns> public static HookUID register(HOOK_ID hook, Sisco_Hook_Delegate cb, object registrar = null) { HookUID UID = null; if (registrar == null) { registrar = Get_Assembly_Registrar(Assembly.GetCallingAssembly()); } if (hook == null) { Log("Attempted to register for NULL event!"); return(null); } try { // create the callback list for this hook type if it doesn't exist. if (!SiscosHooks.Events.ContainsKey(hook)) { SiscosHooks.Events[hook] = new Dictionary <HookUID, Sisco_Hook_Delegate>(); } UID = new HookUID(hook, registrar); SiscosHooks.Events[hook].Add(UID, cb); EventCounter[(int)hook] = SiscosHooks.Events[hook].Count; if (registrar != null) { // create this registrar's hooks list if it doesn't exist. if (!SiscosHooks.Tracker.ContainsKey(registrar)) { return(null); } //add this hook to their list. SiscosHooks.Tracker[registrar].Add(UID); } return(UID); } catch (Exception ex) { Log(ex); } return(null); }
public static _hook_result call(HOOK_ID hook, object sender, ref object returnValue, object[] args) { try { #if DEBUG SLog.Info("[SiscosHooks] {0}({1})", hook, Get_Arg_String(args)); #endif _hook_result result = new _hook_result(args); Dictionary <HookUID, Sisco_Hook_Delegate> cb_list; bool r = Events.TryGetValue((HOOK_ID)hook, out cb_list); if (r == false) { return(new _hook_result()); //no abort } List <HookUID> TRASH = null; foreach (KeyValuePair <HookUID, Sisco_Hook_Delegate> kvp in cb_list) { try { HookUID UID = kvp.Key; UID.hasFired = true; Sisco_Hook_Delegate act = kvp.Value; if (act == null) { continue; } Sisco_Return ret = act(ref sender, ref result.args, ref returnValue); // If this hook is a singleuse hook then we need to put it in our trashbin so we know to unregister it at the end of this function. if (UID.SingleUse) { if (TRASH == null) { TRASH = new List <HookUID>(); } TRASH.Add(UID); } if (ret != null) { if (ret.early_return) { result.abort = true; } if (ret.handled == true) { result.handled = true; break;//cancel all other events } } } catch (Exception ex) { Log(hook, ex.Message); Log(ex.StackTrace); } } if (TRASH != null) { foreach (HookUID uid in TRASH) { try { unregister(uid); } catch (Exception ex) { Log(uid.hook, DebugHud.Format_Exception_Log(ex)); } } } if (result == null) { Log(hook, "Result became NULL somehow!"); return(new _hook_result());// we MUST return something other then NULL or the whole game can screw up! } if (args != null && args.Length != result.args.Length) { Log(hook, "The size of Result.args does not match the number of arguments recieved from the function!"); } return(result); } catch (Exception ex) { Log(hook, ex.Message); Log(ex.StackTrace); return(new _hook_result()); } return(new _hook_result());//no abort }
private static void Log(HOOK_ID hook, string format, params object[] args) { SLog.Info(String.Format("{0}<{1}> {2}", LOG_TAG, hook.ToString(), format), args); }
/// <summary> /// Allows registering single-use hook with a void callback. /// </summary> /// <param name="evt"></param> /// <param name="cb"></param> /// <returns></returns> public static HookUID Once(HOOK_ID evt, Action cb) { return(Once(evt, (ref object sender, ref object[] args, ref object retVal) => { cb(); return null; })); }
/// <summary> /// Copies all of the relevant data from one instance into another. /// </summary> /// <param name="h"></param> public HookUID(HookUID h) { uid = h.uid; hook = h.hook; registrar = h.registrar; }
public bool Equals(HOOK_ID obj) { return (this.id == obj.id); }
private HOOK_ID(HOOK_ID i) { id = i.id; if (id >= _idx) _idx = (id + 1); }