Page 1 of 1

KRIMZON_SV_PARSECLIENTCOMMAND

Posted: Sat Aug 31, 2013 9:32 pm
by Cobalt
Happen to find this code in Lord Havocs DP mod. It was declared a little differently:

void SV_ParseClientCommand (string s)

Rather than how it reads now, else it would not compile. Im not understanding how its called unless its always being called, therefore the (s) string will be the text parsed after the client hits enter after typing text in the console? I tried a rough test using this code, and it seems not to work, unless I have to call this every frame , say in startframe? Finally if I read this right, we are merely aliasing one string for another string that I guess is predefined in the engine or using the alias command?

Code: Select all

//KRIMZON_SV_PARSECLIENTCOMMAND test
void  (string s) SV_ParseClientCommand =
{
	local float args;
	local string c;
	args = tokenize(s);
	c = argv(0);
	// edit this to do what you want with the received commands
	     if (c == "time") clientcommand(self, s);
	else if (c == "say_team") clientcommand(self, s);
	else if (c == "name") clientcommand(self, s);
	else if (c == "color") clientcommand(self, s);
	else if (c == "tell") clientcommand(self, s);
	else if (c == "kill") clientcommand(self, s);
	else if (c == "status") clientcommand(self, s);
	else if (c == "pause") clientcommand(self, s);
	else if (c == "kick") clientcommand(self, s);
	else if (c == "ping") clientcommand(self, s);
	else if (c == "ban") clientcommand(self, s);
	else if (c == "pmodel") clientcommand(self, s);
	else if (c == "god") clientcommand(self, s);
	else if (c == "fly") clientcommand(self, s);
	else if (c == "noclip") clientcommand(self, s);
	else if (c == "notarget") clientcommand(self, s);
	else if (c == "give") clientcommand(self, s);
	// please keep this fallback incase new engine commands are added
	else clientcommand(self, s);
};

Re: KRIMZON_SV_PARSECLIENTCOMMAND

Posted: Sat Aug 31, 2013 10:22 pm
by Spike
cmd foo
->"foo"

remember that its parsed on the server, and the server doesn't see all the cvar etc commands the user enters. it only sees the commands that are actually sent to it.
'cmd' sends its arguments as a string, allowing you to send arbitary client commands (eg: csqc can localcmd("cmd foo\n") to send messages to the server).
say, say_team, kill, etc, commands automatically forward themselves to the server too, as client commands.

that test code you pasted is basically a no-op. add a print so that you know something is happening. or just return instantly and puzzle over why you no longer have a name set, etc.

Re: KRIMZON_SV_PARSECLIENTCOMMAND

Posted: Sun Sep 01, 2013 12:18 am
by Cobalt
Hm still kinda lost. From what I read about the related built-ins :

Code: Select all

//KRIMZON_SV_PARSECLIENTCOMMAND
//idea: KrimZon
//darkplaces implementation: KrimZon, LordHavoc
//engine-called QC prototypes:
//void(string s) SV_ParseClientCommand;
//builtin definitions:
void(entity e, string s) clientcommand = #440;
float(string s) tokenize = #441;
string(float n) argv = #442;
//description:
//provides QC the ability to completely control server interpretation of client commands ("say" and "color" for example, clientcommand is necessary for this and substring (FRIK_FILE) is useful) as well as adding new commands (tokenize, argv, and stof (FRIK_FILE) are useful for this)), whenever a clc_stringcmd is received the QC function is called, and it is up to the QC to decide what (if anything) to do with it

clc_stringcmd, I am guessing is when something is typed into the con and enter is pressed? Is built in 440 called and self = client and string s is the string?
Spike wrote:cmd foo
->"foo"

remember that its parsed on the server, and the server doesn't see all the cvar etc commands the user enters. it only sees the commands that are actually sent to it.
'cmd' sends its arguments as a string, allowing you to send arbitary client commands (eg: csqc can localcmd("cmd foo\n") to send messages to the server).
say, say_team, kill, etc, commands automatically forward themselves to the server too, as client commands.

that test code you pasted is basically a no-op. add a print so that you know something is happening. or just return instantly and puzzle over why you no longer have a name set, etc.

Re: KRIMZON_SV_PARSECLIENTCOMMAND

Posted: Sun Sep 01, 2013 12:33 am
by Cobalt
Ok did more tests...seems when a valid command is entered, that viod () gets called, IE: color 5 2 for example. I was misunderstanding the operation as if you could add new commands , but it seems not to be able to do so.

Re: KRIMZON_SV_PARSECLIENTCOMMAND

