23 | | During development, artists and programmers typically follow a edit/see how it looks in-game/repeat methodology. Unfortunately, changes to a file are not immediately noticed by the game; the usual workaround is to |
24 | | restart the map (or worse, entire game) to make sure they are reloaded. Since decreases in edit cycle time improve productivity, we want changes to files to be picked up immediately. To that end, we support hotloading - |
25 | | as soon as the OS reports changes, all Handle objects that ensued from that file are reloaded. |
| 24 | During development, artists and programmers typically follow a edit/see how it looks in-game/repeat methodology. |
| 25 | Unfortunately, changes to a file are not immediately noticed by the game. |
| 26 | The usual workaround is to restart the map (or worse, entire game) to make sure they are reloaded. |
| 27 | Since decreases in edit cycle time improve productivity, we want changes to files to be picked up immediately. |
| 28 | To that end, we support hotloading - as soon as the OS reports changes, all Handle objects that ensued from that file are reloaded. |
27 | | The VFS's part in this is registering "watches" that report changes to any mounted real directory. Since the file notification backend (currently SGI FAM and a Win32 port) cannot watch an entire directory tree, |
28 | | we need to do so for every single directory. The VFS traverses and stores data for them anyway, we do so here. |
| 30 | The VFS's part in this is registering "watches" that report changes to any mounted real directory. |
| 31 | Since the file notification backend (or some OS specific APIs) cannot watch an entire directory tree, we need to do so for every single directory. |
| 32 | The VFS traverses and stores data for them anyway, we do so here. |
35 | | When users tweak game parameters or even create an entirely new game principle with the same underlying engine, it is called modding. As evidenced by the Counterstrike mod for Half-Life, this can greatly prolong the life of a game. Additionally, since we started out as a mod group, great value is placed on giving users all the tools to make modding easy. |
| 39 | When users tweak game parameters or even create an entirely new game principle with the same underlying engine, it is called modding. |
| 40 | As evidenced by the Counterstrike mod for Half-Life, this can greatly prolong the life of a game. |
| 41 | Additionally, since we started out as a mod group, great value is placed on giving users all the tools to make modding easy. |
39 | | The actual method of overriding game data is quite simple: a mod directory is mounted into the file system with a higher priority than original data. These files therefore temporarily (as long as the mod is active) replace the |
40 | | originals. This allows multiple (non-overlapping!) mods to be active at the same time and also makes switching between them easy. The same mechanism is also used for patches to game data. |
| 45 | The actual method of overriding game data is quite simple: a mod directory is mounted into the file system with a higher priority than original data. |
| 46 | These files therefore temporarily (as long as the mod is active) replace the originals. |
| 47 | This allows multiple mods to be active at the same time and also makes switching between them easy. |
| 48 | The same mechanism could also be used for patches to game data. |
| 49 | |
| 50 | ==== File Replacement ==== |
| 51 | |
| 52 | A newly mounted mod has its files added to the VFS if the files have a higher priority, or they have the same priority but a newer timestamp (e.g. update packs, development), or the used file loader (archives are preferred over loose files) is more efficient. |
| 53 | |
| 54 | ==== File Removal ==== |
| 55 | |
| 56 | Mods can remove files from lower priority mods. |
| 57 | To remove file `a` the mod has to provide a file named `a.DELETED` (contents do not matter, file should probably be empty to save space). |
| 58 | Removing directories follows a similar approach where a directory `b` in a lower priority mod is removed if a file named `b.DELETED` is in the mod. (Not yet included; see #2641) |
| 59 | All files with a lower priority than the `.DELETED` file in this directory (and all subdirectories) are then removed, and empty subdirectories are also removed. |
| 60 | Note that the directory cannot be removed unconditionally since it might contain higher priority (or same priority) files which should be kept. |
56 | | "Mounting" is understood to mean populating a given VFS directory (the "mount point") with the contents of e.g. a real directory or archive (the "mounted object" - for a list of supported types, see enum !MountType). |
| 81 | "Mounting" is understood to mean populating a given VFS directory (the "mount point") with the contents of e.g. a real directory or archive (the "mounted object"). |
| 82 | It is important to note that the VFS is a full-fledged tree storing information about each file, e.g. its last-modified time or actual location. |
| 83 | The advantage is that file open time does not increase with the number of mounts, which is important because multiple patches and mods may be active. |
| 84 | This is in contrast to e.g. PhysicsFS, which just maintains a list of mountings and scans it when opening each file. |
58 | | It is important to note that the VFS is a full-fledged tree storing information about each file, e.g. its last-modified time or actual location. The advantage is that file open time does not increase with the number of |
59 | | mounts, which is important because multiple patches and mods may be active. This is in contrast to e.g. PhysicsFS, which just maintains a list of mountings and scans it when opening each file. |
60 | | |
61 | | Each file object in the VFS tree stores its current location; there is no way to access files of the same name but lower priority residing in other mounted objects. For this reason, the entire VFS must be rebuilt (i.e. repopulating all mount points) when a mounting is removed. Fortunately this is rare and does not happen in-game; we optimize for the common case. |
| 86 | Each file object in the VFS tree stores its current location; there is no way to access files of the same name but lower priority residing in other mounted objects. |
| 87 | For this reason, the entire VFS must be rebuilt (i.e. repopulating all mount points) when a mounting is removed. |
| 88 | Fortunately this is rare and does not happen in-game (apart from the mod selector), so we optimize for the common case. |
71 | | Interoperability is a double-edged sword, since anyone can change critical files or use game assets. However, obfuscating archive contents doesn't solve anything, because the application needs to access them and a cracker |
72 | | need only reverse-engineer that. Regardless, the application can call its archives e.g. ".pk3" (as does Quake III) for minimal protection. |
| 98 | Interoperability is a double-edged sword, since anyone can change critical files or use game assets. |
| 99 | However, obfuscating archive contents doesn't solve anything, because the application needs to access them and a cracker need only reverse-engineer that. |
| 100 | Regardless, the application can call its archives e.g. ".pk3" (as does Quake III) for minimal protection. |
76 | | Arranging archive contents in order of access was mentioned above. To that end, the VFS can log all file open calls into a text file (one per line). This is then processed by an archive builder script, which needs to |
77 | | collect all files by VFS lookup rules, then add them to the archive in the order specified in that file (all remaining files that weren't triggered in the logging test run should be added thereafter). |
| 104 | The game supports building archives via the `-archivebuild` command line parameters. |
| 105 | This adds all files in the specified mod (and their cached variants) to a `.zip` archive. |
| 106 | Optionally the archive can be compressed thereby slightly improving file access times (less data to read, decompression overhead is not an issue since it is done in parallel with IOs). |