Generating MD5

From BFEditor

Jump to: navigation, search

Contents

MD5 for Battlefield in general

In order to have Battlefield check the content of clients joining a mod you need MD5 checksums. Known .md5 files are:

std_archive.md5

std_archive_mod.md5

archive.md5

std_archive.md5 and std_archive_mod.md5 both go into the main folder of the mod (for example Battlefield 2\mods\bf2\std_archive.md5). These files contain the checksums of any archive, with exception of level files, that is loaded into the game. There is one exception: std_archive.md5 does not contain the shader archive, if present, for the mod, while std_archive_mod.md5 does.

Reason: LooseEnd

The archive.md5 file can be found in the root folder of the currently loaded level/map (for example Battlefield 2\mods\bf2\levels\zatar_wetlands\archive.md5). This archive contains the checksum of any archive loaded by the map (server.zip and client.zip).

How MD5 files are built

Battlefield MD5 files are a collection of 10 MD5 strings (ordinals), each string on its own line with its index in front of it. For example:

0 aa86b516c3d6218fec20d7bfcf5d28fb

1 d1ac4760a3a29bbb15b872e81417c832

2 ea07bc156ee1924802e45bdb8beb3fe8

3 6838b588d5d77d2491e9d698d3f9cc2f

4 cfd328123a8fa17593b65ea754d8f504

5 e47474c84013700b74aa01745e3ad091

6 78fa2efde1ace394d168dc6ae92c3439

7 a447464e1a82157893eab4c9fc645c62

8 5232b860b6b35f7867b6fa641b416eab

9 6f6d8717dbfc24c8dfd41045dfeec49a

When building the file, each file is divided into blocks of a predefined size (16384 Bytes) Each time one block size of data is read from the file, put in a MD5 object which is then updated, each time in a different ordinal. In pseudo it goes like this:

For file in filecollection

  For each tenth block in the file

    For each ordinal

      read blocksize data from file as data (and move position of blocksize in the file)

      update md5 ordinal with data

Then the resulting list of ordinals is saved and processed further.

How MD5 sums fit in

When a server is started it checks on loading if any .md5 files are present and if so, it will enable content checking using the provided .md5 files as a reference. Failing to have one .md5 file will result in bad content check (ie disabled). When a client joins and content check is enabled, the server tells the client first to check the miscellaneous files (ClientArchives.con, ServerArchives.con, Init.con and GameLogicInit.con in that order) as one md5 hash string, then it tells the ordinal that needs to be send for that session, then it asks to check the main archives. The client will then hash all open archives (ie loaded ingame) on alphabetical order doing the original bf2 files first. At first it ignores any mod shader files and sends the requested ordinal from the result to the server, then it includes the shader archive (if open) and sends the active ordinal as the mod checksum. Then it will hash the archives form the current map and sends the needed ordinal as the map archive checksum. If one of these 4 hases do not match the client will be kicked for a content mismatch (the debugger forms the exception on this as it will ignore the bf2 md5).

Generating MD5 Checksums

Generating MD5 can be as easy or hard as you want it. If you have a default mod setup without any shader files and full custom maps and only archives that are opened ingame the default provided generate_md5.py will suffice. For this to work you need an installed python interpreter and then run the script. You have 2 options here:

1.) Open it in any texteditor and change bf2 in

try:

 mod_name = args[0]

except:

 print("\n****** Content Checking: Mod name missing - using mods/bf2 ******\n")

 mod_name = "bf2"

into your mods name.

2.) Start a console (like cmd in WinXP) and set the Battlefield 2 main directory as your working directory. Then type in:

generate_md5.py MODNAME

where MODNAME is the name of your mod

(do make sure .py file are associated with the python.exe interpreter and that atleast %1 and %2 are passed as arguments (if you dont know what I mean, either go for option 1 or try your luck)). The script will now start hashing your files and maps and when its done you should have your MD5 files, hopefully correctly done.

For those people who do not have the standards in their mod for the script provided by Digital Illisions CE I made my alterations to it to catch some errors. This modified script allows for user input (so no editing/command line), automatically adds missing client.zip files for modified stock maps and checks for empty zipfiles (the editor tends to make them). It can be retrieved here:

http://desert-conflict.org/harry/generate_md5_dcon.py

(it also has the possibility to hash the miscellaneous files, although this is not needed for proper content checking and shows a little progress too).


When the script has has completed hashing (this takes some time), you can find the .md5 files in your folder.

Kicking on newly generated MD5 files

