Absolute beginners guide to sending clients pk3s

The full title of this tutorial should be “Absolute beginners guide to getting FTE clients to automatically download the files they need, while allowing older (non-CSQC compatible) clients to connect without crashing”. Or “How to make a modern Quake engine (CSQC, shaders, particles, iqms etc ) compatible with older clients, so that they can also connect”.

Traditionally. by using precache_ functions, and making sure the files are on your server, Quake clients (eg Fuhquake, EZQuake) automatically download the files below.

FILES TYPE ONE: Files which Quake clients automatically download from Quake servers
1. models (*.mdl) / precache_model()
2. iqms (*iqm) / precache_model()
3. the iqm’s image files (*tga, *.png, *.jpg) / precache_pic()
4. particle scripts (*.cfg)  /particleeffectnum()
5. images (*tga, *.png, *.jpg) /precache_pic()
6. maps (*.bsp)/ automacically downloaded when connecting
7. csprogs.dat/ automacically downloaded when connecting
8. sounds (*.wav) / precache_sound()
9. charset / precache_pic()
10. skyboxes (image files)/precache_pic()

But not all files can be sent in this way. Here’s a list of files which (normally) have to be manually downloaded by players:

FILES TYPE TWO: Files which Quake clients DO NOT automatically download from Quake servers
1. real time lighting files (*.rtlights)
2.  *.lit files
3.  *.lux files
4. shaders (*.shader)
5. glsl file (*.glsl)
6. default.cfg
7. qwprogs.dat // only needed for single player games

Normally these files (ie both the above lists) are ALL included in one zip (which also contains the client), and are automatically extracted into the right directories when unzipping. But what if your game runs on a (dedicated) multiplayer server which regularly updates content?

OVERVIEW:
The method described here is to zip all the ‘Type Two’ files into a pk3, include a ‘special file’ (as explained below), upload the pk3 to the FTE server, and reference the ‘special file’ in the qc. The server sends the pk3 to FTE clients … and older clients are simply ignored! Here’s the details:

THE METHOD
Step 1. Make a sub folder in your game’s root folder, lets call it ‘mypk3dir’

Step 2. Make subdirectories in mypk3dir

c:/Quake/your_mod_name/mypk3dir/particles
c:/Quake/your_mod_name/mypk3dir/scripts
c:/Quake/your_mod_name/mypk3dir/textures
c:/Quake/your_mod_name/mypk3dir/lits

etc..

Step 3. Put a all your new files in their corresponding directory in the mypk3dir folder. TIP: Make sure you include any textures you reference in your shaders, or in any qc script embedded in functions such as shaderforname().

Step 4. When everything is working and you’re ready to make the pk3, make a text file, and at the top put:

[code]
cmd “mypk3_is_sexy” // something unique
[/code]

Save the file as “mypk3dir_confirm.cfg”, and save it in the mypk3dir directory.

Step 5. Go to the mypk3dir directory, select everything, and zip it; lets name the file ‘my_package’. A file called my_package.zip will be created.  Note: just to be crystal clear, you selected everything IN mypk3dir, NOT mypk3dir itself. ie there is no mypk3dir folder in my_package.zip. ie. the root directory of my_package.zip has your folders:

/particles
/scripts
/textures
/lits

and the “mypk3dir_confirm.cfg” file.

Step 5. Change the extension from ‘zip’ to ‘pk3’, so the file is now called ‘my_package.pk3’

Step 6. Upload my_package.pk3 to your server and put it in: Quake/modname

Step 7. The QuakeC part
In the qc run the following code when someone connects, eg somewhere in ClientConnect():

[code]
// returns the name of the pak the file is located
string file_to_check = “mypk3dir_confirm.cfg”;
string pk3_name = whichpack(file_to_check); ; // whichpack makes the server search for the file “mypk3dir_confirm.cfg”, and returns a string, which is the name of the pk3 in which “mypk3dir_confirm.cfg” is contained.

// Is the string containing the name of the pak where “mypk3dir_confirm.cfg” is located NOT empty?
// ie was “mypk3dir_confirm.cfg” found on the server?
if(pk3_name != “”)
{
dprint(sprintf(“%s found in %s\n”, file_to_check, pk3_name));
stuffcmd (self, sprintf(“exec %s\n”, file_to_check)); // Make the clients execute the run mypk3dir_confirm.cfg script
}
else
{
dprint(sprintf(“%s NOT found in a pk3 on the server\n”, file_to_check));
}

[/code]

HOW IT WORKS
When a client connects, whichpack(“mypk3dir_confirm.cfg”); will run, and the server will automatically tell the client that the ‘returned package’ (in this case “my_package.pk3”) should be pre-downloaded and used. This will force clients (specifically FTE clients) to download my_package.pk3 (if they don’t already have it) from the server.

Step 8: Confirming that clients got the file:

[code]
void(string in) SV_ParseClientCommand =
{
.
.

tokenize(in);

if(argv(0) == “mypk3_is_sexy”)
{
dprint(self.netname, ” has my_package.pk3\n”);
sprint(self, PRINT_HIGH, “my_package.pk3 detected!!!\n”);
}
[/code]

When clients execute the ‘mypk3dir_confirm.cfg’ script (as described in step 7), it will be as if they typed “cmd mypk3_is_sexy” at their console, and the server will run SV_ParseClientCommand and be able to detect the message, and let you know that ‘mypk3dir_confirm.cfg’ must exist on their computer, therefore they did receive, and are accessing the files in my_package.pk3.

TROUBLESHOOTING:

Q1: What if the pk3 is massive, and I need to update one line on one script? Do I have to remake the whole thing, and players have to redownload it just because one line in one tiny file has changed?
A: If that’s the case, then don’t use one BIG pk3 for ‘regularly updated’ files, make a special tiny pk3’s which only have (tiny) scripts. Remember to give the updated versions new (and unique!) names eg if you update “scripts/foo.cfg”, name the update “scripts/foo2.cfg”. Similarly, zip it into a new pk3 called eg “my_package2.pk3”)

Q2: How can I confirm that the server knows that a files is in a pk3?
A: Type “flocate scripts/foo.cfg” at the console

Q3: I followed these instructions, but the (eg) new particles aren’t running!
A: You need to change maps, though when testing, I had to restart my client to get it to run the particle script in the pk3.

[TO DO: What if there is a conflict between a (eg) shader in foo.pk3 and foo3.pk3 ie one w the same name?]

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>