44#include " game/game.hpp"
55
66#include " fastfiles.hpp"
7- #include " component/engine/console/command.hpp"
8- #include " component/engine/console/console.hpp"
97
108#include < utils/hook.hpp>
11- #include < utils/memory.hpp>
12- #include < utils/io.hpp>
9+ #include < utils/nt.hpp>
1310
1411namespace fastfiles
1512{
13+ namespace
14+ {
15+ utils::hook::detour db_load_xassets_hook;
16+
17+ bool patch_consolation_loaded = false ;
18+ bool patch_mp_loaded = false ;
19+ bool patch_consolation_attempted = false ;
20+ bool patch_mp_attempted = false ;
21+
22+ bool zone_name_equals (const char * lhs, const char * rhs)
23+ {
24+ return lhs != nullptr && rhs != nullptr && _stricmp (lhs, rhs) == 0 ;
25+ }
26+
27+ bool has_zone (const game::XZoneInfo* zone_info, const int zone_count, const char * name)
28+ {
29+ if (zone_info == nullptr || zone_count <= 0 || name == nullptr )
30+ {
31+ return false ;
32+ }
33+
34+ for (auto index = 0 ; index < zone_count; ++index)
35+ {
36+ if (zone_name_equals (zone_info[index].name , name))
37+ {
38+ return true ;
39+ }
40+ }
41+
42+ return false ;
43+ }
44+
45+ bool zone_file_exists (const char * zone_name)
46+ {
47+ if (zone_name == nullptr || zone_name[0 ] == ' \0 ' )
48+ {
49+ return false ;
50+ }
51+
52+ const auto zone_file_name = std::string (zone_name) + " .ff" ;
53+ const std::array roots
54+ {
55+ std::filesystem::path (utils::nt::get_host_module ().get_folder ()) / " zone" ,
56+ std::filesystem::current_path () / " zone" ,
57+ };
58+
59+ for (const auto & root : roots)
60+ {
61+ std::error_code ec{};
62+ if (!std::filesystem::exists (root, ec))
63+ {
64+ continue ;
65+ }
66+
67+ if (std::filesystem::exists (root / zone_file_name, ec))
68+ {
69+ return true ;
70+ }
71+
72+ for (std::filesystem::recursive_directory_iterator it (root, ec), end; it != end && !ec; it.increment (ec))
73+ {
74+ if (!it->is_regular_file (ec))
75+ {
76+ continue ;
77+ }
78+
79+ const auto filename = it->path ().filename ().string ();
80+ if (_stricmp (filename.c_str (), zone_file_name.c_str ()) == 0 )
81+ {
82+ return true ;
83+ }
84+ }
85+ }
86+
87+ return false ;
88+ }
89+
90+ game::XZoneInfo make_override_zone (const char * zone_name)
91+ {
92+ game::XZoneInfo zone_info{};
93+ zone_info.name = zone_name;
94+ zone_info.allocFlags = 2 ;
95+ zone_info.freeFlags = 0 ;
96+
97+ return zone_info;
98+ }
99+
100+ int db_load_xassets_stub (game::XZoneInfo* zone_info, const int zone_count, const int sync)
101+ {
102+ patch_consolation_loaded = patch_consolation_loaded || has_zone (zone_info, zone_count, " patch_consolation" );
103+ patch_mp_loaded = patch_mp_loaded || has_zone (zone_info, zone_count, " patch_mp" );
104+
105+ const auto loading_common_fastfiles = has_zone (zone_info, zone_count, " common_mp" );
106+ const auto should_load_patch_consolation = loading_common_fastfiles
107+ && !patch_consolation_attempted
108+ && !patch_consolation_loaded;
109+
110+ const auto should_load_patch_mp = loading_common_fastfiles
111+ && !patch_mp_attempted
112+ && !patch_mp_loaded;
113+
114+ const auto result = db_load_xassets_hook.invoke <int >(zone_info, zone_count, sync);
115+ if (!result)
116+ {
117+ return result;
118+ }
119+
120+ std::vector<game::XZoneInfo> patch_zones{};
121+ if (should_load_patch_mp)
122+ {
123+ patch_mp_attempted = true ;
124+ patch_zones.push_back (make_override_zone (" patch_mp" ));
125+ patch_mp_loaded = true ;
126+ }
127+
128+ if (should_load_patch_consolation)
129+ {
130+ patch_consolation_attempted = true ;
131+ if (zone_file_exists (" patch_consolation" ))
132+ {
133+ patch_zones.push_back (make_override_zone (" patch_consolation" ));
134+ patch_consolation_loaded = true ;
135+ }
136+ else
137+ {
138+ game::Com_Printf (16 , " Skipping override fastfile 'patch_consolation' because it was not found\n " );
139+ }
140+ }
141+
142+ if (!patch_zones.empty ())
143+ {
144+ game::Com_Printf (16 , " Loading patch fastfiles with override priority\n " );
145+ db_load_xassets_hook.invoke <int >(patch_zones.data (), static_cast <int >(patch_zones.size ()), sync);
146+ }
147+
148+ return result;
149+ }
150+ }
151+
16152 void enum_assets (const game::XAssetType type, const std::function<void (game::XAssetHeader)>& callback, const bool include_override)
17153 {
18154 game::DB_EnumXAssets_FastFile (type, static_cast <void (*)(game::XAssetHeader, void *)>([](game::XAssetHeader header, void * data)
@@ -24,11 +160,11 @@ namespace fastfiles
24160
25161 class component final : public component_interface
26162 {
27- /* public:
28- void post_unpack () override
29- {
30- //Placeholder for now, so it builds
31- } */
163+ public:
164+ void post_load () override
165+ {
166+ db_load_xassets_hook. create (game::DB_LoadXAssets, db_load_xassets_stub);
167+ }
32168 };
33169}
34170
0 commit comments