39 ATTRIB(CallbackNode, cbc_next, CallbackNode);
40 ATTRIB(CallbackNode, cbc_order,
int, 0);
44 this.cbc_order = order;
61 if (this.cbc_order & CBC_ORDER_FIRST)
64 if (this.cbc_order & CBC_ORDER_LAST)
68 if (order & CBC_ORDER_FIRST) {
69 node.cbc_next = this.cbc_next;
71 }
else if (order & CBC_ORDER_LAST) {
73 while (it) { prev = it, it = it.cbc_next; }
74 if (prev) prev.cbc_next = node;
75 else this.cbc_next = node;
79 while (it && !(it.cbc_order & CBC_ORDER_LAST)) { prev = it, it = it.cbc_next; }
81 if (prev) prev.cbc_next = node;
82 else this.cbc_next = node;
95 else this.cbc_next =
next;
101 this.cbc_order = order;
107 for (
Callback it = this.cbc_next; it; it = it.cbc_next) {
109 r |= it.cbc.cbc_func();
115 #define _MUTATOR_HANDLE_NOP(type, id) 116 #define _MUTATOR_HANDLE_PARAMS(type, id) , type in_##id 117 #define _MUTATOR_HANDLE_PREPARE(type, id) id = in_##id; 118 #define _MUTATOR_HANDLE_PUSHTMP(type, id) TC(type, id); type tmp_##id = id; 119 #define _MUTATOR_HANDLE_PUSHOUT(type, id) type out_##id = id; 120 #define _MUTATOR_HANDLE_POPTMP(type, id) id = tmp_##id; 121 #define _MUTATOR_HANDLE_POPOUT(type, id) id = out_##id; 126 #define MUTATOR_HOOKABLE(id, params) _MUTATOR_HOOKABLE(id, params) 127 #define _MUTATOR_HOOKABLE(id, params) \ 128 CallbackChain HOOK_##id; \ 129 bool __Mutator_Send_##id(int params(_MUTATOR_HANDLE_PARAMS, _MUTATOR_HANDLE_NOP)) { \ 130 params(_MUTATOR_HANDLE_PUSHTMP, _MUTATOR_HANDLE_NOP) \ 131 params(_MUTATOR_HANDLE_PREPARE, _MUTATOR_HANDLE_NOP) \ 132 bool ret = CallbackChain_Call(HOOK_##id); \ 133 params(_MUTATOR_HANDLE_NOP, _MUTATOR_HANDLE_PUSHOUT) \ 134 params(_MUTATOR_HANDLE_POPTMP, _MUTATOR_HANDLE_NOP) \ 135 params(_MUTATOR_HANDLE_NOP, _MUTATOR_HANDLE_POPOUT) \ 138 ACCUMULATE void RegisterHooks() { HOOK_##id = NEW(CallbackChain, #id); } 140 #define MUTATOR_CALLHOOK(id, ...) _MUTATOR_CALLHOOK(id, __VA_ARGS__) 142 #define _MUTATOR_CALLHOOK(id, ...) APPLY(__Mutator_Send_##id, 0 P99_IF_EMPTY(__VA_ARGS__)()(, __VA_ARGS__)) 144 #define _MUTATOR_CALLHOOK(id, ...) APPLY(__Mutator_Send_##id, 0, ##__VA_ARGS__) 159 ATTRIB(Mutator, mutatorcheck,
bool());
163 this.mutatorfunc = func;
175 #define _MUTATOR_IS_ENABLED(this) this.mutatorcheck() 176 #define MUTATOR_IS_ENABLED(this) _MUTATOR_IS_ENABLED(MUTATOR_##this) 185 int chan = MSG_ENTITY;
193 void NET_Mutator_Remove(
entity this)
196 WITH(
bool, mutator_log,
true, {
197 FOREACH(Mutators, it.registered_id == s, Mutator_Remove(it));
208 this.entremove = NET_Mutator_Remove;
210 WITH(
bool, mutator_log,
true, {
211 FOREACH(Mutators, it.registered_id == s, { Mutator_Add(it); ++added; });
213 if (added > 1)
LOG_WARNF(
"Added more than one mutator for %s", s);
229 if (mutator_log)
LOG_TRACEF(
"Mutator: added %s", mut.m_name);
231 Net_LinkEntity(mut,
false, 0, Mutator_SendEntity);
235 backtrace(
"WARNING: when adding mutator: adding failed, rolling back\n");
238 error(
"WARNING: when adding mutator: rolling back failed");
247 backtrace(
"WARNING: removing not-added mutator\n");
255 error(
"Mutator_Remove: removing mutator failed");
257 if (mutator_log)
LOG_TRACEF(
"Mutator: removed %s", mut.m_name);
259 Net_UnlinkEntity(mut);
263 #define REGISTER_MUTATOR(id, dependence) \ 264 bool MUTATORFUNC_##id##_hooks(int mode) { return = false; } \ 265 bool MUTATORFUNC_##id(int mode) { \ 267 bool ret = MUTATORFUNC_##id##_hooks(mode); if (ret) return ret; \ 269 bool MUTATOR_##id##_check() { return dependence; } \ 270 REGISTER(Mutators, MUTATOR, id, m_id, NEW(Mutator, #id, MUTATORFUNC_##id)) \ 271 { this.mutatorcheck = MUTATOR_##id##_check; } \ 272 ACCUMULATE bool MUTATORFUNC_##id(int mode) 284 #define MUTATOR_ONADD if (mode == MUTATOR_ADDING) 285 #define MUTATOR_ONREMOVE if (mode == MUTATOR_REMOVING) 286 #define MUTATOR_ONROLLBACK_OR_REMOVE if (mode == MUTATOR_REMOVING || mode == MUTATOR_ROLLING_BACK) 288 #define MUTATOR_STATIC() MACRO_BEGIN \ 292 error("This is a game type and it cannot be added at runtime."); \ 296 LOG_INFO("This is a game type and it cannot be removed at runtime."); \ 301 #define MUTATOR_ADD(name) Mutator_Add(MUTATOR_##name) 302 #define MUTATOR_REMOVE(name) Mutator_Remove(MUTATOR_##name) 303 #define MUTATOR_RETURNVALUE CallbackChain_ReturnValue 305 #define _MUTATOR_CALLBACK(name, func) \ 306 Callback CB_##name; \ 308 ACCUMULATE void RegisterCallbacks() { CB_##name = NEW(Callback, func); } 310 #define MUTATOR_HOOKFUNCTION(...) \ 311 EVAL_MUTATOR_HOOKFUNCTION(OVERLOAD(MUTATOR_HOOKFUNCTION, __VA_ARGS__)) 312 #define EVAL_MUTATOR_HOOKFUNCTION(...) __VA_ARGS__ 314 #define MUTATOR_HOOKFUNCTION_2(mut, cb) \ 315 MUTATOR_HOOKFUNCTION_3(mut, cb, CBC_ORDER_ANY) 317 #define MUTATOR_HOOKFUNCTION_3(mut, cb, order) \ 318 _MUTATOR_CALLBACK(mut##_##cb, mut##_##cb) \ 319 ACCUMULATE bool MUTATORFUNC_##mut##_hooks(int mode) { MUTATOR_HOOK(cb, mut##_##cb, order); } \ 320 bool mut##_##cb() { return = false; } \ 321 ACCUMULATE bool mut##_##cb() 326 LOG_INFO(
"HOOK FAILED: ", cb,
":", func);
329 #define MUTATOR_HOOK(cb, func, order) MACRO_BEGIN \ 331 if (!CallbackChain_Add(HOOK_##cb, CB_##func, order)) { \ 332 _mutPrintFail(#cb, #func); \ 336 MUTATOR_ONROLLBACK_OR_REMOVE { \ 337 CallbackChain_Remove(HOOK_##cb, CB_##func); \
string registered_id
registered item identifier
const int CBC_ORDER_EXCLUSIVE
#define REGISTER_NET_LINKED(id)
void _mutPrintFail(string cb, string func)
Callbacks may be added to zero or more callback chains.
void Mutator_Remove(Mutator mut)
Callback chains contain zero or more callbacks.
bool CallbackChain_Call(CallbackChain this)
#define _MUTATOR_IS_ENABLED(this)
#define NET_HANDLE(id, param)
#define CONSTRUCT(cname,...)
bool Mutator_Add(Mutator mut)
#define REGISTRY_DEFINE_GET(id, null)
int CallbackChain_Remove(CallbackChain this, Callback cb)
#define REGISTRY(id, max)
Declare a new registry.
const int CBC_ORDER_FIRST
bool CallbackChain_Add(CallbackChain this, Callback cb, int order)
#define WITH(type, name, value, block)
bool CallbackChain_ReturnValue
#define FOREACH(list, cond, body)
#define CONSTRUCTOR(cname,...)
STATIC_INIT_LATE(Mutators)