#pragma once #if defined(CSQC) const int REPLICATEVARS_SEND_ALL = -1; // sync all cvars with the server (init) const int REPLICATEVARS_CHECK = 0; // check if any cvar has changed and sync it with the server const int REPLICATEVARS_DESTROY = 1; // destroy data associated with cvars (shutdown) #define REPLICATE_INIT(type, name) type name #elif defined(SVQC) #define REPLICATE_INIT(type, name) .type name #endif #ifdef GAMEQC /** * \def REPLICATE(fld, type, cvar) * Replicates a client cvar into a server field * * @param fld The field to replicate into * @param type The field type * @param cvarname * @param fixup_func((entity this, string original_value)) optional parameter */ #define REPLICATE(...) EVAL_REPLICATE(OVERLOAD(REPLICATE, __VA_ARGS__)) #define EVAL_REPLICATE(...) __VA_ARGS__ #if defined(SVQC) ACCUMULATE void ReplicateVars(entity this, entity store, string thisname, int i) {} ACCUMULATE void ReplicateVars_ApplyChange(entity this, entity store, string thisname, int i) {} /** * \def REPLICATE_APPLYCHANGE(cvarname, ApplyChange_code) * Allows setting code that will be executed on cvar value changes * * @param cvarname * @param ApplyChange_code code meant to be run on cvar value changes */ #define REPLICATE_APPLYCHANGE(var, ApplyChange_code) \ void ReplicateVars_ApplyChange(entity this, entity store, string thisname, int i) \ { if (thisname == var) { ApplyChange_code } } #elif defined(CSQC) noref float ReplicateVars_time; ACCUMULATE void ReplicateVars(int mode) { if (!ReplicateVars_time || time < ReplicateVars_time) return; ReplicateVars_time = time + 0.8 + random() * 0.4; // check cvars periodically } void ReplicateVars_Start() { if (!ReplicateVars_time) // make sure it gets executed only once { ReplicateVars_time = time; ReplicateVars(REPLICATEVARS_SEND_ALL); } } #endif #define REPLICATE_3(fld, type, var) REPLICATE_4(fld, type, var, ) #define REPLICATE_4(fld, type, var, func) REPLICATE_##type(fld, var, func) #if defined(SVQC) #define REPLICATE_string(fld, var, func) \ REPLICATE_7(fld, string, var, , \ { strcpy(field, it); }, \ { strfree(field); }, \ { \ /* also initialize to the default value of func when requesting cvars */ \ string s = func(this, strcat(field)); \ if (s != field) \ { \ strcpy(field, s); \ } \ }) #define REPLICATE_vector(fld, var, func) REPLICATE_7(fld, vector, var, func, { field = stov(it); }, , ) #define REPLICATE_float(fld, var, func) REPLICATE_7(fld, float, var, func, { field = stof(it); }, , ) #define REPLICATE_bool(fld, var, func) REPLICATE_7(fld, bool, var, func, { field = boolean(stoi(it)); }, , ) #define REPLICATE_int(fld, var, func) REPLICATE_7(fld, int, var, func, { field = stoi(it); }, , ) #define REPLICATE_7(fld, type, var, func, create, destroy, after) \ void ReplicateVars(entity this, entity store, string thisname, int i) \ { \ type field = store.fld; \ if (i < 0) { destroy } \ else \ { \ string it = func(argv(i + 1)); \ bool current = thisname == var; \ if (i > 0) \ { \ if (current) { create } \ } \ else \ { \ stuffcmd(this, strcat("cl_cmd sendcvar ", var, "\n")); \ } \ if (current) { after } \ } \ store.fld = field; \ } #elif defined(CSQC) #define REPLICATE_vector(fld, var, func) REPLICATE_7(fld, vector, var, func, (fld != stov(cvar_string(var))), { fld = stov(cvar_string(var)); }, ) #define REPLICATE_string(fld, var, func) REPLICATE_7(fld, float, var, func, (fld != cvar_string(var)), { strcpy(fld, cvar_string(var)); }, { strfree(fld); }) #define REPLICATE_float(fld, var, func) REPLICATE_7(fld, float, var, func, (fld != cvar(var)), { fld = cvar(var); }, ) #define REPLICATE_bool(fld, var, func) REPLICATE_7(fld, bool, var, func, (fld != cvar(var)), { fld = cvar(var); }, ) #define REPLICATE_int(fld, var, func) REPLICATE_7(fld, int, var, func, (fld != cvar(var)), { fld = cvar(var); }, ) void ReplicateVars_Send(string cvarname) { localcmd(strcat("cl_cmd sendcvar ", cvarname, "\n")); } #define REPLICATE_7(fld, type, var, func, check, update, destroy) \ void ReplicateVars(int mode) \ { \ if (mode == REPLICATEVARS_DESTROY) { destroy } \ else if (mode == REPLICATEVARS_SEND_ALL || check) \ { \ ReplicateVars_Send(var); \ update \ } \ } #define REPLICATE_SIMPLE(field, cvarname) MACRO_BEGIN \ float thecvar = cvar(cvarname); \ if(field != thecvar) \ { \ ReplicateVars_Send(cvarname); \ field = thecvar; \ } \ MACRO_END #endif #endif