Progs.dat can read client's vars?

Discuss programming in the QuakeC language.
ChOwW
Posts: 21
Joined: Sat Dec 03, 2011 1:20 pm

Progs.dat can read client's vars?

Post by ChOwW »

Hi everyone,

After writing some ideas I had in mind in QC, I am getting blocked on a specific problem, mostly about game security:

I would like to check if a client got a cvar value, and print it into my console.

Exemple :

Code: Select all

/*
=======
GetCVAR functions
Gets a client's cvar value (str / float).
=======
*/
string(string THISIS_CMDNESS) sGetCVAR = {    return ftos(cvar(THISIS_CMDNESS)) ;     }

float(string THISIS_CVAR_TA) fGetCVAR = {    return cvar(THISIS_CVAR_TA);     }

/*
-+=-+= MAIN PROGRAM
*/
void() main = {
log (other,self.netname);
log (other, "has currently a mycvarname value of ");
log (other,  sGetCVAR("mycvarname"));
log (other, "\n");
}
However, all it returns is the server's mycvarname value. Not very useful if I planned to know on a promod (best exemple) if a client's CVAR is not on an allowed value...

Do you have any hint of making this process possible?
(Of course, Vanilla GLQuake, much obliged)
frag.machine
Posts: 2126
Joined: Sat Nov 25, 2006 1:49 pm

Re: Progs.dat can read client's vars?

Post by frag.machine »

ChOwW wrote:Hi everyone,

After writing some ideas I had in mind in QC, I am getting blocked on a specific problem, mostly about game security:

I would like to check if a client got a cvar value, and print it into my console.

Exemple :

Code: Select all

/*
=======
GetCVAR functions
Gets a client's cvar value (str / float).
=======
*/
string(string THISIS_CMDNESS) sGetCVAR = {    return ftos(cvar(THISIS_CMDNESS)) ;     }

float(string THISIS_CVAR_TA) fGetCVAR = {    return cvar(THISIS_CVAR_TA);     }

/*
-+=-+= MAIN PROGRAM
*/
void() main = {
log (other,self.netname);
log (other, "has currently a mycvarname value of ");
log (other,  sGetCVAR("mycvarname"));
log (other, "\n");
}
However, all it returns is the server's mycvarname value. Not very useful if I planned to know on a promod (best exemple) if a client's CVAR is not on an allowed value...

Do you have any hint of making this process possible?
(Of course, Vanilla GLQuake, much obliged)

The very idea of client-side cvars implies, at least to me, that it should not affect gameplay.
If that's the case, it should be defined as a server side cvar, and the server setting would prevail.

What exactly are you trying to do ?
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Progs.dat can read client's vars?

Post by Spike »

theres two ways to do it.
1: csqc.
2: krimzon_sv_parseclientcommand and cvar expansion - stuffcmd(player, "cmd clientcvar $cvarname\n");
ChOwW
Posts: 21
Joined: Sat Dec 03, 2011 1:20 pm

Re: Progs.dat can read client's vars?

Post by ChOwW »

Well, for exemple, i want to check the values of the cvar "fov".

The idea would go in this way :

Code: Select all

 1- check the current fov value from the client.
2- check if that value is not under or above the given limits, lets say 50 and 130.
3- if those limits have been exceeded, make a stuffcmd to the client. 
Anyway, that second idea interests me a lot, Spike: as long as it is not csqc'd :P...
Cobalt
Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA
Contact:

Re: Progs.dat can read client's vars?

Post by Cobalt »

Afaik, there is no way to do this in plain vanilla qc. There were some other kinds of code that I saw years ago regarding the big endian architecture
that can compile in regular QC and they were used to blank out the IP addresses in the status command.....but not sure if they can do stuff like this or not. In legacy ctfbot, there is a feature called : ' Fixed FOV ' which when is set, merely uses stuffcmd to place the clients fov setting to be 90 in either post think or prethink for the player. CSQC may be a better way of accomplishing your requirements though.
Seven
Posts: 301
Joined: Sat Oct 06, 2007 8:49 pm
Location: Germany

Re: Progs.dat can read client's vars?

Post by Seven »

Hello Spike (or anybody else who can help me),

I need your helping hand on this issue:
I need to read a cvar´s value from the client. But I do not want to use CSQC for this.
So I tried your second suggestion from your above post.
I failed...

What I want to do is:
Read the value from the cvar: scr_centertime
And create a string with its content. Let´s name the string: foo

I will then change (independent from the string/value), scr_centertime to 10.
I will use this line for this:

Code: Select all

cvar_set ("scr_centertime", "10");
I only need to do this for a short time, because I want to centerprint a message, which is displayed 10 seconds.
After I printed my message, lets say:

Code: Select all

centerprint(self, "I need help \n");
I will reset the cvar back to its previous condition with:

Code: Select all

cvar_set ("scr_centertime", foo);
That is my plan.
So in other words, I need to be sure that the player has 10 seconds time to read a message (and not only the default scr_centertime --> 2 seconds).
I do not know any other way of displaying a message longer than 2 seconds (independent to the print cvars values).


