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:
parent
d590b1d2aa
commit
0c22b8c344
17 changed files with 182 additions and 140 deletions
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++)
|
||||
{
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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__)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue