]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
spawnfuncs: defer spawning until we say so
authorTimePath <andrew.hardaker1995@gmail.com>
Mon, 28 Aug 2017 12:12:35 +0000 (22:12 +1000)
committerTimePath <andrew.hardaker1995@gmail.com>
Mon, 28 Aug 2017 12:12:35 +0000 (22:12 +1000)
qcsrc/lib/_all.inc
qcsrc/lib/spawnfunc.qh
qcsrc/server/g_world.qc

index 4da78f1444eb27b397d926442c7a153012adf01e..6e93c5af36c4db32060301c3eb64ad911f9bf011 100644 (file)
@@ -182,7 +182,17 @@ void make_safe_for_remove(entity this);
        #define SV_Shutdown _SV_Shutdown
 
        void _StartFrame();
-       void StartFrame() { if (_StartFrame) _StartFrame(); }
+       bool _StartFrame_init;
+       void spawnfunc_worldspawn(entity);
+       void StartFrame() {
+               if (!_StartFrame_init) {
+                       _StartFrame_init = true;
+                       float oldtime = time; time = 1;
+                       __spawnfunc_expecting = 2; spawnfunc_worldspawn(NULL);
+                       time = oldtime;
+        }
+        if (_StartFrame) _StartFrame();
+       }
        #define StartFrame _StartFrame
 
        void _SetNewParms();
index e0605c93840599e8f928f359ce1f6b02cccd7016..34b10830413af229cb45970d272d749858dd80bb 100644 (file)
@@ -27,34 +27,36 @@ noref bool require_spawnfunc_prefix;
        #define _spawnfunc_check(fld) \
                if (fieldname == #fld) continue;
 
-       noref bool __spawnfunc_expecting;
+       noref int __spawnfunc_expecting;
        noref entity __spawnfunc_expect;
        noref bool __spawnfunc_unreachable_workaround = true;
 
+    .void(entity) __spawnfunc_spawn;
+    noref IntrusiveList g_spawn_queue;
+
        #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_expecting) \
-                       { \
+                   bool dospawn = true; \
+                   if (__spawnfunc_expecting > 1) { __spawnfunc_expecting = false; } \
+                       else if (__spawnfunc_expecting) { \
                                /* engine call */ \
+                if (!g_spawn_queue) { g_spawn_queue = IL_NEW(); } \
                                __spawnfunc_expecting = false; \
                                this = __spawnfunc_expect; \
                                __spawnfunc_expect = NULL; \
-                       } \
-                       else \
-                       { \
+                dospawn = false; \
+                       } else { \
+                           /* userland call */ \
                                assert(this); \
                        } \
-                       if (!this.sourceLoc) \
-                       { \
+                       if (!this.sourceLoc) { \
                                this.sourceLoc = __FILE__ ":" STR(__LINE__); \
                        } \
-                       if (!this.spawnfunc_checked) \
-                       { \
-                               for (int i = 0, n = numentityfields(); i < n; ++i) \
-                               { \
+                       if (!this.spawnfunc_checked) { \
+                               for (int i = 0, n = numentityfields(); i < n; ++i) { \
                                        string value = getentityfieldstring(i, this); \
                                        string fieldname = entityfieldname(i); \
                                        whitelist(_spawnfunc_checktypes) \
@@ -65,8 +67,13 @@ noref bool require_spawnfunc_prefix;
                                        LOG_WARNF(_("Entity field %s.%s (%s) is not whitelisted. If you believe this is an error, please file an issue."), #id, fieldname, value); \
                                } \
                                this.spawnfunc_checked = true; \
+                               if (this) { \
+                    /* not worldspawn, delay spawn */ \
+                    this.__spawnfunc_spawn = spawnfunc_##id; \
+                    IL_PUSH(g_spawn_queue, this); \
+                } \
                        } \
-                       __spawnfunc_##id(this); \
+                       if (dospawn) { __spawnfunc_##id(this); } \
                        if (__spawnfunc_unreachable_workaround) return; \
                } \
                void __spawnfunc_##id(entity this)
index 66612e0dbe992abe9accf592e2a49c40c31733a0..dfad188fa55dc1c6f0fb55c7c9ea7e4c456cb5b5 100644 (file)
@@ -949,6 +949,10 @@ spawnfunc(worldspawn)
        WinningConditionHelper(this); // set worldstatus
 
        world_initialized = 1;
+
+       IL_EACH(g_spawn_queue, true, {
+        it.__spawnfunc_spawn(it);
+    });
 }
 
 spawnfunc(light)