Can you tell me another way, or help me to get my above described plan realized ?
I fail to read the string out of the cvar to set it back to previous condition :( because I do not want to manipulate the palyers config settings.

This is what I tried to read the cvar´s value (using FRIK_FILE):

Code: Select all

substring("stuffcmd(self, cmd clientcvar $scr_centertime)", -1, 1);
because using the line you provided inside the substring call brings up a compile error (The ' " ' are too much):

Code: Select all

substring("stuffcmd(self, "cmd clientcvar $scr_centertime\n")", -1, 2);
So I am stuck...

Thank you or anybody else, who is able to help me with this issue.
Last edited by Seven on Thu Jul 26, 2012 9:53 pm, edited 1 time in total.
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Progs.dat can read client's vars?

Post by Baker »

Seven, there isn't a way to read a client's variables. You can, however, let the client restore them ...

I believe this works for DarkPlaces.
alias save_value"set savedcentertime $scr_centertime" // Save original setting
alias restore_value "set scr_centertime $savedcentertime" // Restore original setting
save_value// Have it execute upon connect
Using the above, you can do a stuffcmd "save_value; scr_centertime 10" and do a stuffcmd "restore_value" to allow the client to reset to whatever it was before.

Spike will frown on this a bit because if you quit the game (or disconnect from a server), it will not restore scr_centertime.

But this should work in DarkPlaces (it doesn't work in standard Quake) and is the best you can do without getting super-complex (as far as I know ...).
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Progs.dat can read client's vars?

Post by Spike »

stuffcmd(self, "this string has a \" in it");


stuffcmd has no return value. like I said, you need to use KRIMZON_SV_PARSECLIENTCOMMAND in order to read it, which will only happen after a delay, because it needs to basically bounce off the client before the server can actually see the response. QC does not have blocking calls like that, it would be too easy to exploit.
Seven
Posts: 301
Joined: Sat Oct 06, 2007 8:49 pm
Location: Germany

Re: Progs.dat can read client's vars?

Post by Seven »

Thank you Baker for your suggestion.
Where would I use these alias lines ? Is this inside QC or autoexec ? I have not seen such line formats yet...

If your method (which I still not fully understood) can only restore the original cvar setting after map change,
it would not be good, because then all other original Quake´s centerprint messages in that map would also last 10 sec.


Hello Spike,
I was hoping that you could maybe tell me how to make use of KRIMZON_SV_PARSECLIENTCOMMAND in this context. I never made use of this extension before and dont know how it works.
I am a person who needs to see an example to learn it and beeing able to convert it to different things.
That makes it sometimes hard using a new extension without knowing how the syntax in a used condition is.

Thank you all for your help and efforts.
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Progs.dat can read client's vars?

Post by Baker »

Seven wrote:Thank you Baker for your suggestion.
Where would I use these alias lines ? Is this inside QC or autoexec ?
You'd put the aliases in autoexec.cfg in your mod gamedir since I imagine you are making essentially an offline mod. No it doesn't only reset on map change, it resets when your QuakeC sends the client the "restorefov" command via stuffcmd [if they disconnect or quit, that stuffcmd never occurs to reset it].

See this thread ... http://forums.inside3d.com/viewtopic.php?t=1200

My answer is easy, mostly good, but not "proper". My answer is slightly better than resetting someone to "3", but not by much really.

Whatever Spike is going to tell you is the most proper answer and best for your long-term interests.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Progs.dat can read client's vars?

Post by Spike »

seven:
a 'client command' is basically a reverse stuffcmd, but a bit more restricted (ie: you can't send 'quit'...). If you use any of the cheats like noclip, god, give, notarget, fly, kill, etc, the client sends a clc_clientcmd message with the command its trying to issue directly embedded as a string.
The "cmd" console command takes its arguments and uses that as the complete clientcmd string.
This means that "cmd god" is directly equivelent to "god" (just without the client being able to intercept it).
"cmd name foo" for instance, will change your name on the server without affecting your name on the next server/map/config.
When the server receives a clc_clientcmd, it walks through some list of 'known' strings and invokes the first match it finds, and issues some console print back to the issuer if its not recognised.

KRIMZON_SV_PARSECLIENTCOMMAND basically allows you to intercept that clc_clientcmd before the server tries to execute it. This allows you to a) add alternative commands. b) block cheats. c) hack with the 'say' command's string etc.

Anyway, its fairly simple:

Code: Select all

void(string str) SV_ParseClientCommand =
{
    float numargs = tokenize(str);
    if (argv(0) == "mynewcommand")
        dosomething();
    else
        clientcommand(self, str);
};
The vital thing to remember is that the clientcommand call MUST BE CALLED FOR ALL UNRECOGNISED COMMANDS. Failing to call it in such cases _will_ result in problems, like downloads failing or even being unable to connect to the server.
The exact requirements of each command vary a little, most commands can be safely ignored, like god, say etc, its only the weird ones like prespaw/spawn/begin/signon.
Note that you can also call clientcommand from random bits of your own code. This allows you to get the server to run its regular handling, so gives you a practical way to eg change a player's name/colour without having to depend upon potentially cheatable/savable stuffcmds.

