3967d849df71369842e63a283193601cb449b1c1
[tar-legacy.git] / MCDV / vfilesys.hpp
1 #pragma once
2 #include <string>
3 #include "vpk.hpp"
4 #include "vdf.hpp"
5 #include "vvd.hpp"
6 #include "vtx.hpp"
7 #include "../AutoRadar_installer/FileSystemHelper.h"
8
9 class vfilesys {
10 public:
11 // Cached items
12 vpk::index* vpkIndex;
13 kv::DataBlock* gameinfo;
14
15 // Paths
16 std::string dir_gamedir; // Where the gameinfo.txt is (and where we should output to)
17 std::string dir_exedir; // Counter-Strike Global Offensive directory
18 std::string dir_bin; // exedir + /bin/ folder
19
20 std::vector<std::string> searchPaths; // List of paths to search for stuff (these are all absolute)
21
22 /* Create a file system helper from game info */
23 vfilesys(std::string gameinfo, std::string exedir = ""){
24 if (!fs::checkFileExist(gameinfo.c_str())) throw std::exception("gameinfo.txt not found");
25
26 // Load gameinfo
27 std::ifstream ifs(gameinfo);
28 if (!ifs) {
29 std::cout << "Could not open file... " << gameinfo << std::endl;
30 throw std::exception("File read error");
31 }
32
33 std::string str((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
34
35 kv::FileData* kv_gameinfo = new kv::FileData(str);
36 this->gameinfo = &kv_gameinfo->headNode;
37
38 // Set gamedir
39 this->dir_gamedir = fs::getDirName(gameinfo);
40
41 // Look for csgo.exe to set exedir
42 std::string dir_upOne = this->dir_gamedir + "../"; // go up to csgo.exe (or at least it should be here)
43
44 std::cout << dir_upOne << "\n";
45
46 if (exedir != "")
47 if(fs::checkFileExist((exedir + "/csgo.exe").c_str())) this->dir_exedir = exedir + "/";
48 else throw std::exception("Specified exedir was incorrect");
49
50 else if (fs::checkFileExist((dir_upOne + "csgo.exe").c_str())) this->dir_exedir = dir_upOne;
51 else throw std::exception("Can't find csgo.exe");
52
53 // Set bindir
54 this->dir_bin = this->dir_exedir + "bin/";
55
56 // Collect search paths from gameinfo.txt
57 for (auto && path : kv::getList(this->gameinfo->GetFirstByName("\"GameInfo\"")->GetFirstByName("FileSystem")->GetFirstByName("SearchPaths")->Values, "Game")) {
58 std::string _path = "";
59 if (path.find(':') != path.npos) _path = path + "/"; //this path is abs
60 else _path = this->dir_exedir + path + "/"; // relative path to exedir
61 _path = sutil::ReplaceAll(_path, "\\", "//");
62
63 if (fs::checkFileExist(_path.c_str())) this->searchPaths.push_back(_path);
64 }
65
66 // Look for pak01_dir.vpk in all search paths
67 for (auto && sp : this->searchPaths) {
68 if (fs::checkFileExist((sp + "pak01_dir.vpk").c_str())) {
69 this->vpkIndex = new vpk::index(sp + "pak01_dir.vpk");
70 goto IL_FOUND;
71 }
72 }
73
74 std::cout << "Warning: could not find pak01_dir.vpk...\n";
75
76 IL_FOUND:
77 std::cout << "Finished setting up filesystem.\n";
78 }
79
80 /* Dump out what this filesystem has in memory */
81 void debug() {
82 std::cout << "Directories:\n";
83 std::cout << " dir_game: " << dir_gamedir << "\n";
84 std::cout << " dir_exe: " << dir_exedir << "\n";
85 std::cout << " dir_bin: " << dir_bin << "\n";
86
87 std::cout << "\nSearchpaths:\n";
88 for (auto && sp : this->searchPaths) std::cout << " | " << sp << "\n";
89
90 std::cout << "\nCache locations:\n";
91 std::cout << " vpkindex* =" << this->vpkIndex << "\n";
92 std::cout << " gameinfo* =" << this->gameinfo << "\n";
93 std::cout << "\n";
94 }
95
96 /* Create a file handle on an existing resource file. Could be from vpk, could be from custom. Returns null if not found */
97 template<typename T>
98 T* get_resource_handle(std::string relpath) {
99 // Order of importantness:
100 // 0) VPK file (actual game files)
101 // 1) anything in csgo folders
102
103 if (this->vpkIndex != NULL) {
104 vpk::vEntry* vEntry = this->vpkIndex->find(relpath);
105
106 if (vEntry != NULL) {
107 std::string pakDir = this->dir_exedir + "csgo/pak01_" + sutil::pad0(std::to_string(vEntry->entryInfo.ArchiveIndex), 3) + ".vpk";
108
109 std::ifstream pkHandle(pakDir, std::ios::in | std::ios::binary);
110
111 pkHandle.seekg(vEntry->entryInfo.EntryOffset); // set that ifstream to read from the correct location
112 return new T(&pkHandle);
113 }
114 }
115
116 // Check all search paths for custom content
117 for (auto && sp : this->searchPaths) {
118 if (fs::checkFileExist((sp + relpath).c_str())) {
119 std::ifstream pkHandle(sp + relpath, std::ios::in | std::ios::binary);
120 return new T(&pkHandle);
121 }
122 }
123
124 return NULL;
125 }
126
127 /* Generate a path to a file inside the gamedir. Optionally automatically create new directories (shell). */
128 std::string create_output_filepath(std::string relpath, bool mkdr = false) {
129 std::string fullpath = this->dir_gamedir + relpath;
130
131 if(mkdr) fs::mkdr(fullpath.c_str());
132
133 return fullpath;
134 }
135 };