Administrator guide

Downloads and PK3 references

How players get the files your server needs, and how the server decides which files those are.

Automatic PK3 downloads

TaystJK can serve required PK3 files over HTTP, and over the older UDP downloader for clients that cannot use HTTP. The Docker image’s server.cfg turns both on:

seta sv_allowDownload 1
seta sv_httpDownloads 1
seta sv_httpServerPort 18200

A TaystJK client uses HTTP whenever the server advertises it (cl_main.cpp), and if an HTTP download fails it disconnects with a download error rather than retrying over UDP (cl_parse.cpp). The UDP downloader serves clients without HTTP support, such as OpenJK, EternalJK and the original game, and only while sv_allowDownload is on (sv_client.cpp).

Built-in HTTP server

These settings enable HTTP on TCP 18200. Forward that TCP port through NAT and allow it through the host firewall, independently of UDP 29070. With sv_httpServerPort 0, the server selects the first free port from 18200 through 18215; a fixed port is easier to expose from a container or router.

Clients need cl_allowDownload 1, which is the default. By default TaystJK asks before downloading, saves each download with a dl_ prefix that is only loaded while a server references it, and adds a checksum to the name when a file of that name already exists, so content from one server does not silently replace content used elsewhere. See a map I downloaded is missing everywhere else.

External HTTP server

Instead of the built-in server, set sv_httpServerPort to an http:// URL that points at a web root laid out like GameData:

seta sv_httpDownloads 1
seta sv_httpServerPort "http://downloads.example.org/jka"

For a referenced file named taystjk/maps-pack.pk3, the web server must therefore serve http://downloads.example.org/jka/taystjk/maps-pack.pk3. The current implementation accepts http://, not https://; put a compatible HTTP endpoint in front of the files if you use an external host.

Do not put spaces or @ in downloadable PK3 filenames. The download list sent to clients is one string with @ between its entries, so the server leaves out any PK3 whose name contains one (files.cpp), and a space splits the name in two. After changing downloadable content, restart the map and check the reference list before inviting players.

PK3 referencing and reflists

Only referenced PK3s are offered to clients. The server works out which PK3s are referenced each time it loads a map (sv_init.cpp). Clients receive the list when they connect and again at every map change, and download any listed PK3 they lack before entering the game (cl_parse.cpp). Nothing downloads during a map.

TaystJK automatically references a PK3 when:

  1. The current map’s BSP is loaded from it. A map PK3 in base is offered once the server is on that map.
  2. It holds a client module the engine looks for: vm/cgame.qvm, vm/ui.qvm, cgamex86.dll or uix86.dll (files.cpp).
  3. It is in a directory other than base. Every PK3 in the mod directory is offered on every map, whether or not anything loads from it (files.cpp). Any directory whose name starts with base, such as basejka, counts as base here.

Any other PK3 in base, such as a model or sound pack, is never offered unless it is on the force list.

TaystJK does not run cgame.qvm or ui.qvm; its modules are native libraries, .dll on Windows, .so on Linux and .dylib on macOS. The check still looks for those four names because they are what stock clients load. A PK3 that holds only other module names, such as cgamex86_64.dll, or only client assets, is not referenced on its own; add it to ref_forcelist.txt.

Run sv_referencedPakNames in the server console to inspect the current result. Reflist files let you correct the automatic decision:

File Effect
ref_forcelist.txt Offer each listed PK3 on every map. It only matters for PK3s in base, since the mod directory’s PK3s are offered anyway.
ref_blacklist.txt Never offer the listed PK3s, such as server-only files in the mod directory.
ref_whitelist.txt Offer only the listed PK3s. While this file exists, every PK3 missing from it is never offered, maps included.

A PK3 whose name starts with noDL is never offered either, without any list.

When a PK3 matches more than one rule, the first match in this order wins (files.cpp):

  1. Not on the whitelist, when one exists: never offered.
  2. On the blacklist: never offered.
  3. Name starts with noDL: never offered.
  4. On the force list: offered.

So a forced PK3 must also be on the whitelist if you use one, and a PK3 on both the force list and the blacklist is not offered. A whitelist and blacklist together work, but the blacklist can then only remove PK3s the whitelist allowed; use one or the other.

Blacklisting a map’s PK3 also stops it being offered, so players who do not have that map cannot join while the server runs it.

Place reflists in the server’s mod directory, which is taystjk/ unless you run another mod, or in base/. Use one game-directory/pak-name.pk3 path per line, with no leading spaces; case does not matter:

base/models-pack.pk3
base/sounds-pack.pk3

The server reads the lists when it loads a map (files.cpp, sv_init.cpp), so an edit applies from the next map change. A force list offers a file; it does not remove the client’s download confirmation. The server config generator can write the force list and blacklist for you.

The behavior is inherited from JK2MV; its wiki has useful background on downloaded files, HTTP downloads, and PK3 referencing.

What sv_pure checks

TaystJK’s bundled server.cfg leaves sv_pure at 0 (server.cfg), and the server config generator does not turn it on. This section is for servers that already run it.

sv_pure 1 checks the client’s PK3 checksums against the server’s expected files. The module checks specifically look for cgamex86.dll and uix86.dll inside PK3s (sv_client.cpp).

TaystJK loads native modules as loose libraries. Its build installs them that way (cgame install rules, UI install rules). Before loading a module, FS_FindPureDLL reads the corresponding legacy x86.dll so other platforms and architectures can account for the expected pure-server PK3 checksums (files.cpp, vm.cpp).

Loose native libraries do not fail these checks by themselves. If clients fail pure validation, check that the server and clients have the expected PK3s, including the legacy DLL entries used for these checks. Packing an x64 or ARM native library into a PK3 does not satisfy a check for an x86.dll entry.

sv_pure does not constrain TaystJK clients by default

TaystJK clients skip the pure restriction unless the player turns it off. The client-side cvar cl_pureBaseBypass defaults to 1 (cl_main.cpp), and the client applies it on every connection, whatever gamename your server reports (cl_parse.cpp). Its own description speaks of “pure base servers”, which is the case it was written for, but the code does not check what the server runs.

Two things happen at once. The client marks the base assets pak as referenced so the checksums it reports back look like a stock client’s (files.cpp), and it skips loading your pak list altogether. This leaves it with no list to restrict against, so every pak it has is treated as allowed (FS_PakIsPure).

The effect is that the client authenticates as pure while still loading its own assets: emoji, cosmetics, HUD files and any other PK3 the player has installed. This is deliberate: it lets TaystJK’s client-side additions work on pure servers, but it means sv_pure is not an asset-parity guarantee for TaystJK clients. A player who sets cl_pureBaseBypass 0 gets the normal restriction again from their next connection. A server cannot set it for them: it is an ordinary archived cvar, and the client discards server values for those (Cvar_Server_Set).

Last changed History Edit this page on GitHub