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, either version 3 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 {$INCLUDE ../shared/a_modes.inc}
17 unit g_res_downloader
;
21 uses sysutils
, Classes
, md5
, g_net
, g_netmsg
, g_console
, g_main
, e_log
;
23 function g_Res_SearchSameWAD(const path
, filename
: string; const resMd5
: TMD5Digest
): string;
24 function g_Res_DownloadWAD(const FileName
: string): string;
28 uses g_language
, sfs
, utils
, wadreader
, g_game
;
30 const DOWNLOAD_DIR
= 'downloads';
32 procedure FindFiles(const dirName
, filename
: string; var files
: TStringList
);
34 searchResult
: TSearchRec
;
36 if FindFirst(dirName
+'/*', faAnyFile
, searchResult
) = 0 then
40 if (searchResult
.Attr
and faDirectory
) = 0 then
42 if StrEquCI1251(searchResult
.Name
, filename
) then
44 files
.Add(dirName
+'/'+filename
);
48 else if (searchResult
.Name
<> '.') and (searchResult
.Name
<> '..') then
49 FindFiles(IncludeTrailingPathDelimiter(dirName
)+searchResult
.Name
, filename
, files
);
50 until FindNext(searchResult
) <> 0;
52 FindClose(searchResult
);
57 function CompareFileHash(const filename
: string; const resMd5
: TMD5Digest
): Boolean;
62 fname
:= findDiskWad(filename
);
63 if length(fname
) = 0 then begin result
:= false; exit
; end;
64 gResHash
:= MD5File(fname
);
65 Result
:= MD5Match(gResHash
, resMd5
);
68 function CheckFileHash(const path
, filename
: string; const resMd5
: TMD5Digest
): Boolean;
72 fname
:= findDiskWad(path
+filename
);
73 if length(fname
) = 0 then begin result
:= false; exit
; end;
74 Result
:= FileExists(fname
) and CompareFileHash(fname
, resMd5
);
77 function g_Res_SearchSameWAD(const path
, filename
: string; const resMd5
: TMD5Digest
): string;
85 if CheckFileHash(path
, filename
, resMd5
) then
87 Result
:= path
+ filename
;
91 files
:= TStringList
.Create
;
93 FindFiles(path
, filename
, files
);
94 for i
:= 0 to files
.Count
- 1 do
96 res
:= files
.Strings
[i
];
97 if CompareFileHash(res
, resMd5
) then
107 function SaveWAD(const path
, filename
: string; const data
: array of Byte): string;
113 result
:= path
+DOWNLOAD_DIR
+'/'+filename
;
114 dpt
:= path
+DOWNLOAD_DIR
;
115 if not findFileCI(dpt
, true) then CreateDir(dpt
);
116 resFile
:= createDiskFile(result
);
117 resFile
.WriteBuffer(data
[0], Length(data
));
124 function g_Res_DownloadWAD(const FileName
: string): string;
126 msgStream
: TMemoryStream
;
128 mapData
: TMapDataMsg
;
130 resData
: TResDataMsg
;
132 SetLength(mapData
.ExternalResources
, 0);
133 g_Console_Add(Format(_lc
[I_NET_MAP_DL
], [FileName
]));
134 e_WriteLog('Downloading map `' + FileName
+ '` from server', TMsgType
.Notify
);
135 g_Game_SetLoadingText(FileName
+ '...', 0, False);
136 MC_SEND_MapRequest();
138 msgStream
:= g_Net_Wait_Event(NET_MSG_MAP_RESPONSE
);
139 if msgStream
<> nil then
141 mapData
:= MapDataFromMsgStream(msgStream
);
144 mapData
.FileSize
:= 0;
146 for i
:= 0 to High(mapData
.ExternalResources
) do
148 if not CheckFileHash(GameDir
+ '/wads/',
149 mapData
.ExternalResources
[i
].Name
,
150 mapData
.ExternalResources
[i
].md5
) then
152 g_Console_Add(Format(_lc
[I_NET_WAD_DL
],
153 [mapData
.ExternalResources
[i
].Name
]));
154 e_WriteLog('Downloading Wad `' + mapData
.ExternalResources
[i
].Name
+
155 '` from server', TMsgType
.Notify
);
156 g_Game_SetLoadingText(mapData
.ExternalResources
[i
].Name
+ '...', 0, False);
157 MC_SEND_ResRequest(mapData
.ExternalResources
[i
].Name
);
159 msgStream
:= g_Net_Wait_Event(NET_MSG_RES_RESPONSE
);
160 if msgStream
= nil then
163 resData
:= ResDataFromMsgStream(msgStream
);
165 resStream
:= createDiskFile(GameDir
+'/wads/'+mapData
.ExternalResources
[i
].Name
);
166 resStream
.WriteBuffer(resData
.FileData
[0], resData
.FileSize
);
168 resData
.FileData
:= nil;
174 Result
:= SaveWAD(MapsDir
, ExtractFileName(FileName
), mapData
.FileData
);
175 if mapData
.FileSize
= 0 then