31
31
#include " file_access_pack.h"
32
32
33
33
#include " core/io/file_access_encrypted.h"
34
+ #include " core/io/resource.h"
34
35
#include " core/object/script_language.h"
35
36
#include " core/os/os.h"
36
37
#include " core/version.h"
37
38
39
+ #include " modules/modules_enabled.gen.h" // For gdscript.
40
+ #ifdef MODULE_GDSCRIPT_ENABLED
41
+ #include " modules/gdscript/gdscript_cache.h"
42
+ #endif
43
+
38
44
#include < stdio.h>
39
45
40
46
Error PackedData::add_pack (const String &p_path, bool p_replace_files, uint64_t p_offset) {
@@ -47,29 +53,86 @@ Error PackedData::add_pack(const String &p_path, bool p_replace_files, uint64_t
47
53
return ERR_FILE_UNRECOGNIZED;
48
54
}
49
55
56
+ Error PackedData::remove_pack (const String &p_path) {
57
+ if (!is_pack_loaded (p_path)) {
58
+ return ERR_FILE_UNRECOGNIZED;
59
+ }
60
+
61
+ Vector<PathMD5> reload_packs;
62
+ Vector<HashMap<PathMD5, PackedFile, PathMD5>::Iterator> to_remove;
63
+ for (HashMap<PathMD5, PackedFile, PathMD5>::Iterator E = files.begin (); E; ++E) {
64
+ PackedFile pf = E->value ;
65
+ if (pf.pack .name != p_path) {
66
+ continue ;
67
+ }
68
+
69
+ PathMD5 pmd5 = pf.pack .replaced_pack ;
70
+ if (pmd5.set ) {
71
+ if (!reload_packs.has (pmd5)) {
72
+ reload_packs.push_back (pmd5);
73
+ }
74
+ }
75
+
76
+ remove_path (pf.filepath );
77
+ to_remove.push_back (E);
78
+ }
79
+
80
+ for (const HashMap<PathMD5, PackedFile, PathMD5>::Iterator &E : to_remove) {
81
+ files.remove (E);
82
+ }
83
+ remove_loaded_pack (p_path);
84
+
85
+ // For reloading files unloaded by more recent packs, we simply need to reload packs with replace_files disabled.
86
+ for (PathMD5 pmd5 : reload_packs) {
87
+ if (!loaded_packs.has (pmd5)) {
88
+ continue ;
89
+ }
90
+ LoadedPackInfo pack_info = loaded_packs[pmd5];
91
+ Error err = add_pack (pack_info.name , false , pack_info.offset );
92
+ if (err) {
93
+ return err;
94
+ }
95
+ }
96
+
97
+ return OK;
98
+ }
99
+
50
100
void PackedData::add_path (const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted) {
51
101
String simplified_path = p_path.simplify_path ();
52
102
PathMD5 pmd5 (simplified_path.md5_buffer ());
53
103
104
+ // When running on the editor, the base files are not loaded from a main pack file.
105
+ // This extra check prevents packs from overriding those base files.
106
+ #ifdef TOOLS_ENABLED
107
+ bool exists = files.has (pmd5) || FileAccess::exists (simplified_path);
108
+ #else
54
109
bool exists = files.has (pmd5);
110
+ #endif
111
+
112
+ PackInfo pi ;
113
+ pi .name = p_pkg_path;
114
+ if (p_replace_files && exists) {
115
+ pi .replaced_pack = PathMD5 (files[pmd5].pack .name .md5_buffer ());
116
+ }
55
117
56
118
PackedFile pf;
57
119
pf.encrypted = p_encrypted;
58
- pf.pack = p_pkg_path ;
120
+ pf.pack = pi ;
59
121
pf.offset = p_ofs;
60
122
pf.size = p_size;
61
123
for (int i = 0 ; i < 16 ; i++) {
62
124
pf.md5 [i] = p_md5[i];
63
125
}
64
126
pf.src = p_src;
127
+ pf.filepath = simplified_path.replace_first (" res://" , " " );
65
128
66
129
if (!exists || p_replace_files) {
67
130
files[pmd5] = pf;
68
131
}
69
132
70
133
if (!exists) {
71
134
// search for dir
72
- String p = simplified_path. replace_first ( " res:// " , " " ) ;
135
+ String p = pf. filepath ;
73
136
PackedDir *cd = root;
74
137
75
138
if (p.contains (" /" )) { // in a subdir
@@ -96,6 +159,69 @@ void PackedData::add_path(const String &p_pkg_path, const String &p_path, uint64
96
159
}
97
160
}
98
161
162
+ void PackedData::remove_path (const String &p_path) {
163
+ String p = p_path;
164
+ PackedDir *cd = root;
165
+
166
+ if (p.contains (" /" )) {
167
+ Vector<String> ds = p.get_base_dir ().split (" /" );
168
+
169
+ for (int j = 0 ; j < ds.size (); j++) {
170
+ if (!cd->subdirs .has (ds[j])) {
171
+ return ;
172
+ } else {
173
+ cd = cd->subdirs [ds[j]];
174
+ }
175
+ }
176
+ }
177
+ String filename = p_path.get_file ();
178
+ cd->files .erase (filename);
179
+
180
+ // Clear empty folders.
181
+ while (cd && cd->files .is_empty () && cd->subdirs .is_empty ()) {
182
+ String name = cd->name ;
183
+ cd = cd->parent ;
184
+ if (cd) {
185
+ cd->subdirs .erase (name);
186
+ }
187
+ }
188
+
189
+ String res_path = " res://" + p_path;
190
+
191
+ // Remove paths from cache.
192
+ if (ResourceCache::has (res_path)) {
193
+ ResourceCache::remove_cached_resource (res_path);
194
+ }
195
+
196
+ // GDScript also caches scripts internally, so they too must be removed.
197
+ #ifdef MODULE_GDSCRIPT_ENABLED
198
+ if (GDScriptCache::get_cached_script (res_path).is_valid ()) {
199
+ GDScriptCache::remove_script (res_path);
200
+ }
201
+ #endif
202
+ }
203
+
204
+ void PackedData::add_loaded_pack (const String &p_path, const uint64_t &p_offset) {
205
+ if (!is_pack_loaded (p_path)) {
206
+ LoadedPackInfo pack_info;
207
+ pack_info.name = p_path;
208
+ pack_info.offset = p_offset;
209
+
210
+ PathMD5 pmd5 (p_path.md5_buffer ());
211
+ loaded_packs.insert (pmd5, pack_info);
212
+ }
213
+ }
214
+
215
+ void PackedData::remove_loaded_pack (const String &p_path) {
216
+ PathMD5 pmd5 (p_path.md5_buffer ());
217
+ loaded_packs.erase (pmd5);
218
+ }
219
+
220
+ bool PackedData::is_pack_loaded (const String &p_pack_path) const {
221
+ PathMD5 pmd5 (p_pack_path.md5_buffer ());
222
+ return loaded_packs.has (pmd5);
223
+ }
224
+
99
225
void PackedData::add_pack_source (PackSource *p_source) {
100
226
if (p_source != nullptr ) {
101
227
sources.push_back (p_source);
@@ -259,6 +385,8 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
259
385
f = fae;
260
386
}
261
387
388
+ PackedData::get_singleton ()->add_loaded_pack (p_path, p_offset);
389
+
262
390
for (int i = 0 ; i < file_count; i++) {
263
391
uint32_t sl = f->get_32 ();
264
392
CharString cs;
@@ -385,16 +513,16 @@ void FileAccessPack::close() {
385
513
386
514
FileAccessPack::FileAccessPack (const String &p_path, const PackedData::PackedFile &p_file) :
387
515
pf(p_file),
388
- f(FileAccess::open(pf.pack, FileAccess::READ)) {
389
- ERR_FAIL_COND_MSG (f.is_null (), vformat (" Can't open pack-referenced file '%s'." , String (pf.pack )));
516
+ f(FileAccess::open(pf.pack.name , FileAccess::READ)) {
517
+ ERR_FAIL_COND_MSG (f.is_null (), vformat (" Can't open pack-referenced file '%s'." , String (pf.pack . name )));
390
518
391
519
f->seek (pf.offset );
392
520
off = pf.offset ;
393
521
394
522
if (pf.encrypted ) {
395
523
Ref<FileAccessEncrypted> fae;
396
524
fae.instantiate ();
397
- ERR_FAIL_COND_MSG (fae.is_null (), vformat (" Can't open encrypted pack-referenced file '%s'." , String (pf.pack )));
525
+ ERR_FAIL_COND_MSG (fae.is_null (), vformat (" Can't open encrypted pack-referenced file '%s'." , String (pf.pack . name )));
398
526
399
527
Vector<uint8_t > key;
400
528
key.resize (32 );
@@ -403,7 +531,7 @@ FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFil
403
531
}
404
532
405
533
Error err = fae->open_and_parse (f, key, FileAccessEncrypted::MODE_READ, false );
406
- ERR_FAIL_COND_MSG (err, vformat (" Can't open encrypted pack-referenced file '%s'." , String (pf.pack )));
534
+ ERR_FAIL_COND_MSG (err, vformat (" Can't open encrypted pack-referenced file '%s'." , String (pf.pack . name )));
407
535
f = fae;
408
536
off = 0 ;
409
537
}
0 commit comments