]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/mutators/base.qc
Make most server includes order insensitive
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / base.qc
1 #include "base.qh"
2 #include "../_.qh"
3
4 .float() cbc_func;
5 .entity cbc_next;
6 .float cbc_order;
7
8 entity CallbackChain_New(string name)
9 {
10         entity e;
11         e = spawn();
12         e.classname = "callbackchain";
13         e.netname = name;
14         return e;
15 }
16
17 float CallbackChain_Add(entity cb, float() func, float order)
18 {
19         entity e;
20         if(order & CBC_ORDER_FIRST)
21         {
22                 if(order & CBC_ORDER_LAST)
23                         if(cb.cbc_order & CBC_ORDER_ANY)
24                                 return 0;
25                 if(cb.cbc_order & CBC_ORDER_FIRST)
26                         return 0;
27         }
28         else if(order & CBC_ORDER_LAST)
29         {
30                 if(cb.cbc_order & CBC_ORDER_LAST)
31                         return 0;
32         }
33         entity thiscb;
34         thiscb = spawn();
35         thiscb.classname = "callback";
36         thiscb.cbc_func = func;
37         thiscb.cbc_order = order;
38         if(order & CBC_ORDER_FIRST)
39         {
40                 thiscb.cbc_next = cb.cbc_next;
41                 cb.cbc_next = thiscb;
42         }
43         else if(order & CBC_ORDER_LAST)
44         {
45                 for(e = cb; e.cbc_next; e = e.cbc_next);
46                 e.cbc_next = thiscb;
47         }
48         else
49         {
50                 // by default we execute last, but before a possible CBC_ORDER_LAST callback
51                 for(e = cb; e.cbc_next && !(e.cbc_next.cbc_order & CBC_ORDER_LAST); e = e.cbc_next); // we must make sure that we insert BEFORE an CBC_ORDER_LAST mutator!
52                 thiscb.cbc_next = e.cbc_next;
53                 e.cbc_next = thiscb;
54         }
55         cb.cbc_order |= (order | CBC_ORDER_ANY);
56         return 1;
57 }
58
59 float CallbackChain_Remove(entity cb, float() func)
60 {
61         float order;
62         entity e;
63         float n;
64         n = 0;
65         order = 0;
66         for(e = cb; e.cbc_next; e = e.cbc_next)
67         {
68                 while(e.cbc_next.cbc_func == func)
69                 {
70                         // remove e.cbc_next from the chain
71                         entity e2;
72                         e2 = e.cbc_next.cbc_next;
73                         remove(e.cbc_next);
74                         e.cbc_next = e2;
75                         ++n;
76                 }
77                 // e.cbc_next is now something we want to keep
78                 order |= (e.cbc_next.cbc_order & CBC_ORDER_ANY);
79         }
80         cb.cbc_order = order;
81         return n;
82 }
83
84 float CallbackChain_Call(entity cb)
85 {
86         float r;
87         entity e;
88         r = 0;
89         for(e = cb; e.cbc_next; e = e.cbc_next)
90         {
91                 CallbackChain_ReturnValue = r;
92                 r |= e.cbc_next.cbc_func();
93         }
94         return r; // callbacks return an error status, so 0 is default return value
95 }
96
97 const float MAX_MUTATORS = 15;
98 string loaded_mutators[MAX_MUTATORS];
99 float Mutator_Add(mutatorfunc_t func, string name)
100 {
101         int i, j;
102         j = -1;
103         for(i = 0; i < MAX_MUTATORS; ++i)
104         {
105                 if(name == loaded_mutators[i])
106                         return 1; // already added
107                 if (!(loaded_mutators[i]))
108                         j = i;
109         }
110         if(j < 0)
111         {
112                 backtrace("WARNING: too many mutators, cannot add any more\n");
113                 return 0;
114         }
115         loaded_mutators[j] = name;
116
117         if(func(MUTATOR_ADDING) == 0)
118         {
119                 // good
120                 return 1;
121         }
122
123         backtrace("WARNING: when adding mutator: adding failed, rolling back\n");
124
125         if(func(MUTATOR_ROLLING_BACK) != 0)
126         {
127                 // baaaaad
128                 error("WARNING: when adding mutator: rolling back failed");
129         }
130         return 0;
131 }
132 void Mutator_Remove(float(float) func, string name)
133 {
134         int i;
135         for(i = 0; i < MAX_MUTATORS; ++i)
136                 if(name == loaded_mutators[i])
137                         break;
138         if(i >= MAX_MUTATORS)
139         {
140                 backtrace("WARNING: removing not-added mutator\n");
141                 return;
142         }
143         loaded_mutators[i] = string_null;
144
145         if(func(MUTATOR_REMOVING) != 0)
146         {
147                 // baaaaad
148                 error("Mutator_Remove: removing mutator failed");
149         }
150 }