Refrain from reporting qc extensions that depend upon disabled protocol extensions.

This commit is contained in:
Shpoike 2021-03-06 06:27:31 +00:00
parent fe6f65306c
commit 074c31e414
2 changed files with 163 additions and 87 deletions

View file

@ -1067,7 +1067,7 @@ qboolean CL_CheckDownloads(void)
COM_Effectinfo_Enumerate(CL_GenerateRandomParticlePrecache); COM_Effectinfo_Enumerate(CL_GenerateRandomParticlePrecache);
cl.protocol_particles = true; cl.protocol_particles = true;
} }
else if (cl.protocol_pext2) else if (cl.protocol_pext2 || (cl.protocol_pext1&PEXT1_CSQC))
cl.protocol_particles = true; //doesn't have a pext flag of its own, but at least we know what it is. cl.protocol_particles = true; //doesn't have a pext flag of its own, but at least we know what it is.
#endif #endif
} }

View file

@ -7246,107 +7246,183 @@ static struct
{"digest_hex", PF_digest_hex, PF_digest_hex, 639, PF_digest_hex, 639, "string(string digest, string data, ...)"}, {"digest_hex", PF_digest_hex, PF_digest_hex, 639, PF_digest_hex, 639, "string(string digest, string data, ...)"},
}; };
static const char *extnames[] = qboolean PR_Can_Particles(unsigned int prot, unsigned int pext1, unsigned int pext2)
{ {
"DP_CON_SET", if (prot == PROTOCOL_VERSION_DP7)
"DP_CON_SETA", return true; //a bit different, but works
"DP_CSQC_QUERYRENDERENTITY", else if (pext2 || (pext1&PEXT1_CSQC))
"DP_EF_NOSHADOW", return true; //a bit different, but works
"DP_ENT_ALPHA", //already in quakespasm, supposedly. else
"DP_ENT_COLORMOD", return false; //sorry. don't report it as supported.
"DP_ENT_SCALE", }
"DP_ENT_TRAILEFFECTNUM", qboolean PR_Can_Ent_Alpha(unsigned int prot, unsigned int pext1, unsigned int pext2)
//"DP_GFX_QUAKE3MODELTAGS", //we support attachments but no md3/iqm/tags, so we can't really advertise this (although the builtin is complete if you ignore the lack of md3/iqms/tags) {
"DP_INPUTBUTTONS", if (prot != PROTOCOL_NETQUAKE)
"DP_QC_AUTOCVARS", //they won't update on changes return true; //most base protocols support it
"DP_QC_ASINACOSATANATAN2TAN", else if (pext2 & PEXT2_REPLACEMENTDELTAS)
"DP_QC_COPYENTITY", return true; //as does fte's extensions
"DP_QC_CRC16", else
//"DP_QC_DIGEST", return false; //sorry. don't report it as supported.
"DP_QC_CVAR_DEFSTRING", }
"DP_QC_CVAR_STRING", qboolean PR_Can_Ent_ColorMod(unsigned int prot, unsigned int pext1, unsigned int pext2)
"DP_QC_CVAR_TYPE", {
"DP_QC_EDICT_NUM", if (prot == PROTOCOL_VERSION_DP7)
"DP_QC_ENTITYDATA", return true; //dpp7 supports it
"DP_QC_ETOS", else if (pext2 & PEXT2_REPLACEMENTDELTAS)
"DP_QC_FINDCHAIN", return true; //as does fte's extensions
"DP_QC_FINDCHAINFLAGS", else
"DP_QC_FINDCHAINFLOAT", return false; //sorry. don't report it as supported.
"DP_QC_FINDFLAGS", }
"DP_QC_FINDFLOAT", qboolean PR_Can_Ent_Scale(unsigned int prot, unsigned int pext1, unsigned int pext2)
"DP_QC_GETLIGHT", {
"DP_QC_GETSURFACE", if (prot == PROTOCOL_RMQ || prot == PROTOCOL_VERSION_DP7)
"DP_QC_GETSURFACETRIANGLE", return true; //some base protocols support it
"DP_QC_GETSURFACEPOINTATTRIBUTE", else if (pext2 & PEXT2_REPLACEMENTDELTAS)
"DP_QC_MINMAXBOUND", return true; //as does fte's extensions
"DP_QC_MULTIPLETEMPSTRINGS", else
"DP_QC_RANDOMVEC", return false; //sorry. don't report it as supported.
"DP_QC_RENDER_SCENE", }
"DP_QC_SINCOSSQRTPOW", static struct
"DP_QC_SPRINTF", {
"DP_QC_STRFTIME", const char *name;
"DP_QC_STRING_CASE_FUNCTIONS", qboolean (*checkextsupported)(unsigned int prot, unsigned int pext1, unsigned int pext2);
"DP_QC_STRINGBUFFERS", } qcextensions[] =
"DP_QC_STRINGCOLORFUNCTIONS", {
"DP_QC_STRREPLACE", {"DP_CON_SET"},
"DP_QC_TOKENIZEBYSEPARATOR", {"DP_CON_SETA"},
"DP_QC_TRACEBOX", {"DP_CSQC_QUERYRENDERENTITY"},
"DP_QC_TRACETOSS", {"DP_EF_NOSHADOW"},
"DP_QC_TRACE_MOVETYPES", {"DP_ENT_ALPHA", PR_Can_Ent_Alpha}, //already in quakespasm, supposedly.
"DP_QC_URI_ESCAPE", {"DP_ENT_COLORMOD", PR_Can_Ent_ColorMod},
"DP_QC_VECTOANGLES_WITH_ROLL", {"DP_ENT_SCALE", PR_Can_Ent_Scale},
"DP_QC_VECTORVECTORS", {"DP_ENT_TRAILEFFECTNUM", PR_Can_Particles},
"DP_QC_WHICHPACK", //{"DP_GFX_QUAKE3MODELTAGS"}, //we support attachments but no md3/iqm/tags, so we can't really advertise this (although the builtin is complete if you ignore the lack of md3/iqms/tags)
"DP_VIEWZOOM", {"DP_INPUTBUTTONS"},
"DP_REGISTERCVAR", {"DP_QC_AUTOCVARS"}, //they won't update on changes
"DP_SV_BOTCLIENT", {"DP_QC_ASINACOSATANATAN2TAN"},
"DP_SV_DROPCLIENT", {"DP_QC_COPYENTITY"},
// "DP_SV_POINTPARTICLES", //can't enable this, because certain mods then assume that we're DP and all the particles break. {"DP_QC_CRC16"},
"DP_SV_POINTSOUND", //{"DP_QC_DIGEST"},
"DP_SV_PRINT", {"DP_QC_CVAR_DEFSTRING"},
"DP_SV_SETCOLOR", {"DP_QC_CVAR_STRING"},
"DP_SV_SPAWNFUNC_PREFIX", {"DP_QC_CVAR_TYPE"},
"DP_SV_WRITEUNTERMINATEDSTRING", {"DP_QC_EDICT_NUM"},
// "DP_TE_BLOOD", {"DP_QC_ENTITYDATA"},
{"DP_QC_ETOS"},
{"DP_QC_FINDCHAIN"},
{"DP_QC_FINDCHAINFLAGS"},
{"DP_QC_FINDCHAINFLOAT"},
{"DP_QC_FINDFLAGS"},
{"DP_QC_FINDFLOAT"},
{"DP_QC_GETLIGHT"},
{"DP_QC_GETSURFACE"},
{"DP_QC_GETSURFACETRIANGLE"},
{"DP_QC_GETSURFACEPOINTATTRIBUTE"},
{"DP_QC_MINMAXBOUND"},
{"DP_QC_MULTIPLETEMPSTRINGS"},
{"DP_QC_RANDOMVEC"},
{"DP_QC_RENDER_SCENE"}, //meaningful for menuqc
{"DP_QC_SINCOSSQRTPOW"},
{"DP_QC_SPRINTF"},
{"DP_QC_STRFTIME"},
{"DP_QC_STRING_CASE_FUNCTIONS"},
{"DP_QC_STRINGBUFFERS"},
{"DP_QC_STRINGCOLORFUNCTIONS"},
{"DP_QC_STRREPLACE"},
{"DP_QC_TOKENIZEBYSEPARATOR"},
{"DP_QC_TRACEBOX"},
{"DP_QC_TRACETOSS"},
{"DP_QC_TRACE_MOVETYPES"},
{"DP_QC_URI_ESCAPE"},
{"DP_QC_VECTOANGLES_WITH_ROLL"},
{"DP_QC_VECTORVECTORS"},
{"DP_QC_WHICHPACK"},
{"DP_VIEWZOOM"},
{"DP_REGISTERCVAR"},
{"DP_SV_BOTCLIENT"},
{"DP_SV_DROPCLIENT"},
// {"DP_SV_POINTPARTICLES", PR_Can_Particles}, //can't enable this, because certain mods then assume that we're DP and all the particles break.
{"DP_SV_POINTSOUND"},
{"DP_SV_PRINT"},
{"DP_SV_SETCOLOR"},
{"DP_SV_SPAWNFUNC_PREFIX"},
{"DP_SV_WRITEUNTERMINATEDSTRING"},
// {"DP_TE_BLOOD", PR_Can_Particles},
#ifdef PSET_SCRIPT #ifdef PSET_SCRIPT
"DP_TE_PARTICLERAIN", {"DP_TE_PARTICLERAIN", PR_Can_Particles},
"DP_TE_PARTICLESNOW", {"DP_TE_PARTICLESNOW", PR_Can_Particles},
#endif #endif
"DP_TE_STANDARDEFFECTBUILTINS", {"DP_TE_STANDARDEFFECTBUILTINS"},
"EXT_BITSHIFT", {"EXT_BITSHIFT"},
"FRIK_FILE", //lacks the file part, but does have the strings part. {"FRIK_FILE"}, //lacks the file part, but does have the strings part.
"FTE_CSQC_SERVERBROWSER", //callable from csqc too, for feature parity. {"FTE_CSQC_SERVERBROWSER"}, //callable from csqc too, for feature parity.
"FTE_ENT_SKIN_CONTENTS", //SOLID_BSP&&skin==CONTENTS_FOO changes CONTENTS_SOLID to CONTENTS_FOO, allowing you to swim in moving ents without qc hacks, as well as correcting view cshifts etc. {"FTE_ENT_SKIN_CONTENTS"}, //SOLID_BSP&&skin==CONTENTS_FOO changes CONTENTS_SOLID to CONTENTS_FOO, allowing you to swim in moving ents without qc hacks, as well as correcting view cshifts etc.
#ifdef PSET_SCRIPT #ifdef PSET_SCRIPT
"FTE_PART_SCRIPT", {"FTE_PART_SCRIPT"},
"FTE_PART_NAMESPACES", {"FTE_PART_NAMESPACES"},
#ifdef PSET_SCRIPT_EFFECTINFO #ifdef PSET_SCRIPT_EFFECTINFO
"FTE_PART_NAMESPACE_EFFECTINFO", {"FTE_PART_NAMESPACE_EFFECTINFO"},
#endif #endif
#endif #endif
"FTE_QC_CHECKCOMMAND", {"FTE_QC_CHECKCOMMAND"},
"FTE_QC_CROSSPRODUCT", {"FTE_QC_CROSSPRODUCT"},
"FTE_QC_HARDWARECURSORS", {"FTE_QC_HARDWARECURSORS"},
"FTE_QC_INFOKEY", {"FTE_QC_INFOKEY"},
"FTE_QC_INTCONV", {"FTE_QC_INTCONV"},
"FTE_QC_MULTICAST", {"FTE_QC_MULTICAST"},
"FTE_STRINGS", {"FTE_STRINGS"},
#ifdef PSET_SCRIPT #ifdef PSET_SCRIPT
"FTE_SV_POINTPARTICLES", {"FTE_SV_POINTPARTICLES", PR_Can_Particles},
#endif #endif
"KRIMZON_SV_PARSECLIENTCOMMAND", {"KRIMZON_SV_PARSECLIENTCOMMAND"},
"ZQ_QC_STRINGS", {"ZQ_QC_STRINGS"},
}; };
static void PF_checkextension(void) static void PF_checkextension(void)
{ {
const char *extname = G_STRING(OFS_PARM0); const char *extname = G_STRING(OFS_PARM0);
unsigned int i; unsigned int i;
for (i = 0; i < sizeof(extnames)/sizeof(extnames[0]); i++) for (i = 0; i < countof(qcextensions); i++)
{ {
if (!strcmp(extname, extnames[i])) if (!strcmp(extname, qcextensions[i].name))
{ {
if (qcextensions[i].checkextsupported)
{
unsigned int prot, pext1, pext2;
extern unsigned int sv_protocol;
extern unsigned int sv_protocol_pext1;
extern unsigned int sv_protocol_pext2;
extern cvar_t cl_nopext;
if (sv.active)
{ //server or client+server
prot = sv_protocol;
pext1 = sv_protocol_pext1;
pext2 = sv_protocol_pext2;
//if the server seems to be set up for singleplayer then filter by client settings. otherwise just assume the best.
if (!isDedicated && svs.maxclients == 1 && !cl_nopext.value)
pext1 = pext2 = 0;
}
else if (cls.state == ca_connected)
{ //client only (or demo)
prot = cl.protocol;
pext1 = cl.protocol_pext1;
pext2 = cl.protocol_pext2;
}
else
{ //menuqc? ooer
prot = 0;
pext1 = 0;
pext2 = 0;
}
if (!qcextensions[i].checkextsupported(prot, pext1, pext2))
{
if (!pr_checkextension.value)
Con_Printf("Mod queried extension %s, but not enabled\n", extname);
G_FLOAT(OFS_RETURN) = false;
return;
}
}
if (!pr_checkextension.value) if (!pr_checkextension.value)
Con_Printf("Mod found extension %s\n", extname); Con_Printf("Mod found extension %s\n", extname);
G_FLOAT(OFS_RETURN) = true; G_FLOAT(OFS_RETURN) = true;
@ -7781,8 +7857,8 @@ void PR_DumpPlatform_f(void)
} }
fprintf(f, "\n\n//List of advertised extensions\n"); fprintf(f, "\n\n//List of advertised extensions\n");
for (i = 0; i < sizeof(extnames)/sizeof(extnames[0]); i++) for (i = 0; i < countof(qcextensions); i++)
fprintf(f, "//%s\n", extnames[i]); fprintf(f, "//%s\n", qcextensions[i].name);
fprintf(f, "\n\n//Explicitly flag this stuff as probably-not-referenced, meaning fteqcc will shut up about it and silently strip what it can.\n"); fprintf(f, "\n\n//Explicitly flag this stuff as probably-not-referenced, meaning fteqcc will shut up about it and silently strip what it can.\n");
fprintf(f, "#pragma noref 1\n"); fprintf(f, "#pragma noref 1\n");