Might the situation occur the client gets kicked after generating the MD5 file, it can be hard to find the cause of the problem. Sometimes the servers MD5 files didnt get updated properly after hashing the clientfiles using the script. In that case a simple update suffices. Are the MD5 files matching, then there is a difference in hashing of the script and the game executable. In that case I would recommend using the debugger to find out the cause.

First install the debugger into your server too (this can for instance be done by copying all the files from your debugger enabled game install (not the folders) into your server without overwriting any files). Then change the commandline of the debugger to this:

bf2_r.exe +modPath mods/MODNAME +dedicated 1

This will start the debugger in dedicated server mode. When starting it will error on you it cannot set the size of the console window. Ignore this error to continue loading. YOu will not have any textual reference on the loading process so you have to check the CPU usage to make sure its loaded (it usually drops from 100% to <10%). Then start the client with the debugger to join the debugger server. If everything is alright you should be able to properly load your map and go into the content check. Wait untill its done (and if all is right to get kicked). Then close the game and close the server (close the server by typing "exit", do not stop the process using windows (or linux)). You should now have two logfiles. The logfile of the server will contain the hashes the client has send to the server for comparison. The part you're looking for in the server logfile looks like about this:

Debug: GameServer: c misc: HASH expected HASH

Debug: GameServer: c bf2 archive: HASH expected HASH

Debug: GameServer: c mod archive: HASH expected HASH

Debug: GameServer: c level: HASH expected HASH

(please note I shortened the lines a bit and HASH is a valid MD5 hash). This can be used to compare your MD5 files to those of the server which allows you to see if your misc files do not match, your archive files or your map files (or a combination). Compare the expected hashes to the ones in the .md5 files, if they do not match you didnt update the .md5 files correctly. Do the expectations match than your files arent checksummed right (or the misc files have been edited). Its then to you to open up the clients debugger log files and find lines like these:

Debug: File: dep: file resolve mode changed from FRM_ArchivesOnly to FRM_Any

Debug: IO: dep: hashing misc con files

Debug: IO: dep: checksumming file ClientArchives.con

Debug: IO: dep: checksumming file ServerArchives.con

Debug: IO: dep: checksumming file Init.con

Debug: IO: dep: checksumming file GameLogicInit.con

Debug: IO: dep: MD5 misc stripe run took 0.00125122 seconds

Debug: IO: dep: found open archive: mods/MyMod/common_server.zip

Debug: IO: dep: found open archive: mods/MyMod/levels/zatar_wetlands/server.zip

Debug: IO: dep: found open archive: mods/bf2/levels/zatar_wetlands/client.zip

(...)

Debug: IO: dep: starting striped MD5 checksum run with 17 archives to process, challenge ordinal is 7

    This is handy to see which ordinal was used for checksum, dont forget only one ordinal is send over the network

Debug: IO: dep: starting pass 1

    Ie checking main archives

Debug: IO: dep: checksumming archive 'mods/bf2/common_client.zip' of size 140302934 (8564 blocks)

Debug: IO: dep: checksumming archive 'mods/bf2/common_server.zip' of size 78540 (5 blocks)

Debug: IO: dep: checksumming archive 'mods/bf2/fonts_client.zip' of size 11630301 (710 blocks)

(...)

Debug: IO: dep: checksumming archive 'mods/MyMod/objects/objects_client.zip' of size 37694069 (2301 blocks)

Debug: IO: dep: checksumming archive 'mods/MyMod/objects/objects_server.zip' of size 6305654 (385 blocks)

Debug: IO: dep: checksumming archive 'mods/MyMod/shaders_client.zip' of size 189165 (12 blocks)

Debug: IO: dep: starting pass 2

    Ie checking level archives

Debug: IO: dep: checksumming archive 'mods/bf2/levels/zatar_wetlands/client.zip' of size 64975608 (3966 blocks)

Debug: IO: dep: checksumming archive 'mods/MyMod/levels/zatar_wetlands/server.zip' of size 7687579 (470 blocks)

Debug: IO: dep: MD5 stripe run took 84.412 seconds

The first part tells which archives are "open", which means they are loaded ingame. This list MUST match the one form the generating script. The next part tells which archives are checksummed in which order, again this must match the way its done in the script. Pass 2 shows which archives are checked for the current level. As you cna see here the client.zip file is read form the bf2 mod as MyMod doesnt have it (this is not intercepted in the standard generating script). With this info you should be able to determine the cause of the problem.

Do note that the bf2 checksum (Debug: GameServer: c bf2 archive: HASH expected HASH) is not correct in the debugger. The custom shader will be included anyway and this checksum is ignored anyway, so in special situations it might occur that the debuger will allow hte client in whilst the original game doesnt. In that case you can be pretty sure it's the shaders archive.

Personal tools