Some q3 tweaks.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5416 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2019-02-24 08:32:45 +00:00
parent d590b1d2aa
commit 0c22b8c344
17 changed files with 182 additions and 140 deletions

View File

@ -320,18 +320,28 @@ typedef struct {
qbyte weapon; // weapon
signed char forwardmove, rightmove, upmove;
} q3usercmd_t;
#define CMD_BACKUP UPDATE_BACKUP
#define CMD_MASK UPDATE_MASK
qboolean CGQ3_GetUserCmd(int cmdNumber, q3usercmd_t *ucmd)
#define CMD_BACKUP countof(cl.outframes)
#define CMD_MASK (CMD_BACKUP-1)
static int CGQ3_GetCurrentCmdNumber(void)
{ //Q3 sequences are 1-based, so 1<=idx<=latestsequence are valid
//FTE's sequences are 0-based, so 0<=idx<latestsequence are valid
return cl.movesequence-1;
}
static qboolean CGQ3_GetUserCmd(int cmdNumber, q3usercmd_t *ucmd)
{
//q3 prediction uses for(int frame = CGQ3_GetCurrentCmdNumber() - CMD_BACKUP{64} + 1; frame <= CGQ3_GetCurrentCmdNumber(); frame++)
//skipping any that are older than the snapshot's time.
usercmd_t *cmd;
if (cmdNumber > cl.movesequence)
Host_EndGame("CL_GetUserCmd: cmdNumber > ccs.currentUserCmdNumber");
//q3 does not do partials.
if (cmdNumber >= cl.movesequence)
Host_EndGame("CLQ3_GetUserCmd: %i >= %i", cmdNumber, cl.movesequence);
if (cl.movesequence - cmdNumber >= CMD_BACKUP)
return false; // too old
if (cl.movesequence - (cmdNumber+1) > CMD_BACKUP)
return false;
//note: frames and commands are desynced in q3.
cmd = &cl.outframes[(cmdNumber) & CMD_MASK].cmd[0];
ucmd->angles[0] = cmd->angles[0];
ucmd->angles[1] = cmd->angles[1];
@ -1011,7 +1021,7 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
break;
case CG_S_STARTSOUND:// ( vec3_t origin, int entityNum, int entchannel, sfxHandle_t sfx )
S_StartSound(VM_LONG(arg[1])+1, VM_LONG(arg[2]), S_PrecacheSound(VM_FROMSTRCACHE(arg[3])), VM_POINTER(arg[0]), NULL, 1, 1, 0, 0, 0);
S_StartSound(VM_LONG(arg[1])+1, VM_LONG(arg[2]), S_PrecacheSound(VM_FROMSTRCACHE(arg[3])), VM_POINTER(arg[0]), NULL, 1, 1, 0, 0, CF_CLI_NODUPES);
break;
case CG_S_ADDLOOPINGSOUND:
@ -1121,7 +1131,7 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
break;
case CG_GETCURRENTCMDNUMBER:
VM_LONG(ret) = cl.movesequence-1;
VM_LONG(ret) = CGQ3_GetCurrentCmdNumber();
break;
case CG_GETUSERCMD:
VALIDATEPOINTER(arg[1], sizeof(q3usercmd_t));
@ -1290,7 +1300,7 @@ static qintptr_t EXPORT_FN CG_SystemCallsNative(qintptr_t arg, ...)
args[9]=va_arg(argptr, qintptr_t);
va_end(argptr);
return CG_SystemCalls(NULL, (unsigned)~0, arg, args);
return CG_SystemCalls(NULL, ~(quintptr_t)0, arg, args);
}
int CG_Refresh(void)
@ -1343,7 +1353,7 @@ void CG_Start (void)
Z_FreeTags(CGTAGNUM);
SCR_BeginLoadingPlaque();
cgvm = VM_Create("vm/cgame", com_nogamedirnativecode.ival?NULL:CG_SystemCallsNative, CG_SystemCallsVM);
cgvm = VM_Create("cgame", com_nogamedirnativecode.ival?NULL:CG_SystemCallsNative, "vm/cgame", CG_SystemCallsVM);
if (cgvm)
{ //hu... cgame doesn't appear to have a query version call!
SCR_EndLoadingPlaque();

View File

@ -5554,6 +5554,7 @@ void CL_SetSolidEntities (void)
packet_entities_t *pak;
entity_state_t *state;
physent_t *pent;
model_t *mod;
memset(&pmove.physents[0], 0, sizeof(physent_t));
pmove.physents[0].model = cl.worldmodel;
@ -5575,18 +5576,20 @@ void CL_SetSolidEntities (void)
{ /*bsp model size*/
if (state->modelindex <= 0)
continue;
if (!cl.model_precache[state->modelindex])
mod = cl.model_precache[state->modelindex];
if (!mod)
continue;
/*vanilla protocols have no 'solid' information. all entities get assigned ES_SOLID_BSP, even if its not actually solid.
so we need to make sure that item pickups are not erroneously considered solid, but doors etc are.
yes, this probably means that externally loaded models will be predicted non-solid - you'll need to upgrade your network protocol for the gamecode to be able to specify solidity.
normally, ONLY inline models are considered solid when we have no solid info.
monsters will always be non-solid, too.
*/
if (!(cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) && !((*cl.model_precache[state->modelindex]->name == '*' || cl.model_precache[state->modelindex]->numsubmodels) && cl.model_precache[state->modelindex]->funcs.NativeTrace))
if (!(cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) && mod->numsubmodels <= 1)
continue;
pent = &pmove.physents[pmove.numphysent];
memset(pent, 0, sizeof(physent_t));
pent->model = cl.model_precache[state->modelindex];
pent->model = mod;
if (pent->model->loadstate != MLS_LOADED)
continue;
VectorCopy (state->angles, pent->angles);

View File

@ -34,7 +34,7 @@ static cvar_t cl_movement = CVARD("cl_movement","1", "Specifies whether to send
cvar_t cl_nodelta = CVAR("cl_nodelta","0");
static cvar_t cl_c2sdupe = CVAR("cl_c2sdupe", "0");
cvar_t cl_c2sdupe = CVAR("cl_c2sdupe", "0");
cvar_t cl_c2spps = CVAR("cl_c2spps", "0");
cvar_t cl_c2sImpulseBackup = CVAR("cl_c2sImpulseBackup","3");
cvar_t cl_netfps = CVAR("cl_netfps", "150");

View File

@ -178,7 +178,7 @@ cvar_t cl_gunanglez = CVAR("cl_gunanglez", "0");
cvar_t cl_proxyaddr = CVAR("cl_proxyaddr", "");
cvar_t cl_sendguid = CVARD("cl_sendguid", "", "Send a randomly generated 'globally unique' id to servers, which can be used by servers for score rankings and stuff. Different servers will see different guids. Delete the 'qkey' file in order to appear as a different user.\nIf set to 2, all servers will see the same guid. Be warned that this can show other people the guid that you're using.");
cvar_t cl_downloads = CVARFD("cl_downloads", "1", CVAR_NOTFROMSERVER, "Allows you to block all automatic downloads.");
cvar_t cl_downloads = CVARAFD("cl_downloads", "1", /*q3*/"cl_allowDownload", CVAR_NOTFROMSERVER, "Allows you to block all automatic downloads.");
cvar_t cl_download_csprogs = CVARFD("cl_download_csprogs", "1", CVAR_NOTFROMSERVER, "Download updated client gamecode if available. Warning: If you clear this to avoid downloading vm code, you should also clear cl_download_packages.");
cvar_t cl_download_redirection = CVARFD("cl_download_redirection", "2", CVAR_NOTFROMSERVER, "Follow download redirection to download packages instead of individual files. Also allows the server to send nearly arbitary download commands.\n2: allows redirection only to named packages files (and demos/*.mvd), which is a bit safer.");
cvar_t cl_download_mapsrc = CVARFD("cl_download_mapsrc", "", CVAR_ARCHIVE, "Specifies an http location prefix for map downloads. EG: \"http://example.com/path/quakemaps/\"");
@ -3496,10 +3496,18 @@ client_connect: //fixme: make function
cls.state = ca_connected;
if (cls.netchan.remote_address.type != NA_LOOPBACK)
{
switch(cls.protocol)
{
case CP_QUAKEWORLD: Con_DPrintf("QW "); break;
case CP_NETQUAKE: Con_Printf ("NQ "); break;
case CP_QUAKE2: Con_Printf ("Q2 "); break;
case CP_QUAKE3: Con_Printf ("Q3 "); break;
default: break;
}
if (cls.netchan.remote_address.prot == NP_DTLS || cls.netchan.remote_address.prot == NP_TLS || cls.netchan.remote_address.prot == NP_WSS)
Con_TPrintf ("Connected (^2encrypted^7).\n");
Con_TPrintf ("Connected (^[^2encrypted\\tip\\Any passwords will be sent securely, but may still be logged^]).\n");
else
Con_TPrintf ("Connected (^1plain-text^7).\n");
Con_TPrintf ("Connected (^[^1plain-text\\tip\\"CON_WARNING"Do not type passwords as they can potentially be seen by network sniffers^]).\n");
}
#ifdef QUAKESPYAPI
allowremotecmd = false; // localid required now for remote cmds

View File

@ -1636,7 +1636,7 @@ void UI_Start (void)
ui_width = vid.width;
ui_height = vid.height;
uivm = VM_Create("vm/ui", com_nogamedirnativecode.ival?NULL:UI_SystemCallsNative, UI_SystemCallsVM);
uivm = VM_Create("ui", com_nogamedirnativecode.ival?NULL:UI_SystemCallsNative, "vm/ui", UI_SystemCallsVM);
if (uivm)
{
apiversion = VM_Call(uivm, UI_GETAPIVERSION, 6);

View File

@ -47,7 +47,7 @@ qboolean CG_FillQ3Snapshot(int snapnum, snapshot_t *snapshot)
snapshot->numEntities = snap->numEntities;
for (i=0; i<snapshot->numEntities; i++)
{
memcpy(&snapshot->entities[i], &ccs.parseEntities[(snap->firstEntity+i) & PARSE_ENTITIES_MASK], sizeof(snapshot->entities[0]));
memcpy(&snapshot->entities[i], &ccs.parseEntities[(snap->firstEntity+i) & Q3PARSE_ENTITIES_MASK], sizeof(snapshot->entities[0]));
}
memcpy( &snapshot->areamask, snap->areabits, sizeof( snapshot->areamask ) );
@ -108,7 +108,7 @@ static void CLQ3_DeltaEntity( clientSnap_t *frame, int newnum, q3entityState_t *
{
q3entityState_t *state;
state = &ccs.parseEntities[ccs.firstParseEntity & PARSE_ENTITIES_MASK];
state = &ccs.parseEntities[ccs.firstParseEntity & Q3PARSE_ENTITIES_MASK];
if( unchanged )
{
@ -155,7 +155,7 @@ static void CLQ3_ParsePacketEntities( clientSnap_t *oldframe, clientSnap_t *newf
}
else
{
oldstate = &ccs.parseEntities[oldframe->firstEntity & PARSE_ENTITIES_MASK];
oldstate = &ccs.parseEntities[oldframe->firstEntity & Q3PARSE_ENTITIES_MASK];
oldnum = oldstate->number;
}
@ -193,7 +193,7 @@ static void CLQ3_ParsePacketEntities( clientSnap_t *oldframe, clientSnap_t *newf
}
else
{
oldstate = &ccs.parseEntities[(oldframe->firstEntity + numentities) & PARSE_ENTITIES_MASK];
oldstate = &ccs.parseEntities[(oldframe->firstEntity + numentities) & Q3PARSE_ENTITIES_MASK];
oldnum = oldstate->number;
}
}
@ -213,7 +213,7 @@ static void CLQ3_ParsePacketEntities( clientSnap_t *oldframe, clientSnap_t *newf
}
else
{
oldstate = &ccs.parseEntities[(oldframe->firstEntity + numentities) & PARSE_ENTITIES_MASK];
oldstate = &ccs.parseEntities[(oldframe->firstEntity + numentities) & Q3PARSE_ENTITIES_MASK];
oldnum = oldstate->number;
}
continue;
@ -244,7 +244,7 @@ static void CLQ3_ParsePacketEntities( clientSnap_t *oldframe, clientSnap_t *newf
}
else
{
oldstate = &ccs.parseEntities[(oldframe->firstEntity + numentities) & PARSE_ENTITIES_MASK];
oldstate = &ccs.parseEntities[(oldframe->firstEntity + numentities) & Q3PARSE_ENTITIES_MASK];
oldnum = oldstate->number;
}
}
@ -289,12 +289,12 @@ void CLQ3_ParseSnapshot(void)
{
// The frame that the server did the delta from
// is too old, so we can't reconstruct it properly.
Con_Printf( "Delta frame too old.\n" );
Con_DPrintf( "Delta frame too old.\n" );
}
else if(ccs.firstParseEntity - oldsnap->firstEntity >
MAX_PARSE_ENTITIES - MAX_ENTITIES_IN_SNAPSHOT)
Q3MAX_PARSE_ENTITIES - MAX_ENTITIES_IN_SNAPSHOT)
{
Con_Printf( "Delta parse_entities too old.\n" );
Con_DPrintf( "Delta parse_entities too old.\n" );
}
else
{
@ -371,8 +371,8 @@ void CLQ3_ParseDownload(void)
if (dl->size == (unsigned int)-1)
{
s = MSG_ReadString();
Con_Printf("\nDownload refused:\n %s\n", s);
CL_DownloadFailed(dl->remotename, dl);
Host_EndGame("%s", s);
return;
}
@ -441,6 +441,7 @@ static qboolean CLQ3_SendDownloads(char *rc, char *rn)
char tempname[MAX_QPATH];
char crc[64];
vfsfile_t *f;
extern cvar_t cl_downloads;
rc = COM_ParseOut(rc, crc, sizeof(crc));
rn = COM_Parse(rn);
if (!*com_token)
@ -468,8 +469,14 @@ static qboolean CLQ3_SendDownloads(char *rc, char *rn)
if (!FS_GenCachedPakName(va("%s.tmp", com_token), crc, tempname, sizeof(tempname)))
continue;
if (!cl_downloads.ival)
{
Con_Printf(CON_WARNING "Need to download %s.pk3, but downloads are disabled\n", com_token);
continue;
}
//fixme: request to download it
Con_Printf("Sending request to download %s\n", com_token);
Con_Printf("Sending request to download %s.pk3\n", com_token);
CLQ3_SendClientCommand("download %s.pk3", com_token);
ccs.downloadchunknum = 0;
dl = Z_Malloc(sizeof(*dl));
@ -897,6 +904,7 @@ void CLQ3_SendCmd(usercmd_t *cmd)
int cmdcount, key;
usercmd_t *to, *from;
extern int keycatcher;
extern cvar_t cl_nodelta, cl_c2sdupe;
//reuse the q1 array
cmd->servertime = cl.servertime*1000;
@ -927,10 +935,13 @@ void CLQ3_SendCmd(usercmd_t *cmd)
cmd->buttons |= 2; //add in the 'at console' button
cl.outframes[cl.movesequence&CMD_MASK].cmd[0] = *cmd;
cl.movesequence++;
//FIXME: q3 generates a new command every video frame, but a new packet at a more limited rate.
//FIXME: we should return here if its not yet time for a network frame.
frame = &cl.outframes[cls.netchan.outgoing_sequence & CMD_MASK];
frame->cmd_sequence = cl.movesequence++;
frame->cmd_sequence = cl.movesequence;
frame->server_message_num = ccs.serverMessageNum;
frame->server_time = cl.gametime;
frame->client_time = Sys_DoubleTime()*1000;
@ -955,15 +966,19 @@ void CLQ3_SendCmd(usercmd_t *cmd)
MSG_WriteBits(&msg, 0, 8);
}
i = (cls.netchan.outgoing_sequence-1);
i = cls.netchan.outgoing_sequence;
i -= bound(0, cl_c2sdupe.ival, 5); //extra age, if desired
i--;
if (i < cls.netchan.outgoing_sequence-CMD_MASK)
i = cls.netchan.outgoing_sequence-CMD_MASK;
oldframe = &cl.outframes[i & CMD_MASK];
cmdcount = cl.movesequence - oldframe->cmd_sequence;
if (cmdcount > CMD_MASK)
cmdcount = CMD_MASK;
// begin a client move command, if any
if( cmdcount )
if (cmdcount)
{
extern cvar_t cl_nodelta;
if(cl_nodelta.value || !ccs.snap.valid ||
ccs.snap.serverMessageNum != ccs.serverMessageNum)
MSG_WriteBits(&msg, clcq3_nodeltaMove, 8); // no compression
@ -977,8 +992,8 @@ void CLQ3_SendCmd(usercmd_t *cmd)
string = ccs.serverCommands[ccs.lastServerCommandNum & TEXTCMD_MASK];
key = ccs.fs_key ^ ccs.serverMessageNum ^ StringKey(string, 32);
// send this and the previous cmds in the message, so
// if the last packet was dropped, it can be recovered
//note that q3 uses timestamps so sequences are not important
//we can also send dupes without issue.
from = &nullcmd;
for (i = cl.movesequence-cmdcount; i < cl.movesequence; i++)
{

View File

@ -202,8 +202,8 @@ typedef struct frame_s {
int serverTime;
} q3frame_t;
#define MAX_PARSE_ENTITIES 1024
#define PARSE_ENTITIES_MASK (MAX_PARSE_ENTITIES-1)
#define Q3MAX_PARSE_ENTITIES 2048
#define Q3PARSE_ENTITIES_MASK (Q3MAX_PARSE_ENTITIES-1)
#define MAX_STRING_CHARS 1024
#define TEXTCMD_BACKUP 64 // size of reliable text commands buffer, must be power of two
@ -234,7 +234,7 @@ typedef struct {
clientSnap_t snapshots[Q3UPDATE_BACKUP];
clientSnap_t snap;
q3entityState_t parseEntities[MAX_PARSE_ENTITIES];
q3entityState_t parseEntities[Q3MAX_PARSE_ENTITIES];
q3entityState_t baselines[MAX_GENTITIES];

View File

@ -2568,6 +2568,9 @@ channel_t *SND_PickChannel(soundcardinfo_t *sc, int entnum, int entchannel)
if (sc->total_chans <= oldest)
sc->total_chans = oldest+1;
#ifdef Q3CLIENT //presumably we should be using this instead of pos for oldest, but blurgh.
sc->channel[oldest].starttime = Sys_Milliseconds();
#endif
return &sc->channel[oldest];
}
@ -2963,6 +2966,28 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, vec3_t
S_LockMixer();
for (sc = sndcardinfo; sc; sc = sc->next)
{
#ifdef Q3CLIENT
if (flags & CF_CLI_NODUPES)
{ //don't start too many simultaneous sounds. q3 sucks or something.
int active = 0, i;
unsigned int time = Sys_Milliseconds();
for (i = 0; i < sc->total_chans; i++)
{ //as per q3, channel isn't important.
if (sc->channel[i].entnum == entnum && sc->channel[i].sfx == sfx)
{
//never allow a new sound within 50ms of the previous one
if (time - sc->channel[i].starttime < 50)
break;
active++;
}
}
if (active >= 4 || i < sc->total_chans)
{
Con_DPrintf("CF_CLI_NODUPES strikes again!\n");
break;
}
}
#endif
// pick a channel to play on
target_chan = SND_PickChannel(sc, entnum, entchannel);
if (!target_chan)

View File

@ -115,6 +115,9 @@ typedef struct
#define CF_SV_SENDVELOCITY 512 // serverside hint that velocity is important
#define CF_CLI_AUTOSOUND 1024 // generated from q2 entities, which avoids breaking regular sounds, using it outside the sound system will probably break things.
#define CF_CLI_INACTIVE 2048 // try to play even when inactive
#ifdef Q3CLIENT
#define CF_CLI_NODUPES 4096 // block multiple identical sounds being started on the same entity within rapid succession. required by quake3.
#endif
#define CF_NETWORKED (CF_NOSPACIALISE|CF_NOREVERB|CF_FORCELOOP|CF_FOLLOW/*|CF_RESERVEDN*/)
typedef struct
@ -130,6 +133,9 @@ typedef struct
vec3_t velocity; // velocity of sound effect
vec_t dist_mult; // distance multiplier (attenuation/clipK)
int master_vol; // 0-255 master volume
#ifdef Q3CLIENT
unsigned int starttime; // start time, to replicate q3's 50ms embargo on duped sounds.
#endif
} channel_t;
struct soundcardinfo_s;

View File

@ -645,6 +645,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define ARCH_CPU_POSTFIX "x64"
#else
#define ARCH_CPU_POSTFIX "amd64"
#define ARCH_ALTCPU_POSTFIX "x86_64"
#endif
#endif
#elif defined(_M_IX86) || defined(__i386__)

View File

@ -1621,7 +1621,42 @@ char *Cmd_ExpandString (const char *data, char *dest, int destlen, int *accessle
if (c == '"')
quotes++;
if (c == '$' && (!(quotes&1) || dpcompat_console.ival))
if (c == '%' && !(quotes&1) && !dpcompat_console.ival)
{ //QW262/ezquake does this. kinda annoying.
char *end;
if (data[1] == '%')
{
str = "%";
data+=2;
}
else if (data[1] == '#')
{
str = va("\"%s\"", Cmd_Args());
data+=2;
}
else if (data[1] == '*')
{
str = Cmd_Args();
data+=2;
}
else if ((i=strtol(data+1, &end, 10)))
{
data = end;
str = Cmd_Argv(i);
}
else
{
data++;
str = "%"; //some kind of encoding error
}
// check buffer size
if (len + strlen(str) >= destlen-1)
break;
strcpy(&dest[len], str);
len += strlen(str);
}
else if (c == '$' && (!(quotes&1) || dpcompat_console.ival))
{
data++;
if (*data == '$')
@ -1741,75 +1776,6 @@ char *Cmd_ExpandString (const char *data, char *dest, int destlen, int *accessle
return dest;
}
static char *Cmd_ExpandStringArguments (char *data, char *dest, int destlen)
{
char c;
int quotes = 0;
int len = 0;
char *str, *strend;
int old_len;
while ( (c = *data) != 0)
{
if (c == '"')
quotes++;
if (c == '%' && !(quotes&1))
{
if (data[1] == '%')
{
str = "%";
old_len = 2;
}
else if (data[1] == '#')
{
str = va("\"%s\"", Cmd_Args());
old_len = 2;
}
else if (data[1] == '*')
{
str = Cmd_Args();
old_len = 2;
}
else if (strtol(data+1, &strend, 10))
{
str = Cmd_Argv(atoi(data+1));
old_len = strend - data;
}
else
{
str = NULL;
old_len = 0;
}
if (str)
{
// check buffer size
if (len + strlen(str) >= destlen-1)
break;
strcpy(&dest[len], str);
len += strlen(str);
dest[len] = 0;
data += old_len;
continue;
}
}
dest[len] = c;
data++;
len++;
dest[len] = 0;
if (len >= destlen-1)
break;
}
dest[len] = 0;
return dest;
}
/*
============
Cmd_TokenizeString
@ -2805,7 +2771,6 @@ static void Cmd_ExecuteStringGlobalsAreEvil (const char *text, int level)
// if the alias value is a command or cvar and
// the alias is called with parameters, add them
//unless we're mimicing dp, or the alias has explicit expansions (or macros) in which case it can do its own damn args
if (dpcompat_console.ival)
{
char *ignoringquoteswasstupid;
Cmd_ExpandString(a->value, dest, sizeof(dest), &execlevel, !Cmd_IsInsecure()?true:false, true);
@ -2821,7 +2786,7 @@ static void Cmd_ExecuteStringGlobalsAreEvil (const char *text, int level)
if ((a->restriction?a->restriction:rcon_level.ival) > execlevel)
return;
}
else if (!strchr(a->value, '$'))
if (!dpcompat_console.ival)
{
if (Cmd_Argc() > 1 && (!strncmp(a->value, "cmd ", 4) || (!strchr(a->value, ' ') && !strchr(a->value, '\t') &&
(Cvar_FindVar(a->value) || (Cmd_Exists(a->value) && a->value[0] != '+' && a->value[0] != '-'))))
@ -2830,11 +2795,7 @@ static void Cmd_ExecuteStringGlobalsAreEvil (const char *text, int level)
Cbuf_InsertText (Cmd_Args(), execlevel, false);
Cbuf_InsertText (" ", execlevel, false);
}
Cmd_ExpandStringArguments (a->value, dest, sizeof(dest));
}
else
Q_strncpyz(dest, a->value, sizeof(dest));
Cbuf_InsertText (dest, execlevel, false);
#ifdef HAVE_CLIENT

View File

@ -286,14 +286,14 @@ static plugin_t *Plug_Load(const char *file, int type)
if (!newplug->vm && (type & PLUG_NATIVE) && !Q_strncasecmp(file, "fteplug_", 8) && !Q_strcasecmp(ARCH_DL_POSTFIX+1, COM_FileExtension(file, temp, sizeof(temp))))
{
COM_StripExtension(file, temp, sizeof(temp));
newplug->vm = VM_Create(temp, Plug_SystemCallsNative, NULL);
newplug->vm = VM_Create(temp, Plug_SystemCallsNative, NULL, NULL);
}
if (!newplug->vm && (type & PLUG_NATIVE))
newplug->vm = VM_Create(va("fteplug_%s_", file), Plug_SystemCallsNative, NULL);
newplug->vm = VM_Create(va("fteplug_%s_", file), Plug_SystemCallsNative, NULL, NULL);
if (!newplug->vm && (type & PLUG_NATIVE))
newplug->vm = VM_Create(va("fteplug_%s", file), Plug_SystemCallsNative, NULL);
newplug->vm = VM_Create(va("fteplug_%s", file), Plug_SystemCallsNative, NULL, NULL);
if (!newplug->vm && (type & PLUG_QVM))
newplug->vm = VM_Create(file, NULL, Plug_SystemCallsVM);
newplug->vm = VM_Create(NULL, NULL, file, Plug_SystemCallsVM);
if (!newplug->vm && (type & PLUG_NATIVE))
{
unsigned int u;

View File

@ -76,7 +76,10 @@ struct vm_s {
qboolean QVM_LoadDLL(vm_t *vm, const char *name, qboolean binroot, void **vmMain, sys_calldll_t syscall)
{
void (EXPORT_FN *dllEntry)(sys_calldll_t syscall);
char dllname_arch[MAX_OSPATH]; //id compatiblehttps://slashdot.org/
char dllname_archpri[MAX_OSPATH]; //id compatible
#ifdef ARCH_ALTCPU_POSTFIX
char dllname_archsec[MAX_OSPATH]; //id compatible
#endif
char dllname_anycpu[MAX_OSPATH];//simple
dllhandle_t *hVM;
@ -91,7 +94,10 @@ qboolean QVM_LoadDLL(vm_t *vm, const char *name, qboolean binroot, void **vmMain
{NULL, NULL},
};
snprintf(dllname_arch, sizeof(dllname_arch), "%s"ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, name);
snprintf(dllname_archpri, sizeof(dllname_archpri), "%s"ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, name);
#ifdef ARCH_ALTCPU_POSTFIX
snprintf(dllname_archsec, sizeof(dllname_archsec), "%s"ARCH_ALTCPU_POSTFIX ARCH_DL_POSTFIX, name);
#endif
snprintf(dllname_anycpu, sizeof(dllname_anycpu), "%s" ARCH_DL_POSTFIX, name);
hVM=NULL;
@ -101,12 +107,12 @@ qboolean QVM_LoadDLL(vm_t *vm, const char *name, qboolean binroot, void **vmMain
{
Con_DPrintf("Attempting to load native library: %s\n", name);
if (!hVM && FS_NativePath(dllname_arch, FS_BINARYPATH, fname, sizeof(fname)))
if (!hVM && FS_NativePath(dllname_archpri, FS_BINARYPATH, fname, sizeof(fname)))
hVM = Sys_LoadLibrary(fname, funcs);
if (!hVM && FS_NativePath(dllname_anycpu, FS_BINARYPATH, fname, sizeof(fname)))
hVM = Sys_LoadLibrary(fname, funcs);
if (!hVM && FS_NativePath(dllname_arch, FS_ROOT, fname, sizeof(fname)))
if (!hVM && FS_NativePath(dllname_archpri, FS_ROOT, fname, sizeof(fname)))
hVM = Sys_LoadLibrary(fname, funcs);
if (!hVM && FS_NativePath(dllname_anycpu, FS_ROOT, fname, sizeof(fname)))
hVM = Sys_LoadLibrary(fname, funcs);
@ -138,11 +144,20 @@ qboolean QVM_LoadDLL(vm_t *vm, const char *name, qboolean binroot, void **vmMain
{
if (!hVM)
{
snprintf (fname, sizeof(fname), "%s%s", gpath, dllname_arch);
snprintf (fname, sizeof(fname), "%s%s", gpath, dllname_archpri);
Con_DLPrintf(2, "Loading native: %s\n", fname);
hVM = Sys_LoadLibrary(fname, funcs);
}
#ifdef ARCH_ALTCPU_POSTFIX
if (!hVM)
{
snprintf (fname, sizeof(fname), "%s%s", gpath, dllname_archsec);
Con_DLPrintf(2, "Loading native: %s\n", fname);
hVM = Sys_LoadLibrary(fname, funcs);
}
#endif
if (!hVM)
{
snprintf (fname, sizeof(fname), "%s%s", gpath, dllname_anycpu);
@ -981,17 +996,15 @@ vm_t *VM_CreateBuiltin(const char *name, sys_calldll_t syscalldll, qintptr_t (*i
/*
** VM_Create
*/
vm_t *VM_Create(const char *name, sys_calldll_t syscalldll, sys_callqvm_t syscallqvm)
vm_t *VM_Create(const char *dllname, sys_calldll_t syscalldll, const char *qvmname, sys_callqvm_t syscallqvm)
{
vm_t *vm;
if(!name || !*name)
Sys_Error("VM_Create: bad parms");
vm = Z_Malloc(sizeof(vm_t));
// prepare vm struct
memset(vm, 0, sizeof(vm_t));
Q_strncpyz(vm->filename, name, sizeof(vm->filename));
Q_strncpyz(vm->filename, "", sizeof(vm->filename));
vm->syscalldll=syscalldll;
vm->syscallqvm=syscallqvm;
@ -1001,9 +1014,9 @@ vm_t *VM_Create(const char *name, sys_calldll_t syscalldll, sys_callqvm_t syscal
{
if (!COM_CheckParm("-nodlls") && !COM_CheckParm("-nosos")) //:)
{
if(QVM_LoadDLL(vm, name, !syscallqvm, (void**)&vm->vmMain, syscalldll))
if(QVM_LoadDLL(vm, dllname, !syscallqvm, (void**)&vm->vmMain, syscalldll))
{
Con_DPrintf("Creating native machine \"%s\"\n", name);
Con_DPrintf("Creating native machine \"%s\"\n", dllname);
vm->type=VM_NATIVE;
return vm;
}
@ -1013,9 +1026,9 @@ vm_t *VM_Create(const char *name, sys_calldll_t syscalldll, sys_callqvm_t syscal
if (syscallqvm)
{
if(QVM_LoadVM(vm, name, syscallqvm))
if(QVM_LoadVM(vm, qvmname, syscallqvm))
{
Con_DPrintf("Creating virtual machine \"%s\"\n", name);
Con_DPrintf("Creating virtual machine \"%s\"\n", qvmname);
vm->type=VM_BYTECODE;
return vm;
}

View File

@ -21,7 +21,7 @@ typedef struct vm_s vm_t;
void VM_PrintInfo(vm_t *vm);
vm_t *VM_CreateBuiltin(const char *name, sys_calldll_t syscalldll, qintptr_t (*init)(qintptr_t *args));
vm_t *VM_Create(const char *name, sys_calldll_t syscalldll, sys_callqvm_t syscallqvm);
vm_t *VM_Create(const char *dllname, sys_calldll_t syscalldll, const char *qvmname, sys_callqvm_t syscallqvm);
const char *VM_GetFilename(vm_t *vm);
void VM_Destroy(vm_t *vm);
//qboolean VM_Restart(vm_t *vm);

View File

@ -2152,9 +2152,9 @@ qboolean PR_LoadQ1QVM(void)
Q1QVM_Shutdown(true);
q1qvm = VM_Create("qwprogs", com_nogamedirnativecode.ival?NULL:syscallnative, syscallqvm);
q1qvm = VM_Create("qwprogs", com_nogamedirnativecode.ival?NULL:syscallnative, "qwprogs", syscallqvm);
if (!q1qvm)
q1qvm = VM_Create("qwprogs", syscallnative, NULL);
q1qvm = VM_Create("qwprogs", syscallnative, "qwprogs", NULL);
if (!q1qvm)
{
if (svprogfuncs == &q1qvmprogfuncs)

View File

@ -64,7 +64,7 @@ extern cvar_t password;
#endif
cvar_t spectator_password = CVARF("spectator_password", "", CVAR_NOUNSAFEEXPAND); // password for entering as a sepctator
cvar_t allow_download = CVARD("allow_download", "1", "If 1, permits downloading. Set to 0 to unconditionally block *ALL* downloads.");
cvar_t allow_download = CVARAD("allow_download", /*q3*/"sv_allowDownload", "1", "If 1, permits downloading. Set to 0 to unconditionally block *ALL* downloads.");
cvar_t allow_download_skins = CVARD("allow_download_skins", "1", "0 blocks downloading of any file in the skins/ directory");
cvar_t allow_download_models = CVARD("allow_download_models", "1", "0 blocks downloading of any file in the progs/ or models/ directory");
cvar_t allow_download_sounds = CVARD("allow_download_sounds", "1", "0 blocks downloading of any file in the sound/ directory");

View File

@ -862,7 +862,7 @@ static void SVQ3_Adjust_Area_Portal_State(q3sharedEntity_t *ge, qboolean open)
}
#define VALIDATEPOINTER(o,l) if ((int)o + l >= mask || VM_POINTER(o) < offset) SV_Error("Call to game trap %u passes invalid pointer\n", (unsigned int)fn); //out of bounds.
static qintptr_t Q3G_SystemCalls(void *offset, unsigned int mask, qintptr_t fn, const qintptr_t *arg)
static qintptr_t Q3G_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, const qintptr_t *arg)
{
int ret = 0;
switch(fn)
@ -1615,7 +1615,7 @@ static qintptr_t EXPORT_FN Q3G_SystemCallsNative(qintptr_t arg, ...)
args[12]=va_arg(argptr, qintptr_t);
va_end(argptr);
return Q3G_SystemCalls(NULL, ~0, arg, args);
return Q3G_SystemCalls(NULL, ~(quintptr_t)0, arg, args);
}
void SVQ3_ShutdownGame(void)
@ -1890,7 +1890,7 @@ qboolean SVQ3_InitGame(void)
SVQ3_ShutdownGame();
q3gamevm = VM_Create("vm/qagame", com_nogamedirnativecode.ival?NULL:Q3G_SystemCallsNative, Q3G_SystemCallsVM);
q3gamevm = VM_Create("qagame", com_nogamedirnativecode.ival?NULL:Q3G_SystemCallsNative, "vm/qagame", Q3G_SystemCallsVM);
if (!q3gamevm)
return false;