tokenize/argv are part of this extension rather than another one. argv requires tokenize to have previously been called. argv(0) will then return the intial token, argv(1) will return the first argument, etc. enclose the argument in quotes if you want argv to ever return a string with a space in it.

note that qc string equality is case sensitive, and the tokenize command was greatly butchered in dp to serve as a random parser and thus will not exactly match how the server tokenizes the string, but this is not relevent for your use-case.


So, for your use-case, you want to issue that 'cmd' stuffcmd. This causes the client to issue a clc_clientcmd, which the ssqc can parse with that function I pasted above. If you stuffcmd(self, "cmd clientcvar ct $scr_centertime\n"); then you have:
if (argv(0) == "clientcvar" && argv(1) == "ct") self.scr_centertime = atof(argv(2)); else <some code to call clientcommand>.
Beware that stuffcmd is not instant, nor are any clcs. So the time between the stuffcmd and the server getting the response can vary, even up to a second or beyond. Note that stuffcmd+cmd both send reliably, so you can override the client's current value as a stuffcmd on the very next line (or even as part of the very same stuffcmd!), you just won't be able to restore it until you know what to restore it to. Avoid sending multiple queries in order to avoid overwriting the user's choice with a value you sent.

This cannot be used for cheat prevention as a modified client can easily handle your stuffcmd specifically and send an allowed response while still using a cheaty value in the cvar (the same is true of querying it through csqc too).
CSQC does have the upper hand in that it has a 'shutdown' function within which cvars can be reliably restored.


and yes, you can use editable aliases to restore things, but that's bad as it requires lots of effort from the user instead of just using the client's menus to their heart's content (and they might not have your default cfg (using automatic mod downloads) and thus will not get anything restored at all).
Seven
Posts: 301
Joined: Sat Oct 06, 2007 8:49 pm
Location: Germany

Re: Progs.dat can read client's vars?

Post by Seven »

Thank you very much Spike and Baker for your detailed answers.
I now understand that it is in general not a good idea to try to read client cvars from the server side.
That is why QC-mods should not mess with client cvars at all.
I will rethink my idea and most probably skip it.

Thank you again for your lessons.
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Progs.dat can read client's vars?

Post by Baker »

Seven, the "right" way to do what you want to do here.

Centerprint it 3 times, 2.9 seconds apart. Then you don't have to mess with anyone's cvars. And if they have a dumb scr_centerprinttime value like 1, that's on them.

[Or find some other way to display your message. Or eliminate the idea entirely :D Maybe you should say what this idea is?]
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Seven
Posts: 301
Joined: Sat Oct 06, 2007 8:49 pm
Location: Germany

Re: Progs.dat can read client's vars?

Post by Seven »

Hello Baker,

yes, I also thought about why not use a small function with a centerprint loop and a nextthink value to cover the 10 sec.
But I thought that centerprints bring automagically that "notify" sound with them. Just like the one from the start map skill settings message.
It always "beeps" :)
But then I looked into the maps ent file and discovered that the sound is not engine sided hardcoded to centerprints.
There are even 3 possible sounds available.
Default is without sounds, so this "workaround" should be an easy way for doing it.
Thank you for your suggestion Baker.

It has something to do with the "small mod compilation". A SSQC sided version of a map introduction text.
But the more I think about it, the more I think that this would annoy people.
Maybe I should switch to bprint instead (which is only visible in console for the interested user).
But who knows for which other purpose this thing will end...
Anyhow, it helped me to learn a bit more about QC. And that was defenitely worth the trouble.
Thank you again Spike and Baker for sharing your knowledge to the ones in need.

Best wishes,
Seven
Seven
Posts: 301
Joined: Sat Oct 06, 2007 8:49 pm
Location: Germany

Re: Progs.dat can read client's vars?

Post by Seven »

Hello,

I found a easy solution to the read a client cvar value via SSQC.
It was there all the time, but we didnt see it.

It is possible to read for example the "FOV" value or in my above example the value of "scr_centertime" or any other cvar value with the help of this dpexetension:

Code: Select all

//DP_QC_CVAR_STRING
//idea: VorteX
//DarkPlaces implementation: VorteX, LordHavoc
//builtin definitions:
string(string s) cvar_string = #448;
//description:
//returns the value of a cvar, as a tempstring.
You can then check/compare that cvar value and do the things you want to do with it.
You can then use another value for that cvar via "cvar_set ("cvar_name", new_value)"
In the end you can reset the original cvar value if desired.


Be aware, that this is of course something a mod should not do (to manipulate a client cvar value).
It is an evil hack.
But at least it is possible this way.

You can also do other things with a client cvar in SSQC, with these dpextensions:
DP_QC_CVAR_DEFSTRING //returns the default value of a cvar
DP_QC_CVAR_DESCRIPTION //returns the description of a cvar
DP_QC_CVAR_TYPE //returns the type of a cvar

Best wishes,
Seven
Post Reply