From: divverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Date: Sun, 15 Apr 2007 20:01:38 +0000 (+0000)
Subject: New console commands sv_cmd, menu_cmd, cl_cmd, that call GameCommand(string s) in... 
X-Git-Tag: xonotic-v0.1.0preview~3333
X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=10335c4c27003a165ae9c4557447c9bd109d0623;p=xonotic%2Fdarkplaces.git

New console commands sv_cmd, menu_cmd, cl_cmd, that call GameCommand(string s) in the server, menu, client program with the remainder of the command line as argument. Extension: DP_QC_CMD for all of them, DP_SV_CMD for sv_cmd.



git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@7097 d7cf8633-e32d-0410-b094-e92efae38249
---

diff --git a/mvm_cmds.c b/mvm_cmds.c
index a18d71f5..1a9a84f3 100644
--- a/mvm_cmds.c
+++ b/mvm_cmds.c
@@ -11,7 +11,9 @@ char *vm_m_extensions =
 "DP_QC_STRFTIME "
 "DP_QC_STRINGCOLORFUNCTIONS "
 "DP_QC_TOKENIZEBYSEPARATOR "
-"DP_QC_UNLIMITEDTEMPSTRINGS";
+"DP_QC_UNLIMITEDTEMPSTRINGS "
+"DP_QC_CMD "
+;
 
 /*
 =========
diff --git a/progsvm.h b/progsvm.h
index 87806d74..d8eb4953 100644
--- a/progsvm.h
+++ b/progsvm.h
@@ -256,6 +256,7 @@ typedef struct prvm_prog_funcoffsets_s
 	func_t SV_ChangeTeam; // ssqc
 	func_t SV_ParseClientCommand; // ssqc
 	func_t SV_PlayerPhysics; // ssqc
+	func_t GameCommand; // any
 
 	// menu qc only uses some functions, nothing else
 	func_t m_display; // mqc
diff --git a/prvm_edict.c b/prvm_edict.c
index 8a97b425..c7429950 100644
--- a/prvm_edict.c
+++ b/prvm_edict.c
@@ -38,6 +38,8 @@ cvar_t prvm_traceqc = {0, "prvm_traceqc", "0", "prints every QuakeC statement as
 // LordHavoc: counts usage of each QuakeC statement
 cvar_t prvm_statementprofiling = {0, "prvm_statementprofiling", "0", "counts how many times each QuakeC statement has been executed, these counts are displayed in prvm_printfunction output (if enabled)"};
 
+extern sizebuf_t vm_tempstringsbuf;
+
 //============================================================================
 // mempool handling
 
@@ -985,6 +987,71 @@ qboolean PRVM_ED_ParseEpair(prvm_edict_t *ent, ddef_t *key, const char *s)
 	return true;
 }
 
+/*
+=============
+PRVM_GameCommand_f
+
+Console command to send a string to QC function GameCommand of the
+indicated progs
+
+Usage:
+  sv_cmd adminmsg 3 "do not teamkill"
+  cl_cmd someclientcommand
+  menu_cmd somemenucommand
+
+All progs can support this extension; sg calls it in server QC, cg in client
+QC, mg in menu QC.
+=============
+*/
+void PRVM_GameCommand(const char *whichprogs, const char *whichcmd)
+{
+	if(Cmd_Argc() < 1)
+	{
+		Con_Printf("%s text...\n", whichcmd);
+		return;
+	}
+
+	PRVM_Begin;
+	if(!PRVM_SetProgFromString(whichprogs))
+	// note: this is not PRVM_SetProg because that one aborts "hard" using PRVM_Error
+	// also, it makes printing error messages easier!
+	{
+		Con_Printf("%s program not loaded.\n", whichprogs);
+		return;
+	}
+
+	if(!prog->funcoffsets.GameCommand)
+	{
+		Con_Printf("%s program do not support GameCommand!\n", whichprogs);
+	}
+	else
+	{
+		int restorevm_tempstringsbuf_cursize;
+		const char *s;
+
+		s = Cmd_Args();
+
+		restorevm_tempstringsbuf_cursize = vm_tempstringsbuf.cursize;
+		PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(s ? s : "");
+		PRVM_ExecuteProgram (prog->funcoffsets.GameCommand, "QC function GameCommand is missing");
+		vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
+	}
+
+	PRVM_End;
+}
+void PRVM_GameCommand_Server_f(void)
+{
+	PRVM_GameCommand("server", "sv_cmd");
+}
+void PRVM_GameCommand_Client_f(void)
+{
+	PRVM_GameCommand("client", "cl_cmd");
+}
+void PRVM_GameCommand_Menu_f(void)
+{
+	PRVM_GameCommand("menu", "menu_cmd");
+}
+
 /*
 =============
 PRVM_ED_EdictSet_f
@@ -1331,6 +1398,7 @@ void PRVM_FindOffsets(void)
 	prog->funcoffsets.SV_ChangeTeam                   = PRVM_ED_FindFunctionOffset("SV_ChangeTeam");
 	prog->funcoffsets.SV_ParseClientCommand           = PRVM_ED_FindFunctionOffset("SV_ParseClientCommand");
 	prog->funcoffsets.SV_PlayerPhysics                = PRVM_ED_FindFunctionOffset("SV_PlayerPhysics");
+	prog->funcoffsets.GameCommand                     = PRVM_ED_FindFunctionOffset("GameCommand");
 	prog->globaloffsets.SV_InitCmd                    = PRVM_ED_FindGlobalOffset("SV_InitCmd");
 	prog->globaloffsets.self                          = PRVM_ED_FindGlobalOffset("self");
 	prog->globaloffsets.time                          = PRVM_ED_FindGlobalOffset("time");
@@ -1910,6 +1978,9 @@ void PRVM_Init (void)
 	Cmd_AddCommand ("prvm_globalset", PRVM_GlobalSet_f, "sets value of a specified global variable in the selected VM (server, client, menu)");
 	Cmd_AddCommand ("prvm_edictset", PRVM_ED_EdictSet_f, "changes value of a specified property of a specified entity in the selected VM (server, client, menu)");
 	Cmd_AddCommand ("prvm_printfunction", PRVM_PrintFunction_f, "prints a disassembly (QuakeC instructions) of the specified function in the selected VM (server, client, menu)");
+	Cmd_AddCommand ("cl_cmd", PRVM_GameCommand_Client_f, "calls the client QC function GameCommand with the supplied string as argument");
+	Cmd_AddCommand ("menu_cmd", PRVM_GameCommand_Menu_f, "calls the menu QC function GameCommand with the supplied string as argument");
+	Cmd_AddCommand ("sv_cmd", PRVM_GameCommand_Server_f, "calls the server QC function GameCommand with the supplied string as argument");
 	// LordHavoc: optional runtime bounds checking (speed drain, but worth it for security, on by default - breaks most QCCX features (used by CRMod and others))
 	Cvar_RegisterVariable (&prvm_boundscheck);
 	Cvar_RegisterVariable (&prvm_traceqc);
diff --git a/svvm_cmds.c b/svvm_cmds.c
index bbe14a77..cfe61808 100644
--- a/svvm_cmds.c
+++ b/svvm_cmds.c
@@ -132,6 +132,8 @@ char *vm_sv_extensions =
 "PRYDON_CLIENTCURSOR "
 "TENEBRAE_GFX_DLIGHTS "
 "TW_SV_STEPCONTROL "
+"DP_SV_CMD "
+"DP_QC_CMD "
 ;
 
 /*