]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/lib/replicate.qh
Add REPLICATE_APPLYCHANGE macro
[xonotic/xonotic-data.pk3dir.git] / qcsrc / lib / replicate.qh
1 #pragma once
2
3 #ifdef SVQC
4 // copies a string to a tempstring (so one can strunzone it)
5 string strcat1(string s) = #115; // FRIK_FILE
6 #endif
7
8 #if defined(CSQC)
9 #define REPLICATE_FIELD(type, name) type name
10 #elif defined(SVQC)
11 #define REPLICATE_FIELD(type, name) .type name
12 #endif
13
14 #ifdef GAMEQC
15
16     /**
17      * \def REPLICATE(fld, type, cvar)
18      * Replicate a client cvar into a server field
19      *
20      * @param fld   The field to replicate into
21      * @param type  The field type
22      * @param cvarname
23      * @param fixup_func((entity this, string original_value))  optional parameter
24      */
25         #define REPLICATE(...) EVAL_REPLICATE(OVERLOAD(REPLICATE, __VA_ARGS__))
26         #define EVAL_REPLICATE(...) __VA_ARGS__
27
28         #if defined(SVQC)
29         ACCUMULATE void ReplicateVars(entity this, entity store, string thisname, int i) {}
30         ACCUMULATE void ReplicateVars_ApplyChange(entity this, entity store, string thisname, int i) {}
31     /**
32      * \def REPLICATE(cvarname, ApplyChange_code)
33      * Allow setting code to will be executed on cvar value changes
34      *
35      * @param cvarname
36      * @param ApplyChange_code  code meant to be run on cvar value changes
37      */
38         #define REPLICATE_APPLYCHANGE(var, ApplyChange_code) \
39                 void ReplicateVars_ApplyChange(entity this, entity store, string thisname, int i) \
40                         { if (thisname == var) { ApplyChange_code } }
41         #elif defined(CSQC)
42         ACCUMULATE void ReplicateVars(int mode) {}
43         #endif
44
45         #define REPLICATE_3(fld, type, var) REPLICATE_4(fld, type, var, )
46         #define REPLICATE_4(fld, type, var, func) REPLICATE_##type(fld, var, func)
47         #if defined(SVQC)
48                 #define REPLICATE_string(fld, var, func) \
49                         REPLICATE_7(fld, string, var, , \
50                 { strcpy(field, it); }, \
51                 { strfree(field); }, \
52                 { \
53                         /* also initialize to the default value of func when requesting cvars */ \
54                         string s = func(this, strcat1(field)); \
55                         if (s != field) \
56                         { \
57                                 strcpy(field, s); \
58                         } \
59                 })
60                 #define REPLICATE_float(fld, var, func) REPLICATE_7(fld, float, var, func,  { field = stof(it); },          , )
61                 #define REPLICATE_bool(fld, var, func) REPLICATE_7(fld, bool, var, func,   { field = boolean(stoi(it)); }, , )
62                 #define REPLICATE_int(fld, var, func) REPLICATE_7(fld, int, var, func,    { field = stoi(it); },          , )
63
64                 #define REPLICATE_7(fld, type, var, func, create, destroy, after) \
65                         void ReplicateVars(entity this, entity store, string thisname, int i) \
66                         { \
67                                 type field = store.fld; \
68                                 if (i < 0) { destroy } \
69                                 else \
70                                 { \
71                                         string it = func(argv(i + 1)); \
72                                         bool current = thisname == var; \
73                                         if (i > 0) \
74                                         { \
75                                                 if (current) { create } \
76                                         } \
77                                         else \
78                                         { \
79                                                 stuffcmd(this, strcat("cl_cmd sendcvar ", var, "\n")); \
80                                         } \
81                                         if (current) { after } \
82                                 } \
83                                 store.fld = field; \
84                         }
85         #elif defined(CSQC)
86                 noref float ReplicateVars_time;
87                 #define ReplicateVars_NOT_SENDING() (time > ReplicateVars_time)
88                 #define ReplicateVars_DELAY(t) ReplicateVars_time = time + t
89                 #define ReplicateVars_DELAY_1FRAME() ReplicateVars_time = time
90                 #define REPLICATE_string(fld, var, func) REPLICATE_7(fld, float, var, func, (fld != cvar_string(var)), { strcpy(fld, cvar_string(var)); }, { strfree(fld); })
91                 #define REPLICATE_float(fld, var, func) REPLICATE_7(fld, float, var, func, (fld != cvar(var)), { fld = cvar(var); }, )
92                 #define REPLICATE_bool(fld, var, func) REPLICATE_7(fld, bool, var, func, (fld != cvar(var)), { fld = cvar(var); }, )
93                 #define REPLICATE_int(fld, var, func) REPLICATE_7(fld, int, var, func, (fld != cvar(var)), { fld = cvar(var); }, )
94
95                 void ReplicateVars_Destroy() { ReplicateVars(1); }
96                 void ReplicateVars_Send_All() { ReplicateVars(-1); }
97                 void ReplicateVars_Check()
98                 {
99                         // if a cvar has changed send it and check cvars again next frame
100                         ReplicateVars(0);
101                         if (ReplicateVars_NOT_SENDING()) // if no cvar has changed
102                                 ReplicateVars_DELAY(0.8 + random() * 0.4); // check cvars after a while
103                 }
104                 void ReplicateVars_Send(string cvarname) { localcmd(strcat("cl_cmd sendcvar ", cvarname, "\n")); }
105
106                 #define REPLICATE_7(fld, type, var, func, check, update, destroy) \
107                         void ReplicateVars(int mode) \
108                         { \
109                                 if (mode == 1) { destroy } \
110                                 else if (mode == -1) { ReplicateVars_Send(var); update } \
111                                 else if (ReplicateVars_NOT_SENDING() && check) \
112                                 { \
113                                         ReplicateVars_Send(var); \
114                                         ReplicateVars_DELAY_1FRAME(); \
115                                         update \
116                                         return; \
117                                 } \
118                         }
119
120                 #define REPLICATE_SIMPLE(field, cvarname) MACRO_BEGIN \
121                         if (ReplicateVars_NOT_SENDING()) \
122                         { \
123                                 float thecvar = cvar(cvarname); \
124                                 if(field != thecvar) \
125                                 { \
126                                         ReplicateVars_Send(cvarname); \
127                                         ReplicateVars_DELAY_1FRAME(); \
128                                         field = thecvar; \
129                                         return; \
130                                 } \
131                         } \
132                 MACRO_END
133         #endif
134
135 #endif