void RegisterHooks() {};
void RegisterCallbacks() {};
-void RegisterMutators() {};
#define _MUTATOR_HOOKABLE(id, ...) CallbackChain HOOK_##id; bool __Mutator_Send_##id(__VA_ARGS__)
#define MUTATOR_HOOKABLE(id, params) \
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 = 30;
-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
+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()
+{
+ SELFPARAM();
+ string s = this.netname;
+ WITH(bool, mutator_log, true, LAMBDA(
+ FOREACH(Mutators, it.registered_id == s, LAMBDA(Mutator_Remove(it)));
+ ));
+}
+NET_HANDLE(Mutator, bool isNew)
+{
+ 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, LAMBDA(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]))
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");
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;
}
// 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) { \
bool ret = MUTATORFUNCTION_##id##_hooks(mode); if (ret) return ret; \
} \
bool MUTATOR_##id##_check() { return dependence; } \
- REGISTER(RegisterMutators, MUTATOR, MUTATORS, 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)
}
STATIC_INIT_LATE(Mutators) {
- FOREACH(MUTATORS, it.mutatorcheck(), LAMBDA(Mutator_Add(it)));
+ FOREACH(Mutators, it.mutatorcheck(), LAMBDA(Mutator_Add(it)));
}
#define MUTATOR_ONADD if (mode == MUTATOR_ADDING)
#define MUTATOR_HOOKFUNCTION(...) \
EVAL(OVERLOAD(MUTATOR_HOOKFUNCTION, __VA_ARGS__))
-#define MUTATOR_HOOKFUNCTION_1(name) \
- _MUTATOR_CALLBACK(name, HOOKFUNCTION_##name) \
- bool HOOKFUNCTION_##name()
-
#define MUTATOR_HOOKFUNCTION_2(mut, cb) \
MUTATOR_HOOKFUNCTION_3(mut, cb, CBC_ORDER_ANY)
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"); \
MUTATOR_ONROLLBACK_OR_REMOVE { \
CallbackChain_Remove(HOOK_##cb, CALLBACK_##func); \
} \
-} while (0)
+} MACRO_END
#include "events.qh"