// cmd.c -- Quake script command processing module
#include "quakedef.h"
+#include "thread.h"
typedef struct cmdalias_s
{
static sizebuf_t cmd_text;
static unsigned char cmd_text_buf[CMDBUFSIZE];
+void *cmd_text_mutex = NULL;
+
+static void Cbuf_LockThreadMutex(void)
+{
+ if (cmd_text_mutex)
+ Thread_LockMutex(cmd_text_mutex);
+}
+
+static void Cbuf_UnlockThreadMutex(void)
+{
+ if (cmd_text_mutex)
+ Thread_UnlockMutex(cmd_text_mutex);
+}
/*
============
{
int l;
- l = (int)strlen (text);
+ l = (int)strlen(text);
+ Cbuf_LockThreadMutex();
if (cmd_text.cursize + l >= cmd_text.maxsize)
- {
Con_Print("Cbuf_AddText: overflow\n");
- return;
- }
-
- SZ_Write (&cmd_text, (const unsigned char *)text, (int)strlen (text));
+ else
+ SZ_Write(&cmd_text, (const unsigned char *)text, (int)strlen (text));
+ Cbuf_UnlockThreadMutex();
}
char *temp;
int templen;
+ Cbuf_LockThreadMutex();
+
// copy off any commands still remaining in the exec buffer
templen = cmd_text.cursize;
if (templen)
SZ_Write (&cmd_text, (const unsigned char *)temp, templen);
Mem_Free (temp);
}
+
+ Cbuf_UnlockThreadMutex();
}
/*
qboolean quotes;
char *comment;
+ Cbuf_LockThreadMutex();
+ SV_LockThreadMutex();
+
// LordHavoc: making sure the tokenizebuffer doesn't get filled up by repeated crashes
cmd_tokenizebufferpos = 0;
)
{
Cmd_PreprocessString( line, preprocessed, sizeof(preprocessed), NULL );
- Cmd_ExecuteString (preprocessed, src_command);
+ Cmd_ExecuteString (preprocessed, src_command, false);
}
else
{
- Cmd_ExecuteString (line, src_command);
+ Cmd_ExecuteString (line, src_command, false);
}
if (cmd_wait)
break;
}
}
+
+ SV_UnlockThreadMutex();
+ Cbuf_UnlockThreadMutex();
}
/*
Cbuf_InsertText (build);
}
-
-/*
-===============
-Cmd_Exec_f
-===============
-*/
-static void Cmd_Exec_f (void)
+static void Cmd_Exec(const char *filename)
{
char *f;
- const char *filename;
+ qboolean isdefaultcfg = strlen(filename) >= 11 && !strcmp(filename + strlen(filename) - 11, "default.cfg");
- if (Cmd_Argc () != 2)
- {
- Con_Print("exec <filename> : execute a script file\n");
- return;
- }
-
- filename = Cmd_Argv(1);
if (!strcmp(filename, "config.cfg"))
{
filename = CONFIGFILENAME;
// if executing default.cfg for the first time, lock the cvar defaults
// it may seem backwards to insert this text BEFORE the default.cfg
// but Cbuf_InsertText inserts before, so this actually ends up after it.
- if (strlen(filename) >= 11 && !strcmp(filename + strlen(filename) - 11, "default.cfg"))
+ if (isdefaultcfg)
Cbuf_InsertText("\ncvar_lockdefaults\n");
// insert newline after the text to make sure the last line is terminated (some text editors omit the trailing newline)
Cbuf_InsertText (f);
Mem_Free(f);
- // special defaults for specific games go here, these execute before default.cfg
- // Nehahra pushable crates malfunction in some levels if this is on
- // Nehahra NPC AI is confused by blowupfallenzombies
- if (gamemode == GAME_NEHAHRA)
- Cbuf_InsertText("\nsv_gameplayfix_upwardvelocityclearsongroundflag 0\nsv_gameplayfix_blowupfallenzombies 0\n\n");
- // hipnotic mission pack has issues in their 'friendly monster' ai, which seem to attempt to attack themselves for some reason when findradius() returns non-solid entities.
- // hipnotic mission pack has issues with bobbing water entities 'jittering' between different heights on alternate frames at the default 0.0138889 ticrate, 0.02 avoids this issue
- // hipnotic mission pack has issues in their proximity mine sticking code, which causes them to bounce off.
- if (gamemode == GAME_HIPNOTIC)
- Cbuf_InsertText("\nsv_gameplayfix_blowupfallenzombies 0\nsys_ticrate 0.02\nsv_gameplayfix_slidemoveprojectiles 0\n\n");
- // rogue mission pack has a guardian boss that does not wake up if findradius returns one of the entities around its spawn area
- if (gamemode == GAME_ROGUE)
- Cbuf_InsertText("\nsv_gameplayfix_findradiusdistancetobox 0\n\n");
- if (gamemode == GAME_NEXUIZ)
- Cbuf_InsertText("\nsv_gameplayfix_q2airaccelerate 1\nsv_gameplayfix_stepmultipletimes 1\n\n");
- if (gamemode == GAME_TENEBRAE)
- Cbuf_InsertText("\nr_shadow_gloss 2\nr_shadow_bumpscale_basetexture 4\n\n");
+ if (isdefaultcfg)
+ {
+ // special defaults for specific games go here, these execute before default.cfg
+ // Nehahra pushable crates malfunction in some levels if this is on
+ // Nehahra NPC AI is confused by blowupfallenzombies
+ if (gamemode == GAME_NEHAHRA)
+ Cbuf_InsertText("\nsv_gameplayfix_upwardvelocityclearsongroundflag 0\nsv_gameplayfix_blowupfallenzombies 0\n\n");
+ // hipnotic mission pack has issues in their 'friendly monster' ai, which seem to attempt to attack themselves for some reason when findradius() returns non-solid entities.
+ // hipnotic mission pack has issues with bobbing water entities 'jittering' between different heights on alternate frames at the default 0.0138889 ticrate, 0.02 avoids this issue
+ // hipnotic mission pack has issues in their proximity mine sticking code, which causes them to bounce off.
+ if (gamemode == GAME_HIPNOTIC)
+ Cbuf_InsertText("\nsv_gameplayfix_blowupfallenzombies 0\nsys_ticrate 0.02\nsv_gameplayfix_slidemoveprojectiles 0\n\n");
+ // rogue mission pack has a guardian boss that does not wake up if findradius returns one of the entities around its spawn area
+ if (gamemode == GAME_ROGUE)
+ Cbuf_InsertText("\nsv_gameplayfix_findradiusdistancetobox 0\n\n");
+ if (gamemode == GAME_NEXUIZ)
+ Cbuf_InsertText("\nsv_gameplayfix_q2airaccelerate 1\nsv_gameplayfix_stepmultipletimes 1\n\n");
+ if (gamemode == GAME_TENEBRAE)
+ Cbuf_InsertText("\nr_shadow_gloss 2\nr_shadow_bumpscale_basetexture 4\n\n");
+ // Steel Storm: Burning Retribution csqc misinterprets CSQC_InputEvent if type is a value other than 0 or 1
+ if (gamemode == GAME_STEELSTORM)
+ Cbuf_InsertText("\ncl_csqc_generatemousemoveevents 0\n\n");
+ }
+}
+
+/*
+===============
+Cmd_Exec_f
+===============
+*/
+static void Cmd_Exec_f (void)
+{
+ fssearch_t *s;
+ int i;
+
+ if (Cmd_Argc () != 2)
+ {
+ Con_Print("exec <filename> : execute a script file\n");
+ return;
+ }
+
+ s = FS_Search(Cmd_Argv(1), true, true);
+ if(!s || !s->numfilenames)
+ {
+ Con_Printf("couldn't exec %s\n",Cmd_Argv(1));
+ return;
+ }
+
+ for(i = 0; i < s->numfilenames; ++i)
+ Cmd_Exec(s->filenames[i]);
+
+ FS_FreeSearch(s);
}
cmd_text.data = cmd_text_buf;
cmd_text.maxsize = sizeof(cmd_text_buf);
cmd_text.cursize = 0;
+
+ if (Thread_HasThreads())
+ cmd_text_mutex = Thread_CreateMutex();
}
void Cmd_Init_Commands (void)
*/
void Cmd_Shutdown(void)
{
+ if (cmd_text_mutex)
+ Thread_DestroyMutex(cmd_text_mutex);
+ cmd_text_mutex = NULL;
+
Mem_FreePool(&cmd_mempool);
}
FIXME: lookupnoadd the token to speed search?
============
*/
-void Cmd_ExecuteString (const char *text, cmd_source_t src)
+void Cmd_ExecuteString (const char *text, cmd_source_t src, qboolean lockmutex)
{
int oldpos;
int found;
cmd_function_t *cmd;
cmdalias_t *a;
+ if (lockmutex)
+ Cbuf_LockThreadMutex();
oldpos = cmd_tokenizebufferpos;
cmd_source = src;
found = false;
// execute the command line
if (!Cmd_Argc())
- {
- cmd_tokenizebufferpos = oldpos;
- return; // no tokens
- }
+ goto done; // no tokens
// check functions
for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
if (!strcasecmp (cmd_argv[0],cmd->name))
{
if (cmd->csqcfunc && CL_VM_ConsoleCommand (text)) //[515]: csqc
- return;
+ goto done;
switch (src)
{
case src_command:
if (cmd->clientfunction)
{
cmd->clientfunction ();
- cmd_tokenizebufferpos = oldpos;
- return;
+ goto done;
}
break;
}
if (cmd_source == src_client)
{
Con_Printf("player \"%s\" tried to %s\n", host_client->name, text);
- cmd_tokenizebufferpos = oldpos;
- return;
+ goto done;
}
// check alias
if (!strcasecmp (cmd_argv[0], a->name))
{
Cmd_ExecuteAlias(a);
- cmd_tokenizebufferpos = oldpos;
- return;
+ goto done;
}
}
if(found) // if the command was hooked and found, all is good
- {
- cmd_tokenizebufferpos = oldpos;
- return;
- }
+ goto done;
// check cvars
if (!Cvar_Command () && host_framecount > 0)
Con_Printf("Unknown command \"%s\"\n", Cmd_Argv(0));
+done:
cmd_tokenizebufferpos = oldpos;
+ if (lockmutex)
+ Cbuf_UnlockThreadMutex();
}