1 (* Copyright (C) Doom 2D: Forever Developers
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, version 3 of the License ONLY.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *)
15 {$INCLUDE ../shared/a_modes.inc}
18 interface
23 // download map wad from server (if necessary)
24 // download all required map resource wads too
25 // registers all required replacement wads
26 // returns name of the map wad (relative to mapdir), or empty string on error
29 // returns original name, or replacement name
32 // call this somewhere in startup sequence
36 implementation
40 var
41 // cvars
45 // other vars
49 saveDBsToDiskEnabled: Boolean = false; // this will be set to `true` if initial database saving succeed
52 //==========================================================================
53 //
54 // saveDatabases
55 //
56 //==========================================================================
58 var
61 begin
63 // rescan dirs
64 // save map database
66 begin
69 try
73 except
76 if (err) then begin saveDBsToDiskEnabled := false; e_LogWriteln('cannot write map database, disk refresh disabled'); exit; end;
78 // save resource database
80 begin
83 try
87 except
90 if (err) then begin saveDBsToDiskEnabled := false; e_LogWriteln('cannot write resource database, disk refresh disabled'); exit; end;
95 //==========================================================================
96 //
97 // g_Res_CreateDatabases
98 //
99 //==========================================================================
101 var
103 begin
104 // create and load a know map database, if necessary
109 // load map database
111 try
115 except
118 // load resource database
120 try
124 except
127 // rescan dirs
132 // save databases
137 //==========================================================================
138 //
139 // getWord
140 //
141 // get next word from a string
142 // words are delimited with ';'
143 // ignores leading and trailing spaces
144 // returns empty string if there are no more words
145 //
146 //==========================================================================
148 var
150 begin
153 begin
154 if (ord(list[1]) <= 32) or (list[1] = ';') or (list[1] = ':') then begin Delete(list, 1, 1); continue; end;
159 while (length(result) > 0) and (ord(result[length(result)]) <= 32) do Delete(result, length(result), 1);
165 //==========================================================================
166 //
167 // isIgnoredResWad
168 //
169 // checks if the given resource wad can be ignored
170 //
171 // FIXME: preparse name list?
172 //
173 //==========================================================================
175 var
178 begin
185 begin
187 //writeln('*** name=[', name, ']; fname=[', fname, ']');
194 //==========================================================================
195 //
196 // clearReplacementWads
197 //
198 // call this before downloading a new map from a server
199 //
200 //==========================================================================
202 begin
208 //==========================================================================
209 //
210 // addReplacementWad
211 //
212 // register new replacement wad
213 //
214 //==========================================================================
216 begin
223 //==========================================================================
224 //
225 // g_Res_FindReplacementWad
226 //
227 // returns original name, or replacement name
228 //
229 //==========================================================================
231 var
233 begin
234 //e_LogWritefln('LOOKING for replacement wad for [%s]...', [oldname], TMsgType.Notify);
238 begin
239 //e_LogWritefln('found replacement wad for [%s] -> [%s]', [oldname, fn], TMsgType.Notify);
245 //==========================================================================
246 //
247 // scanDir
248 //
249 // look for a wad to match the hash
250 // scans subdirs, ignores known wad extensions
251 //
252 // returns found wad disk name, or empty string
253 //
254 //==========================================================================
255 (*
256 function scanDir (dirName: AnsiString; baseName: AnsiString; const resMd5: TMD5Digest): AnsiString;
257 var
258 searchResult: TSearchRec;
259 dfn: AnsiString;
260 md5: TMD5Digest;
261 dirs: array of AnsiString;
262 f: Integer;
263 begin
264 result := '';
265 SetLength(dirs, 0);
266 if (length(baseName) = 0) then exit;
267 dirName := IncludeTrailingPathDelimiter(dirName);
268 e_LogWritefln('scanning dir `%s` for file `%s`...', [dirName, baseName]);
270 // scan files
271 if (FindFirst(dirName+'*', faAnyFile, searchResult) <> 0) then exit;
272 try
273 repeat
274 if ((searchResult.Attr and faDirectory) = 0) then
275 begin
276 if (isWadNamesEqu(searchResult.Name, baseName)) then
277 begin
278 dfn := dirName+searchResult.Name;
279 if FileExists(dfn) then
280 begin
281 e_LogWritefln(' found `%s`...', [dfn]);
282 md5 := MD5File(dfn);
283 if MD5Match(md5, resMd5) then
284 begin
285 e_LogWritefln(' MATCH `%s`...', [dfn]);
286 SetLength(dirs, 0);
287 result := dfn;
288 exit;
289 end;
290 end;
291 end;
292 end
293 else
294 begin
295 if (searchResult.Name <> '.') and (searchResult.Name <> '..') then
296 begin
297 dfn := dirName+searchResult.Name;
298 SetLength(dirs, Length(dirs)+1);
299 dirs[length(dirs)-1] := dfn;
300 end;
301 end;
302 until (FindNext(searchResult) <> 0);
303 finally
304 FindClose(searchResult);
305 end;
307 // scan subdirs
308 for f := 0 to High(dirs) do
309 begin
310 dfn := dirs[f];
311 result := scanDir(dfn, baseName, resMd5);
312 if (length(result) <> 0) then begin SetLength(dirs, 0); exit; end;
313 end;
314 SetLength(dirs, 0);
315 end;
316 *)
319 //==========================================================================
320 //
321 // findExistingMapWadWithHash
322 //
323 // find map or resource wad using its base name and hash
324 //
325 // returns found wad disk name, or empty string
326 //
327 //==========================================================================
329 begin
330 //result := scanDir(GameDir+'/maps', ExtractFileName(fname), resMd5);
333 begin
336 begin
344 //==========================================================================
345 //
346 // findExistingResWadWithHash
347 //
348 // find map or resource wad using its base name and hash
349 //
350 // returns found wad disk name, or empty string
351 //
352 //==========================================================================
354 begin
355 //result := scanDir(GameDir+'/wads', ExtractFileName(fname), resMd5);
358 begin
361 begin
369 //==========================================================================
370 //
371 // generateFileName
372 //
373 // generate new file name based on the given one and the hash
374 // you can pass files with pathes here too
375 //
376 //==========================================================================
378 var
383 begin
397 //==========================================================================
398 //
399 // g_Res_DownloadMapWAD
400 //
401 // download map wad from server (if necessary)
402 // download all required map resource wads too
403 // registers all required replacement wads
404 //
405 // returns name of the map wad (relative to mapdir), or empty string on error
406 //
407 //==========================================================================
409 var
419 begin
425 try
437 // find or download a map
440 begin
441 // download map
444 begin
447 exit;
449 try
451 except
455 try
457 except
460 exit;
462 try
464 except
468 exit;
472 begin
475 exit;
477 // if it was resumed, check md5 and initiate full download if necessary
479 begin
481 // sorry for pasta, i am asshole
483 begin
485 try
488 except
491 exit;
493 try
495 except
499 exit;
503 begin
506 exit;
514 // download resources
516 begin
520 begin
521 // ignored file, abort download
524 continue;
528 begin
529 // already here
532 end
533 else
534 begin
535 try
537 except
541 try
543 except
546 exit;
548 try
550 except
554 exit;
558 begin
561 exit;
563 // if it was resumed, check md5 and initiate full download if necessary
565 begin
567 // sorry for pasta, i am asshole
569 begin
570 e_LogWritefln('resuming failed; downloading resource `%s` to `%s` from scratch...', [tf.diskName, fname]);
571 try
574 except
577 exit;
579 try
581 except
585 exit;
589 begin
592 exit;
600 finally
605 if saveDBsToDiskEnabled and (mapdbUpdated or resdbUpdated) then saveDatabases(mapdbUpdated, resdbUpdated);
609 initialization
610 conRegVar('rdl_ignore_names', @g_res_ignore_names, 'list of resource wad names (without extensions) to ignore in dl hash checks', 'dl ignore wads');
611 conRegVar('rdl_ignore_enabled', @g_res_ignore_enabled, 'enable dl hash check ignore list', 'dl hash check ignore list active');
612 conRegVar('rdl_hashdb_save_enabled', @g_res_save_databases, 'enable saving map/resource hash databases to disk', 'controls storing hash databases to disk');