+ERASEABLE
+void _checkWhitelisted(entity this, string id)
+{
+ for (int i = 0, n = numentityfields(); i < n; ++i)
+ {
+ string value = getentityfieldstring(i, this);
+ string s = entityfieldname(i);
+ FIELDS_UNION(_spawnfunc_checktypes)
+ if (value == "") continue;
+ if (s == "") continue;
+ FIELDS_COMMON(_spawnfunc_check)
+ FIELDS_UNION(_spawnfunc_check)
+ LOG_WARNF(_("Entity field %s.%s (%s) is not whitelisted. If you believe this is an error, please file an issue."), id, s, value);
+ }
+}
+
+// this function simply avoids expanding IL_NEW during compilation
+// for each spawning entity
+void g_spawn_queue_spawn() { g_spawn_queue = IL_NEW(); }
+
+noref bool __spawnfunc_first;
+
+#define spawnfunc(id) \
+ 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 = 0; } \
+ else if (__spawnfunc_expecting) { \
+ /* engine call */ \
+ if (!g_spawn_queue) g_spawn_queue_spawn(); \
+ __spawnfunc_expecting = 0; \
+ this = __spawnfunc_expect; \
+ __spawnfunc_expect = NULL; \
+ dospawn = false; \
+ } else { \
+ /* userland call */ \
+ assert(this); \
+ } \
+ if (!this.sourceLoc) { \
+ this.sourceLoc = __FILE__":"STR(__LINE__); \
+ } \
+ this.classname = #id; \
+ if (!this.spawnfunc_checked) { \
+ _checkWhitelisted(this, #id); \
+ if (__fullspawndata) { \
+ /* not supported in old DP */ \
+ /* must be read inside the real spawnfunc */ \
+ this.fullspawndata = __fullspawndata; \
+ } \
+ this.spawnfunc_checked = true; \
+ if (this) { \
+ /* not worldspawn, delay spawn */ \
+ /* clear some dangerous fields (TODO: properly support these in the map!) */ \
+ this.think = func_null; \
+ this.nextthink = 0; \
+ __spawnfunc_defer(this, __spawnfunc_##id); \
+ } else { \
+ /* world might not be "worldspawn" */ \
+ this.__spawnfunc_constructor = __spawnfunc_##id; \
+ } \
+ } \
+ if (dospawn) { __spawnfunc_##id(this); } \
+ if (__spawnfunc_unreachable_workaround) return; \
+ } \
+ void __spawnfunc_##id(entity this)
+
+#endif