+++ /dev/null
-#include "base.qh"
-#include "../_all.qh"
-
-.bool() cbc_func;
-.entity cbc_next;
-.int cbc_order;
-
-entity CallbackChain_New(string name)
-{
- entity e = spawn();
- e.classname = "callbackchain";
- e.netname = name;
- return e;
-}
-
-bool CallbackChain_Add(entity cb, bool() func, int order)
-{
- if (order & CBC_ORDER_FIRST) {
- if (order & CBC_ORDER_LAST)
- if (cb.cbc_order & CBC_ORDER_ANY)
- return false;
- if (cb.cbc_order & CBC_ORDER_FIRST)
- return false;
- } else if (order & CBC_ORDER_LAST) {
- if (cb.cbc_order & CBC_ORDER_LAST)
- return false;
- }
- entity thiscb = spawn();
- thiscb.classname = "callback";
- thiscb.cbc_func = func;
- thiscb.cbc_order = order;
- if (order & CBC_ORDER_FIRST) {
- thiscb.cbc_next = cb.cbc_next;
- cb.cbc_next = thiscb;
- } else if (order & CBC_ORDER_LAST) {
- entity e = cb;
- while (e.cbc_next) e = e.cbc_next;
- e.cbc_next = thiscb;
- } else {
- // by default we execute last, but before a possible CBC_ORDER_LAST callback
- entity e = cb;
- // we must make sure that we insert BEFORE an CBC_ORDER_LAST mutator!
- while (e.cbc_next && !(e.cbc_next.cbc_order & CBC_ORDER_LAST)) e = e.cbc_next;
- thiscb.cbc_next = e.cbc_next;
- e.cbc_next = thiscb;
- }
- cb.cbc_order |= (order | CBC_ORDER_ANY);
- return true;
-}
-
-int CallbackChain_Remove(entity cb, bool() func)
-{
- int n = 0, order = 0;
- for (entity e = cb; e.cbc_next; e = e.cbc_next) {
- while (e.cbc_next.cbc_func == func) {
- // remove e.cbc_next from the chain
- entity e2 = e.cbc_next.cbc_next;
- remove(e.cbc_next);
- e.cbc_next = e2;
- ++n;
- }
- // e.cbc_next is now something we want to keep
- order |= (e.cbc_next.cbc_order & CBC_ORDER_ANY);
- }
- cb.cbc_order = order;
- return n;
-}
-
-bool CallbackChain_Call(entity cb)
-{
- bool r = false;
- for (entity e = cb; e.cbc_next; e = e.cbc_next) {
- CallbackChain_ReturnValue = r;
- r |= e.cbc_next.cbc_func();
- }
- return r; // callbacks return an error status, so 0 is default return value
-}
-
-const int MAX_MUTATORS = 15;
-string loaded_mutators[MAX_MUTATORS];
-bool Mutator_Add(mutatorfunc_t func, string name)
-{
- int j = -1;
- for (int i = 0; i < MAX_MUTATORS; ++i) {
- if (name == loaded_mutators[i])
- return true; // already added
- if (!(loaded_mutators[i]))
- j = i;
- }
- if (j < 0) {
- backtrace("WARNING: too many mutators, cannot add any more\n");
- return false;
- }
- loaded_mutators[j] = name;
-
- if (!func(MUTATOR_ADDING)) {
- // good
- return true;
- }
-
- backtrace("WARNING: when adding mutator: adding failed, rolling back\n");
-
- if (func(MUTATOR_ROLLING_BACK)) {
- // baaaaad
- error("WARNING: when adding mutator: rolling back failed");
- }
- return false;
-}
-void Mutator_Remove(mutatorfunc_t func, string name)
-{
- int i;
- for (i = 0; i < MAX_MUTATORS; ++i)
- if (name == loaded_mutators[i])
- break;
- if (i >= MAX_MUTATORS) {
- backtrace("WARNING: removing not-added mutator\n");
- return;
- }
- loaded_mutators[i] = string_null;
-
- if (func(MUTATOR_REMOVING) != 0) {
- // baaaaad
- error("Mutator_Remove: removing mutator failed");
- }
-}