From 6d889f8c85220c49070e9f857c90e35f0528ac74 Mon Sep 17 00:00:00 2001 From: bones_was_here Date: Thu, 10 Sep 2020 03:34:46 +1000 Subject: [PATCH] Add function to access "raw" map entity field values in engines with __fullspawndata support --- qcsrc/lib/spawnfunc.qh | 7 +++++ qcsrc/server/miscfunctions.qc | 56 +++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/qcsrc/lib/spawnfunc.qh b/qcsrc/lib/spawnfunc.qh index 7130703ec..bed384ec6 100644 --- a/qcsrc/lib/spawnfunc.qh +++ b/qcsrc/lib/spawnfunc.qh @@ -7,6 +7,8 @@ noref bool require_spawnfunc_prefix; .bool spawnfunc_checked; +.string fullspawndata; + // Optional type checking; increases compile time too much to be enabled by default #if 0 bool entityfieldassignablefromeditor(int i) @@ -282,6 +284,11 @@ noref bool __spawnfunc_first; } \ 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 */ \ diff --git a/qcsrc/server/miscfunctions.qc b/qcsrc/server/miscfunctions.qc index e8b4ab681..c74637c07 100644 --- a/qcsrc/server/miscfunctions.qc +++ b/qcsrc/server/miscfunctions.qc @@ -1446,3 +1446,59 @@ bool isPushable(entity e) return true; return false; } + +string GetField_fullspawndata(entity e, string f, ...) +/* Retrieves the value of a map entity field from fullspawndata + * This bypasses field value changes made by the engine, + * eg string-to-float and escape sequence substitution. + * + * Avoids the need to declare fields just to read them once :) + * + * Returns the last instance of the field to match DarkPlaces behaviour. + * Path support: converts \ to / and tests the file if a third (bool, true) arg is passed. + * Returns string_null if the entity does not have the field, or the file is not in the VFS. + * + * FIXME: entities with //comments are not supported. + */ +{ + string v = string_null; + + if (!e.fullspawndata) + { + LOG_WARNF("^1EDICT %s (classname %s) has no fullspawndata, engine lacks support?", ftos(num_for_edict(e)), e.classname); + return v; + } + + if (strstrofs(e.fullspawndata, "//", 0) >= 0) + { + // tokenize and tokenize_console return early if "//" is reached, + // which can leave an odd number of tokens and break key:value pairing. + LOG_WARNF("^1EDICT %s fullspawndata contains unsupported //comment^7%s", ftos(num_for_edict(e)), e.fullspawndata); + return v; + } + + //print(sprintf("%s(EDICT %s, FIELD %s)\n", __FUNC__, ftos(num_for_edict(e)), f)); + //print(strcat("FULLSPAWNDATA:", e.fullspawndata, "\n")); + + // tokenize treats \ as an escape, but tokenize_console returns the required literal + for (int t = tokenize_console(e.fullspawndata) - 3; t > 0; t -= 2) + { + //print(sprintf("\tTOKEN %s:%s\t%s:%s\n", ftos(t), ftos(t + 1), argv(t), argv(t + 1))); + if (argv(t) == f) + { + v = argv(t + 1); + break; + } + } + + //print(strcat("RESULT: ", v, "\n\n")); + + if (v && ...(0, bool) == true) + { + v = strreplace("\\", "/", v); + if (whichpack(v) == "") + return string_null; + } + + return v; +} -- 2.39.2