Posted: Sun Sep 01, 2013 12:35 am
by Spike
clc_stringcmd is your clientcommand client-to-server message, containing a string.
think of it as a reverse stuffcmd. instead of the server asking the client to do things, it is the client asking the server to do things (like change its name). obviously, you don't have full console access with it, but the ssqc is allowed to see/block/intercept/change the text of the command.

if you do not define that function, the engine will internally treat it as if you defined it as:
void(string s) SV_ParseClientCommand =
{
clientcommand(self, s);
};

which basically causes the engine to use its normal clientcommand handler to handle the command.
as the command is just a string, you need to tokenize (ie: split up into tokens) the command string (aka: s) in order to see the first token and thus what the command is actually asking the ssqc/server to do.
tokenize says how many tokens there were, while argv gives you the text of each token.
you can actually call clientcommand from anywhere, so clientcommand(self, "say hello world"); will of course make the server think that the client wanted to say hello to the world.
so you can use it to block colour changes by noticing that its a colour change command and just ignoring it. and you can directly change player colours by using clientcommands instead of stuffcmds - basically have the server update colours instantly instead of bouncing the command off the client and hoping it doesn't try cheating.

remember, you can always stuffcmd(player, "alias hello \"cmd hello\"\n"); then when the user types 'hello' at the console, it fires off a client command to the server and the ssqc can handle it. this works in all clients, even vanilla, both nq and qw. actually handling it properly in the ssqc is where you need the extension.

Re: KRIMZON_SV_PARSECLIENTCOMMAND

Posted: Sun Sep 01, 2013 2:55 pm
by Cobalt
Interesting, gonna play with it later. One thing I did was put a bprint in the void so I know when its called, and when the player is dead, its calling the function like once per second. I thought maybe a stuffcmd would be giving it a false positive, but I'm not stuffing when player is dead anymore than during regular play. It does not seem suceptable to stuffcmds in any way it seems.

Re: KRIMZON_SV_PARSECLIENTCOMMAND

Posted: Wed Feb 12, 2014 8:44 pm
by Cobalt
Lets see, could we use this to have the server execute a changelevel? If I type in E1M2, it does a localcmd of changelevel e1m2 ?


UPDATE:

Ok, still confused by this function. I placed it in Client.qc at the very bottom - does it matter? Anyway, I put a brpint inside to know when its being called, and its only being called during the intermission, pressing tab (showscores) or when dead.... ? It seems to detect when I type in the color command with arguements like color 5 9 , then it will perform the assigned clientcommand......but seems its also performing the color command as well.


Ok, I found this link which explains you have to use "cmd" as a prefix on your console commands:

http://quakewiki.org/wiki/KRIMZON_SV_PARSECLIENTCOMMAND

Now its starting to make more sense.

Re: KRIMZON_SV_PARSECLIENTCOMMAND

Posted: Tue Jul 15, 2014 11:22 pm
by Cobalt
@Spike:

I also noticed during my tests that the client sends a string : "pings" when tab is pressed.

I dont seem to able to declare an exact alias type command with this unless its prefixed by : "cmd" first

IE: cmd [ string ]

Then you parse whatever that string is suppose to do thereafter.

Re: KRIMZON_SV_PARSECLIENTCOMMAND

Posted: Wed Jul 16, 2014 4:10 am
by Spike
what? you want all console commands like +left etc to bounce off the server before they're executed on the client? that would be laggy as hell.
also, the quit command would be quite exploitable.

Re: KRIMZON_SV_PARSECLIENTCOMMAND

Posted: Sat Nov 08, 2014 5:48 pm
by Cobalt
Ok made some headway with this function thanks to Spike.

Next issue, I want to intercept the "c" string like its doing and identify the "color" command that the client is sending to the server. So far I have it logging to the console something like this when the client connects:

^7 ‚ Typed: name Player
^7 Player‚ Typed: color 6 11

What I want to do is stof(6) in the color string and work with it localy. I suspect we use argv or something but not sure?

Re: KRIMZON_SV_PARSECLIENTCOMMAND

Posted: Sat Nov 08, 2014 9:07 pm
by Spike

Code: Select all

void(string commandstring) SV_ParseClientCommand =
{
	float argc = tokenize(commandstring);
	if (argv(0) == "color")
	{
		float top = stof(argv(1));
		float bottom = (argc>2)?stof(argv(2)):top;	//'color 4' should use 4 for both top AND bottom, instead of reading as 4,0
		bprint(sprintf("received+ignoring top colour = %g, bottom colour = %g\n", top, bottom));
	}
	else
		clientcommand(commandstring);	//mandatory
};
Side note: FTE additionally supports 0xRRGGBB for colours, but only with an explicit 0x. If you're overriding the bottom/team, but leaving the top colour unmodified, it is best to simply use argv(1) directly instead of stofing its result.