From: TimePath Date: Mon, 28 Aug 2017 12:12:35 +0000 (+1000) Subject: spawnfuncs: defer spawning until we say so X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=cd4f8f12a9a7eafce38dd21b03b5c4bc1b00f9de;p=xonotic%2Fxonotic-data.pk3dir.git spawnfuncs: defer spawning until we say so --- 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 66612e0db..dfad188fa 100644 --- a/qcsrc/server/g_world.qc +++ b/qcsrc/server/g_world.qc @@ -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)