]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Fix initialization of maxclients
authorTimePath <andrew.hardaker1995@gmail.com>
Wed, 6 Sep 2017 10:41:59 +0000 (20:41 +1000)
committerTimePath <andrew.hardaker1995@gmail.com>
Wed, 6 Sep 2017 10:41:59 +0000 (20:41 +1000)
Closes #1948

qcsrc/client/main.qc
qcsrc/lib/net.qh
qcsrc/lib/registry.qh
qcsrc/lib/spawnfunc.qh
qcsrc/lib/static.qh
qcsrc/server/g_world.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/utils.qh

index ae624ef85c88c1a7c2b6a09d0fb7617629cfb089..374096f241695ef23c56c59d55a72bec8cb434a1 100644 (file)
@@ -609,21 +609,23 @@ NET_HANDLE(ENT_CLIENT_NAGGER, bool isnew)
 NET_HANDLE(ENT_CLIENT_ELIMINATEDPLAYERS, bool isnew)
 {
        make_pure(this);
-    int i, j, b, f;
-
-    int sf = ReadByte();
-       if(sf & 1)
-       {
-               for(j = 0; j < maxclients; ++j)
-                       if(playerslots[j])
-                               playerslots[j].eliminated = 1;
-               for(i = 1; i <= maxclients; i += 8)
-               {
-                       f = ReadByte();
-                       for(j = i-1, b = 1; b < 256; b *= 2, ++j)
-                               if (!(f & b))
-                                       if(playerslots[j])
-                                               playerslots[j].eliminated = 0;
+    int sf; serialize(byte, 0, sf);
+       if (sf & 1) {
+               for (int j = 0; j < maxclients; ++j) {
+                       if (playerslots[j]) {
+                           playerslots[j].eliminated = 1;
+                       }
+        }
+               for (int i = 1; i <= maxclients; i += 8) {
+                       int f = 0;
+                       serialize(byte, 0, f);
+                       for (int b = 0; b < 8; ++b) {
+                               if (f & BIT(b)) continue;
+                int j = i - 1 + b;
+                if (playerslots[j]) {
+                    playerslots[j].eliminated = 0;
+                }
+            }
                }
        }
        return true;
index 0a3dd8c662a8ac8e1f91e26ab820b8cbe658f842..b1f5326a9bb5a441b5094de347cfe973086d5bd6 100644 (file)
@@ -4,19 +4,30 @@
 #include "sort.qh"
 #include "yenc.qh"
 
+// netcode mismatch and not sure what caused it? developer_csqcentities 1
+
 .string netname;
 .int m_id;
 .bool(entity this, entity sender, bool isNew) m_read;
 #define NET_HANDLE(id, param) bool Net_Handle_##id(entity this, entity sender, param)
 
+#define NET_GUARD(id) \
+    bool Net_Handle_##id##_guard(entity this, entity sender, bool isNew) { \
+        bool valid = false; \
+        serialize_marker(to, valid); \
+        if (!valid) LOG_FATALF("Last message not fully parsed: %s", _net_prevmsgstr); \
+        _net_prevmsgstr = #id; \
+        return Net_Handle_##id(this, sender, isNew); \
+    }
 
 #ifdef CSQC
+string _net_prevmsgstr;
        #define REGISTER_NET_TEMP(id) \
                NET_HANDLE(id, bool); \
-               REGISTER(TempEntities, NET, id, m_id, new_pure(net_temp_packet)) \
-               { \
+        NET_GUARD(id); \
+               REGISTER(TempEntities, NET, id, m_id, new_pure(net_temp_packet)) { \
                        this.netname = #id; \
-                       this.m_read = Net_Handle_##id; \
+                       this.m_read = Net_Handle_##id##_guard; \
                }
 #else
        #define REGISTER_NET_TEMP(id) \
@@ -45,10 +56,11 @@ STATIC_INIT(RegisterTempEntities_renumber) { FOREACH(TempEntities, true, it.m_id
                        this.sourceLoc = __FILE__ ":" STR(__LINE__); \
                        if (!this) isnew = true; \
                } \
+               NET_GUARD(id); \
                REGISTER(LinkedEntities, NET, id, m_id, new_pure(net_linked_packet)) \
                { \
                        this.netname = #id; \
-                       this.m_read = Net_Handle_##id; \
+                       this.m_read = Net_Handle_##id##_guard; \
                }
 #else
        #define REGISTER_NET_LINKED(id) \
@@ -205,6 +217,7 @@ STATIC_INIT(C2S_Protocol_renumber) { FOREACH(C2S_Protocol, true, it.m_id = i); }
                MACRO_BEGIN { \
                        if (NET_##id##_istemp) WriteByte(to, SVC_TEMPENTITY); \
                        WriteByte(to, NET_##id.m_id); \
+                       bool _net_valid = false; serialize_marker(to, _net_valid); \
                } MACRO_END
 #endif
 
@@ -219,7 +232,11 @@ USING(Stream, int);
        #define stream_writing(stream) false
 #endif
 
-#define serialize(T, stream, ...) serialize_##T(stream, __VA_ARGS__)
+#define serialize(T, stream, ...) \
+MACRO_BEGIN \
+    noref Stream _stream = stream; \
+    serialize_##T(_stream, __VA_ARGS__); \
+MACRO_END
 
 #if defined(SVQC)
        #define serialize_byte(stream, this) \
@@ -246,13 +263,27 @@ USING(Stream, int);
 #endif
 
 #define serialize_vector(stream, this) \
-    MACRO_BEGIN \
+MACRO_BEGIN \
     vector _v = this; \
     serialize_float(stream, _v.x); \
     serialize_float(stream, _v.y); \
     serialize_float(stream, _v.z); \
     this = _v; \
-    MACRO_END
+MACRO_END
+
+#define serialize_marker(stream, this) \
+MACRO_BEGIN \
+    if (NDEBUG) { \
+        this = true; \
+    } else { \
+        int _de = 0xDE, _ad = 0xAD, _be = 0xBE, _ef = 0xEF; \
+        serialize_byte(stream, _de); \
+        serialize_byte(stream, _ad); \
+        serialize_byte(stream, _be); \
+        serialize_byte(stream, _ef); \
+        this = (_de == 0xDE && _ad == 0xAD && _be == 0xBE && _ef == 0xEF); \
+    } \
+MACRO_END
 
 // serialization: old
 
index 8ca07b43f3d34ecaa83e63b1810f415e26ad47a6..2d41e5d431b3ba9c7b63ccbb87268a4b96615267 100644 (file)
@@ -187,7 +187,7 @@ void Registry_send(string id, string hash);
 #define EVAL_REGISTER_REGISTRY(...) __VA_ARGS__
 #define REGISTER_REGISTRY_1(id) REGISTER_REGISTRY_2(id, #id)
 #define REGISTER_REGISTRY_2(id, str) \
-       ACCUMULATE_FUNCTION(__static_init, Register##id) \
+       ACCUMULATE_FUNCTION(__static_init_1, Register##id) \
        CLASS(id##Registry, Object) \
                ATTRIB(id##Registry, m_name, string, str); \
                ATTRIB(id##Registry, REGISTRY_NEXT, entity, id##_first); \
index e30e565fd3259a6916d36d5c230d7165bae4dd1c..4638bca2d490544d8881d0e1507cfe048c7f7607 100644 (file)
@@ -69,11 +69,17 @@ noref bool require_spawnfunc_prefix;
         e.__spawnfunc_constructor(e);
     }
 
+       noref bool __spawnfunc_first;
+
        #define spawnfunc_1(id) spawnfunc_2(id, FIELDS_UNION)
        #define spawnfunc_2(id, whitelist) \
                void __spawnfunc_##id(entity this); \
                [[accumulate]] void spawnfunc_##id(entity this) \
                { \
+                   if (!__spawnfunc_first) { \
+                __spawnfunc_first = true; \
+                static_init_early(); \
+                   } \
                    bool dospawn = true; \
                    if (__spawnfunc_expecting > 1) { __spawnfunc_expecting = false; } \
                        else if (__spawnfunc_expecting) { \
index e2c5fd4f0048d90ccbbd719fdbcf12b310bb5fe8..6f511fcecfa1c9c1f2ef842ad5fe47ac44fbd7ef 100644 (file)
@@ -1,14 +1,5 @@
 #pragma once
 
-void __static_init() {}
-#define static_init() CALL_ACCUMULATED_FUNCTION(__static_init)
-void __static_init_late() {}
-#define static_init_late() CALL_ACCUMULATED_FUNCTION(__static_init_late)
-void __static_init_precache() {}
-#define static_init_precache() CALL_ACCUMULATED_FUNCTION(__static_init_precache)
-void __shutdown() {}
-#define shutdownhooks() CALL_ACCUMULATED_FUNCTION(__shutdown)
-
 #define GETTIME_REALTIME 1
 #ifdef MENUQC
 float(int tmr) _gettime = #67;
@@ -25,12 +16,34 @@ void profile(string s)
        LOG_TRACEF("[%f] %s", rt - g_starttime, s);
 }
 
-#define _STATIC_INIT(where, func) \
+#define _STATIC_INIT(func, where) \
        [[accumulate]] void _static_##func() { profile(#func); } \
        ACCUMULATE_FUNCTION(where, _static_##func) \
        void _static_##func()
 
-#define STATIC_INIT(func) _STATIC_INIT(__static_init,           func)
-#define STATIC_INIT_LATE(func) _STATIC_INIT(__static_init_late, func##_late)
-#define PRECACHE(func) _STATIC_INIT(__static_init_precache,     func##_precache)
-#define SHUTDOWN(func) _STATIC_INIT(__shutdown,                        func##_shutdown)
+/** before worldspawn */
+#define STATIC_INIT_EARLY(func) _STATIC_INIT(func##_0,    __static_init_0)
+#define static_init_early()     CALL_ACCUMULATED_FUNCTION(__static_init_0)
+void __static_init_0() {}
+
+/** during worldspawn */
+#define STATIC_INIT(func)       _STATIC_INIT(func##_1,    __static_init_1)
+#define static_init()           CALL_ACCUMULATED_FUNCTION(__static_init_1)
+void __static_init_1() {}
+
+/** directly after STATIC_INIT */
+#define STATIC_INIT_LATE(func)  _STATIC_INIT(func##_2,    __static_init_2)
+#define static_init_late()      CALL_ACCUMULATED_FUNCTION(__static_init_2)
+void __static_init_2() {}
+
+/** directly after STATIC_INIT_LATE */
+#define PRECACHE(func)          _STATIC_INIT(func##_3,    __static_init_3)
+#define static_init_precache()  CALL_ACCUMULATED_FUNCTION(__static_init_3)
+void __static_init_3() {}
+
+/* other map entities spawn now */
+
+/** before shutdown */
+#define SHUTDOWN(func)          _STATIC_INIT(func##_shutdown, __shutdown)
+#define shutdownhooks()         CALL_ACCUMULATED_FUNCTION(    __shutdown)
+void __shutdown() {}
index c47952c5d99f0c83231c5916c6f47e0fcfb13183..ce25dfa522772b08e3f1dfb41dcc2a536a2f4902 100644 (file)
@@ -580,7 +580,15 @@ spawnfunc(__init_dedicated_server)
 
        e = new(info_player_deathmatch);  // safeguard against player joining
 
-       this.classname = "worldspawn"; // safeguard against various stuff ;)
+    // assign reflectively to avoid "assignment to world" warning
+    for (int i = 0, n = numentityfields(); i < n; ++i) {
+        string k = entityfieldname(i);
+        if (k == "classname") {
+            // safeguard against various stuff ;)
+            putentityfieldstring(i, this, "worldspawn");
+            break;
+        }
+    }
 
        // needs to be done so early because of the constants they create
        static_init();
@@ -597,6 +605,14 @@ void __init_dedicated_server_shutdown() {
        MapInfo_Shutdown();
 }
 
+STATIC_INIT_EARLY(maxclients)
+{
+       maxclients = 0;
+       for (entity head = nextent(NULL); head; head = nextent(head)) {
+               ++maxclients;
+       }
+}
+
 void Map_MarkAsRecent(string m);
 float world_already_spawned;
 void Nagger_Init();
@@ -680,12 +696,6 @@ spawnfunc(worldspawn)
 
        cvar_changes_init(); // do this very early now so it REALLY matches the server config
 
-       maxclients = 0;
-       for (entity head = nextent(NULL); head; head = nextent(head))
-       {
-               ++maxclients;
-       }
-
        // needs to be done so early because of the constants they create
        static_init();
 
index 7bb8e922d5902a7f03ac9c67b0da27284eb17f12..1b631c4b77668f3533b7f88b94c434d3999d825f 100644 (file)
@@ -933,24 +933,21 @@ void InitializeEntitiesRun()
 .float(entity) isEliminated;
 bool EliminatedPlayers_SendEntity(entity this, entity to, float sendflags)
 {
-       float i, f, b;
-       entity e;
-       WriteHeader(MSG_ENTITY, ENT_CLIENT_ELIMINATEDPLAYERS);
-       WriteByte(MSG_ENTITY, sendflags);
-
-       if(sendflags & 1)
-       {
-               for(i = 1; i <= maxclients; i += 8)
-               {
-                       for(f = 0, e = edict_num(i), b = 1; b < 256; b *= 2, e = nextent(e))
-                       {
-                               if(eliminatedPlayers.isEliminated(e))
-                                       f |= b;
+       Stream out = MSG_ENTITY;
+       WriteHeader(out, ENT_CLIENT_ELIMINATEDPLAYERS);
+       serialize(byte, out, sendflags);
+       if (sendflags & 1) {
+               for (int i = 1; i <= maxclients; i += 8) {
+                   int f = 0;
+            entity e = edict_num(i);
+                       for (int b = 0; b < 8; ++b, e = nextent(e)) {
+                               if (eliminatedPlayers.isEliminated(e)) {
+                                       f |= BIT(b);
+                               }
                        }
-                       WriteByte(MSG_ENTITY, f);
+                       serialize(byte, out, f);
                }
        }
-
        return true;
 }
 
index da5c7a56a7483839793114dd03e540615351e510..4a603c02256d244dd69fca54040a80b9f4faeed1 100644 (file)
@@ -41,7 +41,7 @@ const string STR_OBSERVER = "observer";
                } \
        } MACRO_END
 
-#define FOREACH_CLIENT(cond, body) FOREACH_CLIENTSLOT(IS_CLIENT(it) && (cond), body)
+#define FOREACH_CLIENT(cond, body) FOREACH_CLIENTSLOT(IS_CLIENT(it) && (cond), LAMBDA(body))
 
 // using the "inside out" version of knuth-fisher-yates shuffle
 // https://en.wikipedia.org/wiki/Fisher–Yates_shuffle