]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/mutators/base.qh
Doxygen: improve
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / mutators / base.qh
index 6fa77a858a21a2bceb2169d603c5b1a577111797..4d92b5d40578c111b334ace23da86b39f560a60e 100644 (file)
@@ -112,14 +112,13 @@ ENDCLASS(CallbackChain)
 #define _MUTATOR_HANDLE_NOP(type, id)
 #define _MUTATOR_HANDLE_PARAMS(type, id) , type in_##id
 #define _MUTATOR_HANDLE_PREPARE(type, id) id = in_##id;
-#define _MUTATOR_HANDLE_PUSHTMP(type, id) type tmp_##id = id;
+#define _MUTATOR_HANDLE_PUSHTMP(type, id) TC(type, id); type tmp_##id = id;
 #define _MUTATOR_HANDLE_PUSHOUT(type, id) type out_##id = id;
 #define _MUTATOR_HANDLE_POPTMP(type, id) id = tmp_##id;
 #define _MUTATOR_HANDLE_POPOUT(type, id) id = out_##id;
 
 void RegisterHooks() {};
 void RegisterCallbacks() {};
-void RegisterMutators() {};
 
 #define _MUTATOR_HOOKABLE(id, ...) CallbackChain HOOK_##id; bool __Mutator_Send_##id(__VA_ARGS__)
 #define MUTATOR_HOOKABLE(id, params) \
