#include <client/shownames.qh>
#include <client/view.qh>
#include <client/weapons/projectile.qh>
+#include <common/checkextension.qh>
#include <common/deathtypes/all.qh>
#include <common/effects/all.inc>
#include <common/effects/all.qh>
LOG_TRACEF("^4CSQC Build information: ^1%s", WATERMARK);
#endif
+ CheckEngineExtensions();
+
{
int i = 0;
for ( ; i < 255; ++i)
noref float autocvar_net_connecttimeout = 30;
+#include "checkextension.qc"
+
#ifdef GAMEQC
#include "anim.qc"
#include "animdecide.qc"
--- /dev/null
+#include "checkextension.qh"
+
+#ifdef GAMEQC
+entity findbox_tofield_Fallback(vector mins, vector maxs, .entity tofield)
+{
+ // 0.03125 minimum radius because findradius returns no results if radius is zero
+ // but findbox for a zero-sized box returns entities touching the specified point
+ entity chain = findradius_tofield(0.5 * (mins + maxs), max(0.03125, 0.5 * vlen(maxs - mins)), tofield);
+ entity prev = NULL;
+ for (entity e = chain; e; e = e.tofield)
+ {
+ if (boxesoverlap(e.absmin, e.absmax, mins, maxs))
+ prev = e;
+ else // not in box so remove from chain
+ {
+ if (prev)
+ prev.tofield = e.tofield;
+ else
+ chain = chain.tofield;
+ }
+ }
+ return chain;
+}
+entity findbox_Fallback(vector mins, vector maxs)
+{
+ return findbox_tofield_Fallback(mins, maxs, chain);
+}
+#endif // GAMEQC
+
+void CheckEngineExtensions(void)
+{
+ if (!cvar("pr_checkextension"))
+ LOG_FATAL("Engine lacks the QC extension system.");
+
+ if (!checkextension("DP_QC_URI_GET") || !checkextension("DP_QC_URI_POST"))
+ LOG_WARN("Engine lacks HTTP support, XonStat and map downloads are unavailable.");
+
+ if (!checkextension("DP_CRYPTO"))
+ LOG_WARN("Engine lacks DP_CRYPTO, Player IDs (required for XonStat and CTS/CTF records) are unavailable.");
+
+#ifdef SVQC // change to GAMEQC if/when we use nudgeoutofsolid in CSQC
+ if (!checkextension("DP_QC_NUDGEOUTOFSOLID"))
+ {
+ LOG_WARN("Engine lacks DP_QC_NUDGEOUTOFSOLID, falling back to WarpZoneLib_MoveOutOfSolid().");
+ // DP_QC_NUDGEOUTOFSOLID fixes many cases WarpZoneLib_MoveOutOfSolid() can't, usually in less CPU time
+ nudgeoutofsolid = WarpZoneLib_MoveOutOfSolid;
+ }
+#endif
+
+#ifdef GAMEQC
+ if (!checkextension("DP_QC_FINDBOX"))
+ {
+ LOG_WARN("Engine lacks DP_QC_FINDBOX, performance will be suboptimal.");
+ findbox = findbox_Fallback;
+ findbox_tofield = findbox_tofield_Fallback;
+ }
+#endif
+
+ // TODO: add proper warns/errors for other extensions we depend on
+}
--- /dev/null
+#pragma once
+
+void CheckEngineExtensions(void);
#define ASSERT_LESS(name, var, const) noref int name[(const - var + 1)];
-#if defined(MENUQC)
-string(string, string...) strcat1n = #53;
-#else
-string(string, string...) strcat1n = #115;
-#endif
-
// would be nice if __FUNC__ could be concatenated at compile time
#if 0
// less work, bigger binary
- #define __SOURCELOC__ (sprintf("^7%s^9(^9"__FILE__"^7:^9"STR(__LINE__)"^7)", __FUNC__))
+ #define __SOURCELOC__ (sprintf("^7%s^9(^9"__FILE__"^7:^9"STR(__LINE__)"^7)\n", __FUNC__))
#else
- #define __SOURCELOC__ (sprintf("^7%s^9(^9%s^7:^9%s^7)", __FUNC__, __FILE__, STR(__LINE__)))
+ #define __SOURCELOC__ (sprintf("^7%s^9(^9%s^7:^9%s^7)\n", __FUNC__, __FILE__, STR(__LINE__)))
#endif
-#define _LOG_HEADER(level) "^9[::^7"PROGNAME"^9::"level"^9] ", __SOURCELOC__
-#define _LOG(f, level, s) \
+#define _LOG_HEADER(level, full) strcat("^9[::^7", PROGNAME, "^9::", level, "^9] ", ((full) ? __SOURCELOC__ : ""))
+
+#define _LOG(func_header, level, func_msg, s) \
MACRO_BEGIN \
- if (autocvar_developer > 0) f(strcat1n(_LOG_HEADER(level), "\n")); \
- f(strcat1n("^7", s, "\n")); \
+ func_header(_LOG_HEADER(level, autocvar_developer > 0)); \
+ func_msg(strcat("^7", s, "\n")); \
MACRO_END
-#define LOG_FATAL(...) _LOG_FATAL(strcat1n(__VA_ARGS__))
+#define LOG_FATAL(...) _LOG_FATAL(strcat(__VA_ARGS__))
#define LOG_FATALF(...) _LOG_FATAL(sprintf(__VA_ARGS__))
-#define _LOG_FATAL(s) _LOG(error, "^1FATAL", s)
+#define _LOG_FATAL(s) _LOG(print, "^1FATAL", error, s)
-#define LOG_SEVERE(...) _LOG_SEVERE(strcat1n(__VA_ARGS__))
+#define LOG_SEVERE(...) _LOG_SEVERE(strcat(__VA_ARGS__))
#define LOG_SEVEREF(...) _LOG_SEVERE(sprintf(__VA_ARGS__))
-#define _LOG_SEVERE(s) _LOG(backtrace, "^1SEVERE", s)
+#define _LOG_SEVERE(s) _LOG(print, "^1SEVERE", backtrace, s)
-#define LOG_WARN(...) _LOG_WARN(strcat1n(__VA_ARGS__))
+#define LOG_WARN(...) _LOG_WARN(strcat(__VA_ARGS__))
#define LOG_WARNF(...) _LOG_WARN(sprintf(__VA_ARGS__))
-#define _LOG_WARN(s) _LOG(print, "^3WARNING", s)
+#define _LOG_WARN(s) _LOG(print, "^3WARNING", print, s)
-#define LOG_INFO(...) _LOG_INFO(strcat1n(__VA_ARGS__))
+#define LOG_INFO(...) _LOG_INFO(strcat(__VA_ARGS__))
#define LOG_INFOF(...) _LOG_INFO(sprintf(__VA_ARGS__))
#define _LOG_INFO(s) \
MACRO_BEGIN \
- if (autocvar_developer > 1) dprint(strcat1n(_LOG_HEADER("^5INFO"), "\n")); \
+ if (autocvar_developer > 0) print(_LOG_HEADER("^5INFO", autocvar_developer > 1)); \
string __s = s; \
print("^7", __s); \
/* TODO: unconditionally add a newline when possible */ \
if (str2chr(__s, strlen(__s) - 1) != '\n') { print("\n"); } \
MACRO_END
-#define LOG_TRACE(...) _LOG_TRACE(strcat1n(__VA_ARGS__))
+#define LOG_TRACE(...) _LOG_TRACE(strcat(__VA_ARGS__))
#define LOG_TRACEF(...) _LOG_TRACE(sprintf(__VA_ARGS__))
-#define _LOG_TRACE(s) _LOG(dprint, "^6TRACE", s)
+#define _LOG_TRACE(s) _LOG(dprint, "^6TRACE", dprint, s)
-#define LOG_DEBUG(...) _LOG_DEBUG(strcat1n(__VA_ARGS__))
+#define LOG_DEBUG(...) _LOG_DEBUG(strcat(__VA_ARGS__))
#define LOG_DEBUGF(...) _LOG_DEBUG(sprintf(__VA_ARGS__))
-#define _LOG_DEBUG(s) _LOG(dprint2, "^2DEBUG", s)
-
-#define dprint2(msg) \
- MACRO_BEGIN \
- if (autocvar_developer > 1) dprint(msg); \
- MACRO_END
+#define _LOG_DEBUG(s) if (autocvar_developer > 1) _LOG(dprint, "^2DEBUG", dprint, s)
// same as LOG_INFO but without any debug information that bloats console output and compiled program files
-#define LOG_HELP(...) _LOG_HELP(strcat1n(__VA_ARGS__))
+#define LOG_HELP(...) _LOG_HELP(strcat(__VA_ARGS__))
#define LOG_HELPF(...) _LOG_HELP(sprintf(__VA_ARGS__))
#define _LOG_HELP(s) \
MACRO_BEGIN \
}
}
-bool WarpZoneLib_MoveOutOfSolid(entity e)
+int WarpZoneLib_MoveOutOfSolid(entity e)
{
vector o = e.origin;
traceline(o, o, MOVE_WORLDONLY, e);
if (trace_startsolid)
- return false;
+ return 0; // too stuck, giving up
tracebox(o, e.mins, e.maxs, o, MOVE_WORLDONLY, e);
if (!trace_startsolid)
- return true;
+ return -1; // wasn't stuck
vector m0 = e.mins;
vector m1 = e.maxs;
if (trace_startsolid)
{
setorigin(e, o);
- return false;
+ return 0; // can't fix
}
- return true;
+ return 1; // was stuck but is fixed now
}
#ifndef BITXOR_ASSIGN
# define BITXOR_ASSIGN(a,b) ((a) = ((a) | (b)) - ((a) & (b)))
#endif
-bool WarpZoneLib_MoveOutOfSolid(entity e);
+int WarpZoneLib_MoveOutOfSolid(entity e);
#define move_out_of_solid(e) WarpZoneLib_MoveOutOfSolid(e)
bool WarpZoneLib_ExactTrigger_Touch(entity this, entity toucher, bool touchfunc);
#pragma once
-bool WarpZoneLib_MoveOutOfSolid(entity e);
#ifdef SVQC
void WarpZoneLib_ExactTrigger_Init(entity this, bool unsetmodel);
#endif
#include "xonotic/util.qh"
+#include <common/checkextension.qh>
#include <common/items/_mod.qh>
#include <common/weapons/_all.qh>
#include <common/mapinfo.qh>
LOG_TRACEF("^4MQC Build information: ^1%s", WATERMARK);
#endif
+ CheckEngineExtensions();
+
// list all game dirs (TEST)
if (cvar("developer") > 0)
{
#include "world.qh"
+#include <common/checkextension.qh>
#include <common/constants.qh>
#include <common/deathtypes/all.qh>
#include <common/gamemodes/_mod.qh>
bool world_already_spawned;
spawnfunc(worldspawn)
{
+ CheckEngineExtensions();
+
cvar_set("_endmatch", "0");
server_is_dedicated = boolean(stof(cvar_defstring("is_dedicated")));
createdtoday "data/maps/_init.bsp" \
|| wget -nv -O data/maps/_init.bsp https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/_init/_init.bsp
+PASS=0
while read -r LINE
do
printf "%s\n" "$LINE"
- [ "$LINE" = "All tests OK" ] && PASS=1
+ printf "%s\n" "$LINE" | grep -q ".*All tests OK$" && PASS=1
done < <(${ENGINE} +developer 1 +map _init +sv_cmd runtest +wait +quit)
-test "$PASS" = "1" || { printf 'sv_cmd runtest failed!'; exit 1; }
+test "$PASS" = "1" || { printf "\033[1;31m%s\033[0m\n" "sv_cmd runtest failed!"; exit 1; }
${ENGINE} +map _init +sv_cmd dumpnotifs +wait +quit
diff notifications.cfg data/data/notifications_dump.cfg ||
printf "\033[32m%s\033[0m\n" "hashes match"
exit 0
else # red error print
- printf "\033[32m%s\033[0m\n" "expected: $EXPECT"
- printf "\033[32m%s\033[0m\n" " actual: $HASH"
- printf "\033[31m%s\033[0m\n" "!!! ERROR: HASHES DO NOT MATCH !!!"
+ printf "\033[31m%s\033[0m\n" "expected: $EXPECT"
+ printf "\033[31m%s\033[0m\n" " actual: $HASH"
+ printf "\033[1;31m%s\033[0m\n" "!!! ERROR: HASHES DO NOT MATCH !!!"
exit 1
fi