/// <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);
        }
        //[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);
        }
        /// <summary>
        /// Unregisters a previously installed hook.
        /// </summary>
        /// <returns>(BOOL) Whether the hook was successfully removed.</returns>
        public static bool unregister(HookUID id)
        {
            try
            {
                bool hk_success = false;
                if (SiscosHooks.Events.ContainsKey(id.hook))
                {
                    hk_success = SiscosHooks.Events[id.hook].Remove(id);
                    if (!hk_success)
                    {
                        Log("Failed to remove hook from hooks list. Sender({0})", id.registrar);
                        return(false);
                    }
                    else
                    {
                        // Update the number of registered instances for this event.
                        EventCounter[(int)id.hook] = SiscosHooks.Events[id.hook].Count;
                    }
                }

                bool tr_success = false;
                if (SiscosHooks.Tracker.ContainsKey(id.registrar))
                {
                    //add this hook to their list.
                    tr_success = SiscosHooks.Tracker[id.registrar].Remove(id);
                    if (!tr_success)
                    {
                        Log("Failed to remove {0} from tracker.", id);
                    }
                }

                return(tr_success && hk_success);
            }
            catch (Exception ex)
            {
                Log(ex);
            }

            return(false);
        }
        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
        }
Beispiel #6
0
 /// <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;
 }