@@ -133,7 +132,11 @@ void RegisterMutators() {};
         return ret; \
     } \
     [[accumulate]] void RegisterHooks() { HOOK_##id = NEW(CallbackChain, #id); }
-#define MUTATOR_CALLHOOK(id, ...) APPLY(__Mutator_Send_##id, 0, ##__VA_ARGS__)
+#ifdef __STDC__
+    #define MUTATOR_CALLHOOK(id, ...) APPLY(__Mutator_Send_##id, 0 P99_IF_EMPTY(__VA_ARGS__)()(, __VA_ARGS__))
+#else
+    #define MUTATOR_CALLHOOK(id, ...) APPLY(__Mutator_Send_##id, 0, ##__VA_ARGS__)
+#endif
 
 enum {
     MUTATOR_REMOVING,
@@ -141,27 +144,73 @@ enum {
     MUTATOR_ROLLING_BACK
 };
 
-typedef bool(int) mutatorfunc_t;
+USING(mutatorfunc_t, bool(int));
 
 CLASS(Mutator, Object)
     ATTRIB(Mutator, m_id, int, 0)
-    ATTRIB(Mutator, mutatorname, string, string_null)
+    ATTRIB(Mutator, m_name, string, string_null)
     ATTRIB(Mutator, mutatorfunc, mutatorfunc_t, func_null)
     ATTRIB(Mutator, mutatorcheck, bool(), func_null)
     CONSTRUCTOR(Mutator, string _name, mutatorfunc_t func) {
         CONSTRUCT(Mutator);
-        this.mutatorname = _name;
+        this.m_name = _name;
         this.mutatorfunc = func;
     }
 ENDCLASS(Mutator)
 
-const int MAX_MUTATORS = 20;
-Mutator loaded_mutators[MAX_MUTATORS];
+REGISTRY(Mutators, BITS(7))
+#define Mutators_from(i) _Mutators_from(i, NULL)
+Mutator loaded_mutators[Mutators_MAX];
+bool Mutator_Add(Mutator mut);
+void Mutator_Remove(Mutator mut);
+bool mutator_log = false;
+
+#ifndef MENUQC
+/** server mutators activate corresponding client mutators for all clients */
+REGISTER_NET_LINKED(Mutator)
+
+#ifdef SVQC
+bool Mutator_SendEntity(entity this, entity to, int sf)
+{
+    int chan = MSG_ENTITY;
+    WriteHeader(chan, Mutator);
+    WriteString(chan, this.registered_id);
+    return true;
+}
+#endif
+
+#ifdef CSQC
+void NET_Mutator_Remove(entity this)
+{
+    string s = this.netname;
+    WITH(bool, mutator_log, true, LAMBDA(
+        FOREACH(Mutators, it.registered_id == s, Mutator_Remove(it));
+    ));
+}
+NET_HANDLE(Mutator, bool isNew)
+{
+    make_pure(this);
+    string s = this.netname = ReadString();
+    return = true;
+    if (isNew)
+    {
+        make_pure(this);
+        this.entremove = NET_Mutator_Remove;
+        int added = 0;
+        WITH(bool, mutator_log, true, LAMBDA(
+            FOREACH(Mutators, it.registered_id == s, { Mutator_Add(it); ++added; });
+        ));
+        if (added > 1) LOG_WARNINGF("Added more than one mutator for %s\n", s);
+    }
+}
+#endif
+
+#endif
 
 bool Mutator_Add(Mutator mut)
 {
     int j = -1;
-    for (int i = 0; i < MAX_MUTATORS; ++i) {
+    for (int i = 0; i < Mutators_MAX; ++i) {
         if (loaded_mutators[i] == mut)
             return true; // already added
         if (!(loaded_mutators[i]))
@@ -175,6 +224,10 @@ bool Mutator_Add(Mutator mut)
     mutatorfunc_t func = mut.mutatorfunc;
     if (!func(MUTATOR_ADDING)) {
         // good
+        if (mutator_log) LOG_TRACEF("Mutator: added %s\n", mut.m_name);
+#ifdef SVQC
+        Net_LinkEntity(mut, false, 0, Mutator_SendEntity);
+#endif
         return true;
     }
     backtrace("WARNING: when adding mutator: adding failed, rolling back\n");
@@ -188,10 +241,10 @@ bool Mutator_Add(Mutator mut)
 void Mutator_Remove(Mutator mut)
 {
     int i;
-    for (i = 0; i < MAX_MUTATORS; ++i)
+    for (i = 0; i < Mutators_MAX; ++i)
         if (loaded_mutators[i] == mut)
             break;
-    if (i >= MAX_MUTATORS) {
+    if (i >= Mutators_MAX) {
         backtrace("WARNING: removing not-added mutator\n");
         return;
     }
@@ -201,18 +254,12 @@ void Mutator_Remove(Mutator mut)
         // baaaaad
         error("Mutator_Remove: removing mutator failed");
     }
+    if (mutator_log) LOG_TRACEF("Mutator: removed %s\n", mut.m_name);
+#ifdef SVQC
+    Net_UnlinkEntity(mut);
+#endif
 }
 
-#define MUTATOR_DECLARATION(name) \
-    Mutator MUTATOR_##name
-#define MUTATOR_DEFINITION(name) \
-    bool MUTATORFUNCTION_##name(int mode); \
-    [[accumulate]] void RegisterMutators() { MUTATOR_##name = NEW(Mutator, #name, MUTATORFUNCTION_##name); } \
-    [[last]] bool MUTATORFUNCTION_##name(int mode)
-
-const int MUTATORS_MAX = MAX_MUTATORS;
-noref entity MUTATORS[MUTATORS_MAX], MUTATORS_first, MUTATORS_last;
-noref int MUTATORS_COUNT;
 #define REGISTER_MUTATOR(id, dependence) \
     bool MUTATORFUNCTION_##id##_hooks(int mode) { return = false; } \
     bool MUTATORFUNCTION_##id(int mode) { \
@@ -220,7 +267,7 @@ noref int MUTATORS_COUNT;
         bool ret = MUTATORFUNCTION_##id##_hooks(mode); if (ret) return ret; \
     } \
     bool MUTATOR_##id##_check() { return dependence; } \
-    REGISTER(RegisterMutators, MUTATOR, MUTATORS, MUTATORS_COUNT, id, m_id, NEW(Mutator, #id, MUTATORFUNCTION_##id)) \
+    REGISTER(Mutators, MUTATOR, id, m_id, NEW(Mutator, #id, MUTATORFUNCTION_##id)) \
     { this.mutatorcheck = MUTATOR_##id##_check; } \
     [[accumulate]] bool MUTATORFUNCTION_##id(int mode)
 
@@ -231,7 +278,7 @@ STATIC_INIT(Mutators) {
 }
 
 STATIC_INIT_LATE(Mutators) {
-    FOREACH(MUTATORS, it.mutatorcheck(), LAMBDA(Mutator_Add(it)));
+    FOREACH(Mutators, it.mutatorcheck(), Mutator_Add(it));
 }
 
 #define MUTATOR_ONADD                   if (mode == MUTATOR_ADDING)
@@ -247,11 +294,8 @@ STATIC_INIT_LATE(Mutators) {
     [[accumulate]] void RegisterCallbacks() { CALLBACK_##name = NEW(Callback, func); }
 
 #define MUTATOR_HOOKFUNCTION(...) \
-    EVAL(OVERLOAD(MUTATOR_HOOKFUNCTION, __VA_ARGS__))
-
-#define MUTATOR_HOOKFUNCTION_1(name) \
-    _MUTATOR_CALLBACK(name, HOOKFUNCTION_##name) \
-    bool HOOKFUNCTION_##name()
+    EVAL_MUTATOR_HOOKFUNCTION(OVERLOAD(MUTATOR_HOOKFUNCTION, __VA_ARGS__))
+#define EVAL_MUTATOR_HOOKFUNCTION(...) __VA_ARGS__
 
 #define MUTATOR_HOOKFUNCTION_2(mut, cb) \
     MUTATOR_HOOKFUNCTION_3(mut, cb, CBC_ORDER_ANY)
@@ -262,17 +306,17 @@ STATIC_INIT_LATE(Mutators) {
     bool mut##_##cb() { return = false; } \
     [[accumulate]] bool mut##_##cb()
 
-#define MUTATOR_HOOK(cb, func, order) do {                              \
+#define MUTATOR_HOOK(cb, func, order) MACRO_BEGIN {                     \
     MUTATOR_ONADD {                                                     \
         if (!CallbackChain_Add(HOOK_##cb, CALLBACK_##func, order)) {    \
-            LOG_INFO("HOOK FAILED: ", #cb, ":", #func, "\n");              \
+            LOG_INFO("HOOK FAILED: ", #cb, ":", #func, "\n");           \
             return true;                                                \
         }                                                               \
     }                                                                   \
     MUTATOR_ONROLLBACK_OR_REMOVE {                                      \
         CallbackChain_Remove(HOOK_##cb, CALLBACK_##func);               \
     }                                                                   \
-} while (0)
+} MACRO_END
 
 #include "events.qh"