From 70acd5b6d2cda9c04c3d4958f41abcf9ecd73b55 Mon Sep 17 00:00:00 2001 From: TimePath Date: Mon, 28 Aug 2017 22:12:35 +1000 Subject: [PATCH] spawnfuncs: defer spawning until we say so --- qcsrc/lib/_all.inc | 12 +++++++++++- qcsrc/lib/spawnfunc.qh | 33 ++++++++++++++++++++------------- qcsrc/server/g_world.qc | 4 ++++ 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/qcsrc/lib/_all.inc b/qcsrc/lib/_all.inc index 4da78f144..6e93c5af3 100644 --- a/qcsrc/lib/_all.inc +++ b/qcsrc/lib/_all.inc @@ -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(); diff --git a/qcsrc/lib/spawnfunc.qh b/qcsrc/lib/spawnfunc.qh index e0605c938..34b108304 100644 --- a/qcsrc/lib/spawnfunc.qh +++ b/qcsrc/lib/spawnfunc.qh @@ -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) diff --git a/qcsrc/server/g_world.qc b/qcsrc/server/g_world.qc index 64aa03b50..e55bd72e9 100644 --- a/qcsrc/server/g_world.qc +++ b/qcsrc/server/g_world.qc @@ -936,6 +936,10 @@ spawnfunc(worldspawn) WinningConditionHelper(this); // set worldstatus world_initialized = 1; + + IL_EACH(g_spawn_queue, true, { + it.__spawnfunc_spawn(it); + }); } spawnfunc(light) -- 2.39.2