index ae645a1196677443c505ee10f75dcd0e16f63193..1f5c6cd4fbaf8f3c432ad6677f27c30da5271ad8 100644 (file)
uses sysutils, Classes, md5, g_net, g_netmsg, g_console, g_main, e_log;
-function g_Res_SearchSameWAD(const path, filename: AnsiString; const resMd5: TMD5Digest): AnsiString;
// download map wad from server (if necessary)
// download all required map resource wads too
+// registers all required replacement wads
// returns name of the map wad (relative to mapdir), or empty string on error
function g_Res_DownloadMapWAD (FileName: AnsiString; const mapHash: TMD5Digest): AnsiString;
-// call this before downloading a new map from a server
-procedure g_Res_ClearReplacementWads ();
// returns original name, or replacement name
function g_Res_FindReplacementWad (oldname: AnsiString): AnsiString;
-procedure g_Res_PutReplacementWad (oldname: AnsiString; newDiskName: AnsiString);
implementation
uses g_language, sfs, utils, wadreader, g_game, hashtable;
-//const DOWNLOAD_DIR = 'downloads';
-
var
+ // cvars
+ g_res_ignore_names: AnsiString = 'standard;shrshade';
+ g_res_ignore_enabled: Boolean = true;
+ // other vars
replacements: THashStrStr = nil;
-// call this before downloading a new map from a server
-procedure g_Res_ClearReplacementWads ();
+//==========================================================================
+//
+// clearReplacementWads
+//
+// call this before downloading a new map from a server
+//
+//==========================================================================
+procedure clearReplacementWads ();
begin
if assigned(replacements) then replacements.clear();
e_LogWriteln('cleared replacement wads');
end;
-// returns original name, or replacement name
+//==========================================================================
+//
+// addReplacementWad
+//
+// register new replacement wad
+//
+//==========================================================================
+procedure addReplacementWad (oldname: AnsiString; newDiskName: AnsiString);
+begin
+ e_LogWritefln('adding replacement wad: oldname=%s; newname=%s', [oldname, newDiskName]);
+ if not assigned(replacements) then replacements := THashStrStr.Create();
+ replacements.put(toLowerCase1251(oldname), newDiskName);
+end;
+
+
+//==========================================================================
+//
+// g_Res_FindReplacementWad
+//
+// returns original name, or replacement name
+//
+//==========================================================================
function g_Res_FindReplacementWad (oldname: AnsiString): AnsiString;
var
fn: AnsiString;
end;
-procedure g_Res_PutReplacementWad (oldname: AnsiString; newDiskName: AnsiString);
-begin
- e_LogWritefln('adding replacement wad: oldname=%s; newname=%s', [oldname, newDiskName]);
- if not assigned(replacements) then replacements := THashStrStr.Create();
- replacements.put(toLowerCase1251(oldname), newDiskName);
-end;
-
-
+//==========================================================================
+//
+// scanDir
+//
+// look for a wad to match the hash
+// scans subdirs, ignores known wad extensions
+//
+// returns found wad disk name, or empty string
+//
+//==========================================================================
function scanDir (dirName: AnsiString; baseName: AnsiString; const resMd5: TMD5Digest): AnsiString;
var
searchResult: TSearchRec;
end;
-function g_Res_SearchResWad (asMap: Boolean; fname: AnsiString; const resMd5: TMD5Digest): AnsiString;
+//==========================================================================
+//
+// findExistingMapWadWithHash
+//
+// find map or resource wad using its base name and hash
+//
+// returns found wad disk name, or empty string
+//
+//==========================================================================
+function findExistingMapWadWithHash (fname: AnsiString; const resMd5: TMD5Digest): AnsiString;
begin
- result := '';
- //if not assigned(scannedDirs) then scannedDirs := THashStrInt.Create();
- if (asMap) then
- begin
- result := scanDir(GameDir+'/maps', ExtractFileName(fname), resMd5);
- end
- else
- begin
- result := scanDir(GameDir+'/wads', ExtractFileName(fname), resMd5);
- end;
+ result := scanDir(GameDir+'/maps', ExtractFileName(fname), resMd5);
end;
-function g_Res_SearchSameWAD (const path, filename: AnsiString; const resMd5: TMD5Digest): AnsiString;
+//==========================================================================
+//
+// findExistingResWadWithHash
+//
+// find map or resource wad using its base name and hash
+//
+// returns found wad disk name, or empty string
+//
+//==========================================================================
+function findExistingResWadWithHash (fname: AnsiString; const resMd5: TMD5Digest): AnsiString;
begin
- result := scanDir(path, filename, resMd5);
+ result := scanDir(GameDir+'/wads', ExtractFileName(fname), resMd5);
end;
+//==========================================================================
+//
+// g_Res_DownloadMapWAD
+//
+// download map wad from server (if necessary)
+// download all required map resource wads too
+// registers all required replacement wads
+//
+// returns name of the map wad (relative to mapdir), or empty string on error
+//
+//==========================================================================
function g_Res_DownloadMapWAD (FileName: AnsiString; const mapHash: TMD5Digest): AnsiString;
var
tf: TNetFileTransfer;
strm: TStream;
fname: AnsiString;
wadname: AnsiString;
+ md5: TMD5Digest;
begin
- //SetLength(mapData.ExternalResources, 0);
result := '';
- g_Res_ClearReplacementWads();
- g_Res_received_map_start := false;
+ clearReplacementWads();
resList := TStringList.Create();
try
+ g_Res_received_map_start := 1;
g_Console_Add(Format(_lc[I_NET_MAP_DL], [FileName]));
e_WriteLog('Downloading map `' + FileName + '` from server', TMsgType.Notify);
g_Game_SetLoadingText(FileName + '...', 0, False);
- //MC_SEND_MapRequest();
if (not g_Net_SendMapRequest()) then exit;
FileName := ExtractFileName(FileName);
if (res <> 0) then exit;
// find or download a map
- result := g_Res_SearchResWad(true{asMap}, tf.diskName, mapHash);
+ result := findExistingMapWadWithHash(tf.diskName, mapHash);
if (length(result) = 0) then
begin
// download map
end;
fname := GameDir+'/maps/downloads/'+FileName;
try
- strm := createDiskFile(fname);
+ strm := openDiskFileRW(fname);
except
e_WriteLog('cannot create map file `'+FileName+'`', TMsgType.Fatal);
result := '';
result := '';
exit;
end;
+ // if it was resumed, check md5 and initiate full download if necessary
+ if tf.resumed then
+ begin
+ md5 := MD5File(fname);
+ // sorry for pasta, i am asshole
+ if not MD5Match(md5, tf.hash) then
+ begin
+ e_LogWritefln('resuming failed; downloading map `%s` from scratch...', [fname]);
+ try
+ DeleteFile(fname);
+ strm := createDiskFile(fname);
+ except
+ e_WriteLog('cannot create map file `'+fname+'`', TMsgType.Fatal);
+ result := '';
+ exit;
+ end;
+ try
+ res := g_Net_ReceiveResourceFile(-1{map}, tf, strm);
+ except
+ e_WriteLog('error downloading map file `'+FileName+'`', TMsgType.Fatal);
+ strm.Free;
+ result := '';
+ exit;
+ end;
+ strm.Free;
+ if (res <> 0) then
+ begin
+ e_WriteLog('error downloading map file `'+FileName+'`', TMsgType.Fatal);
+ result := '';
+ exit;
+ end;
+ end;
+ end;
result := fname;
end;
begin
res := g_Net_RequestResFileInfo(f, tf);
if (res <> 0) then begin result := ''; exit; end;
- wadname := g_Res_SearchResWad(false{asMap}, tf.diskName, tf.hash);
+ wadname := findExistingResWadWithHash(tf.diskName, tf.hash);
if (length(wadname) <> 0) then
begin
// already here
g_Net_AbortResTransfer(tf);
- g_Res_PutReplacementWad(tf.diskName, wadname);
+ addReplacementWad(tf.diskName, wadname);
end
else
begin
fname := GameDir+'/wads/downloads/'+tf.diskName;
e_LogWritefln('downloading resource `%s` to `%s`...', [tf.diskName, fname]);
try
- strm := createDiskFile(fname);
+ strm := openDiskFileRW(fname);
except
e_WriteLog('cannot create resource file `'+fname+'`', TMsgType.Fatal);
result := '';
result := '';
exit;
end;
- g_Res_PutReplacementWad(tf.diskName, fname);
+ // if it was resumed, check md5 and initiate full download if necessary
+ if tf.resumed then
+ begin
+ md5 := MD5File(fname);
+ // sorry for pasta, i am asshole
+ if not MD5Match(md5, tf.hash) then
+ begin
+ e_LogWritefln('resuming failed; downloading resource `%s` to `%s` from scratch...', [tf.diskName, fname]);
+ try
+ DeleteFile(fname);
+ strm := createDiskFile(fname);
+ except
+ e_WriteLog('cannot create resource file `'+fname+'`', TMsgType.Fatal);
+ result := '';
+ exit;
+ end;
+ try
+ res := g_Net_ReceiveResourceFile(f, tf, strm);
+ except
+ e_WriteLog('error downloading map file `'+FileName+'`', TMsgType.Fatal);
+ strm.Free;
+ result := '';
+ exit;
+ end;
+ strm.Free;
+ if (res <> 0) then
+ begin
+ e_WriteLog('error downloading map file `'+FileName+'`', TMsgType.Fatal);
+ result := '';
+ exit;
+ end;
+ end;
+ end;
+ addReplacementWad(tf.diskName, fname);
end;
end;
finally
resList.Free;
+ g_Res_received_map_start := 0;
end;
end;
+initialization
+ conRegVar('rdl_ignore_names', @g_res_ignore_names, 'list of resource wad names (without extensions) to ignore in dl hash checks', 'dl ignore wads');
+ conRegVar('rdl_ignore_enabled', @g_res_ignore_enabled, 'enable dl hash check ignore list', 'dl hash check ignore list active');
end.