ae645a1196677443c505ee10f75dcd0e16f63193
1 (* Copyright (C) Doom 2D: Forever Developers
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.
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.
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/>.
15 {$INCLUDE ../shared/a_modes.inc}
16 unit g_res_downloader
;
20 uses sysutils
, Classes
, md5
, g_net
, g_netmsg
, g_console
, g_main
, e_log
;
22 function g_Res_SearchSameWAD(const path
, filename
: AnsiString; const resMd5
: TMD5Digest
): AnsiString;
24 // download map wad from server (if necessary)
25 // download all required map resource wads too
26 // returns name of the map wad (relative to mapdir), or empty string on error
27 function g_Res_DownloadMapWAD (FileName
: AnsiString; const mapHash
: TMD5Digest
): AnsiString;
29 // call this before downloading a new map from a server
30 procedure g_Res_ClearReplacementWads ();
31 // returns original name, or replacement name
32 function g_Res_FindReplacementWad (oldname
: AnsiString): AnsiString;
33 procedure g_Res_PutReplacementWad (oldname
: AnsiString; newDiskName
: AnsiString);
38 uses g_language
, sfs
, utils
, wadreader
, g_game
, hashtable
;
40 //const DOWNLOAD_DIR = 'downloads';
43 replacements
: THashStrStr
= nil;
46 // call this before downloading a new map from a server
47 procedure g_Res_ClearReplacementWads ();
49 if assigned(replacements
) then replacements
.clear();
50 e_LogWriteln('cleared replacement wads');
54 // returns original name, or replacement name
55 function g_Res_FindReplacementWad (oldname
: AnsiString): AnsiString;
60 if not assigned(replacements
) then exit
;
61 if (replacements
.get(toLowerCase1251(ExtractFileName(oldname
)), fn
)) then result
:= fn
;
65 procedure g_Res_PutReplacementWad (oldname
: AnsiString; newDiskName
: AnsiString);
67 e_LogWritefln('adding replacement wad: oldname=%s; newname=%s', [oldname
, newDiskName
]);
68 if not assigned(replacements
) then replacements
:= THashStrStr
.Create();
69 replacements
.put(toLowerCase1251(oldname
), newDiskName
);
73 function scanDir (dirName
: AnsiString; baseName
: AnsiString; const resMd5
: TMD5Digest
): AnsiString;
75 searchResult
: TSearchRec
;
78 dirs
: array of AnsiString;
83 if (length(baseName
) = 0) then exit
;
84 dirName
:= IncludeTrailingPathDelimiter(dirName
);
85 e_LogWritefln('scanning dir `%s` for file `%s`...', [dirName
, baseName
]);
88 if (FindFirst(dirName
+'*', faAnyFile
, searchResult
) <> 0) then exit
;
91 if ((searchResult
.Attr
and faDirectory
) = 0) then
93 if (isWadNamesEqu(searchResult
.Name
, baseName
)) then
95 dfn
:= dirName
+searchResult
.Name
;
96 if FileExists(dfn
) then
98 e_LogWritefln(' found `%s`...', [dfn
]);
100 if MD5Match(md5
, resMd5
) then
102 e_LogWritefln(' MATCH `%s`...', [dfn
]);
112 if (searchResult
.Name
<> '.') and (searchResult
.Name
<> '..') then
114 dfn
:= dirName
+searchResult
.Name
;
115 SetLength(dirs
, Length(dirs
)+1);
116 dirs
[length(dirs
)-1] := dfn
;
119 until (FindNext(searchResult
) <> 0);
121 FindClose(searchResult
);
125 for f
:= 0 to High(dirs
) do
128 result
:= scanDir(dfn
, baseName
, resMd5
);
129 if (length(result
) <> 0) then begin SetLength(dirs
, 0); exit
; end;
135 function g_Res_SearchResWad (asMap
: Boolean; fname
: AnsiString; const resMd5
: TMD5Digest
): AnsiString;
138 //if not assigned(scannedDirs) then scannedDirs := THashStrInt.Create();
141 result
:= scanDir(GameDir
+'/maps', ExtractFileName(fname
), resMd5
);
145 result
:= scanDir(GameDir
+'/wads', ExtractFileName(fname
), resMd5
);
150 function g_Res_SearchSameWAD (const path
, filename
: AnsiString; const resMd5
: TMD5Digest
): AnsiString;
152 result
:= scanDir(path
, filename
, resMd5
);
156 function g_Res_DownloadMapWAD (FileName
: AnsiString; const mapHash
: TMD5Digest
): AnsiString;
158 tf
: TNetFileTransfer
;
159 resList
: TStringList
;
165 //SetLength(mapData.ExternalResources, 0);
167 g_Res_ClearReplacementWads();
168 g_Res_received_map_start
:= false;
170 resList
:= TStringList
.Create();
173 g_Console_Add(Format(_lc
[I_NET_MAP_DL
], [FileName
]));
174 e_WriteLog('Downloading map `' + FileName
+ '` from server', TMsgType
.Notify
);
175 g_Game_SetLoadingText(FileName
+ '...', 0, False);
176 //MC_SEND_MapRequest();
177 if (not g_Net_SendMapRequest()) then exit
;
179 FileName
:= ExtractFileName(FileName
);
180 if (length(FileName
) = 0) then FileName
:= 'fucked_map_wad.wad';
181 res
:= g_Net_Wait_MapInfo(tf
, resList
);
182 if (res
<> 0) then exit
;
184 // find or download a map
185 result
:= g_Res_SearchResWad(true{asMap}, tf
.diskName
, mapHash
);
186 if (length(result
) = 0) then
189 res
:= g_Net_RequestResFileInfo(-1{map}, tf
);
192 e_LogWriteln('error requesting map wad');
197 CreateDir(GameDir
+'/maps/downloads');
200 fname
:= GameDir
+'/maps/downloads/'+FileName
;
202 strm
:= createDiskFile(fname
);
204 e_WriteLog('cannot create map file `'+FileName
+'`', TMsgType
.Fatal
);
208 tf
.diskName
:= fname
;
210 res
:= g_Net_ReceiveResourceFile(-1{map}, tf
, strm
);
212 e_WriteLog('error downloading map file `'+FileName
+'`', TMsgType
.Fatal
);
220 e_WriteLog('error downloading map file `'+FileName
+'`', TMsgType
.Fatal
);
227 // download resources
228 for f
:= 0 to resList
.Count
-1 do
230 res
:= g_Net_RequestResFileInfo(f
, tf
);
231 if (res
<> 0) then begin result
:= ''; exit
; end;
232 wadname
:= g_Res_SearchResWad(false{asMap}, tf
.diskName
, tf
.hash
);
233 if (length(wadname
) <> 0) then
236 g_Net_AbortResTransfer(tf
);
237 g_Res_PutReplacementWad(tf
.diskName
, wadname
);
242 CreateDir(GameDir
+'/wads/downloads');
245 fname
:= GameDir
+'/wads/downloads/'+tf
.diskName
;
246 e_LogWritefln('downloading resource `%s` to `%s`...', [tf
.diskName
, fname
]);
248 strm
:= createDiskFile(fname
);
250 e_WriteLog('cannot create resource file `'+fname
+'`', TMsgType
.Fatal
);
255 res
:= g_Net_ReceiveResourceFile(f
, tf
, strm
);
257 e_WriteLog('error downloading map file `'+FileName
+'`', TMsgType
.Fatal
);
265 e_WriteLog('error downloading map file `'+FileName
+'`', TMsgType
.Fatal
);
269 g_Res_PutReplacementWad(tf
.diskName
, fname
);