]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/sv_main.qc
Merge branch 'master' into Lyberta/URS3
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / sv_main.qc
index 87430a93eff4502037e10c52e8dd511f820e1852..68e7b375b507a09051f3607114f60d14cd9da0f2 100644 (file)
@@ -247,6 +247,77 @@ void StartFrame()
 .string gametypefilter;
 .string cvarfilter;
 bool DoesQ3ARemoveThisEntity(entity this);
+
+/**
+ * Evaluate an expression of the form: [+ | -]? [var[op]val | [op]var | val | var] ...
+ * +: all must match. this is the default
+ * -: one must NOT match
+ *
+ * var>x
+ * var<x
+ * var>=x
+ * var<=x
+ * var==x
+ * var!=x
+ * var===x
+ * var!==x
+ */
+bool expr_evaluate(string s)
+{
+    bool ret = false;
+    if (str2chr(s, 0) == '+') {
+        s = substring(s, 1, -1);
+    } else if (str2chr(s, 0) == '-') {
+        ret = true;
+        s = substring(s, 1, -1);
+    }
+    bool expr_fail = false;
+    for (int i = 0, n = tokenize_console(s); i < n; ++i) {
+        int o;
+        string k, v;
+        s = argv(i);
+        #define X(expr) \
+            if (expr) { \
+                continue; \
+            } else { \
+                expr_fail = true; \
+                break; \
+            }
+        #define BINOP(op, len, expr) \
+            if ((o = strstrofs(s, op, 0)) >= 0) { \
+                k = substring(s, 0, o); \
+                v = substring(s, o + len, -1); \
+                X(expr); \
+            }
+        BINOP(">=", 2, cvar(k) >= stof(v));
+        BINOP("<=", 2, cvar(k) <= stof(v));
+        BINOP(">",  1, cvar(k) >  stof(v));
+        BINOP("<",  1, cvar(k) <  stof(v));
+        BINOP("==", 2, cvar(k) == stof(v));
+        BINOP("!=", 2, cvar(k) != stof(v));
+        BINOP("===", 3, cvar_string(k) == v);
+        BINOP("!==", 3, cvar_string(k) != v);
+        {
+            k = s;
+            bool b = true;
+            if (str2chr(k, 0) == '!') {
+                k = substring(s, 1, -1);
+                b = false;
+            }
+            float f = stof(k);
+            bool isnum = ftos(f) == k;
+            X(boolean(isnum ? f : cvar(k)) == b);
+        }
+        #undef BINOP
+        #undef X
+    }
+    if (!expr_fail) {
+        ret = !ret;
+    }
+    // now ret is true if we want to keep the item, and false if we want to get rid of it
+    return ret;
+}
+
 void SV_OnEntityPreSpawnFunction(entity this)
 {
        __spawnfunc_expecting = true;
@@ -257,65 +328,8 @@ void SV_OnEntityPreSpawnFunction(entity this)
        {
                goto cleanup;
        }
-       if (this.cvarfilter != "") {
-               bool inv = false;
-
-               string s = this.cvarfilter;
-               if (str2chr(s, 0) == '+') {
-                       s = substring(s, 1, -1);
-               } else if(str2chr(s, 0) == '-') {
-                       inv = true;
-                       s = substring(s, 1, -1);
-               }
-
-        bool cvar_fail = false;
-               for (int i = 0, n = tokenize_console(s); i < n; ++i) {
-                   int o;
-            string k, v;
-                       s = argv(i);
-                       // syntax:
-                       // var>x
-                       // var<x
-                       // var>=x
-                       // var<=x
-                       // var==x
-                       // var!=x
-                       // var===x
-                       // var!==x
-                       #define X(expr) \
-                           if (expr) { \
-                    continue; \
-                } else { \
-                    cvar_fail = true; \
-                    break; \
-                }
-                       #define BINOP(op, len, expr) \
-                           if ((o = strstrofs(s, op, 0)) >= 0) { \
-                    k = substring(s, 0, o); \
-                    v = substring(s, o + len, -1); \
-                    X(expr); \
-                }
-            BINOP(">=", 2, cvar(k) >= stof(v));
-            BINOP("<=", 2, cvar(k) <= stof(v));
-            BINOP(">",  1, cvar(k) >  stof(v));
-            BINOP("<",  1, cvar(k) <  stof(v));
-            BINOP("==", 2, cvar(k) == stof(v));
-            BINOP("!=", 2, cvar(k) != stof(v));
-            // fixme: did these two ever work?
-            BINOP("===", 2, cvar_string(k) == v);
-            BINOP("!==", 2, cvar_string(k) != v);
-            if (str2chr(s, 0) == '!') { k = substring(s, 1, -1); X(!cvar(k)); }
-            { k = s; X(cvar(k)); }
-                       #undef BINOP
-                       #undef X
-               }
-               if (!cvar_fail) {
-                   inv = !inv;
-               }
-               // now inv is true if we want to keep the item, and false if we want to get rid of it
-               if (!inv) {
-                       goto cleanup;
-               }
+       if (this.cvarfilter != "" && !expr_evaluate(this.cvarfilter)) {
+        goto cleanup;
        }
 
        if (DoesQ3ARemoveThisEntity(this)) {