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