DEADSOFTWARE

typo in mapcvt: microseconds -> milliseconds
[d2df-sdl.git] / src / game / g_res_downloader.pas
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, either version 3 of the License, or
6 * (at your option) any later version.
7 *
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.
12 *
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/>.
15 *)
16 {$INCLUDE ../shared/a_modes.inc}
17 unit g_res_downloader;
19 interface
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;
26 implementation
28 uses g_language, sfs, utils, wadreader;
30 const DOWNLOAD_DIR = 'downloads';
32 procedure FindFiles(const dirName, filename: string; var files: TStringList);
33 var
34 searchResult: TSearchRec;
35 begin
36 if FindFirst(dirName+'/*', faAnyFile, searchResult) = 0 then
37 begin
38 try
39 repeat
40 if (searchResult.Attr and faDirectory) = 0 then
41 begin
42 if StrEquCI1251(searchResult.Name, filename) then
43 begin
44 files.Add(dirName+'/'+filename);
45 Exit;
46 end;
47 end
48 else if (searchResult.Name <> '.') and (searchResult.Name <> '..') then
49 FindFiles(IncludeTrailingPathDelimiter(dirName)+searchResult.Name, filename, files);
50 until FindNext(searchResult) <> 0;
51 finally
52 FindClose(searchResult);
53 end;
54 end;
55 end;
57 function CompareFileHash(const filename: string; const resMd5: TMD5Digest): Boolean;
58 var
59 gResHash: TMD5Digest;
60 fname: string;
61 begin
62 fname := findDiskWad(filename);
63 if length(fname) = 0 then begin result := false; exit; end;
64 gResHash := MD5File(fname);
65 Result := MD5Match(gResHash, resMd5);
66 end;
68 function CheckFileHash(const path, filename: string; const resMd5: TMD5Digest): Boolean;
69 var
70 fname: string;
71 begin
72 fname := findDiskWad(path+filename);
73 if length(fname) = 0 then begin result := false; exit; end;
74 Result := FileExists(fname) and CompareFileHash(fname, resMd5);
75 end;
77 function g_Res_SearchSameWAD(const path, filename: string; const resMd5: TMD5Digest): string;
78 var
79 res: string;
80 files: TStringList;
81 i: Integer;
82 begin
83 Result := '';
85 if CheckFileHash(path, filename, resMd5) then
86 begin
87 Result := path + filename;
88 Exit;
89 end;
91 files := TStringList.Create;
93 FindFiles(path, filename, files);
94 for i := 0 to files.Count - 1 do
95 begin
96 res := files.Strings[i];
97 if CompareFileHash(res, resMd5) then
98 begin
99 Result := res;
100 Break;
101 end;
102 end;
104 files.Free;
105 end;
107 function SaveWAD(const path, filename: string; const data: array of Byte): string;
108 var
109 resFile: TStream;
110 dpt: string;
111 begin
112 try
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));
118 resFile.Free
119 except
120 Result := '';
121 end;
122 end;
124 function g_Res_DownloadWAD(const FileName: string): string;
125 var
126 msgStream: TMemoryStream;
127 resStream: TStream;
128 mapData: TMapDataMsg;
129 i: Integer;
130 resData: TResDataMsg;
131 begin
132 SetLength(mapData.ExternalResources, 0);
133 g_Console_Add(Format(_lc[I_NET_MAP_DL], [FileName]));
134 e_WriteLog('Downloading map `' + FileName + '` from server', MSG_NOTIFY);
135 MC_SEND_MapRequest();
137 msgStream := g_Net_Wait_Event(NET_MSG_MAP_RESPONSE);
138 if msgStream <> nil then
139 begin
140 mapData := MapDataFromMsgStream(msgStream);
141 msgStream.Free;
142 end;
144 for i := 0 to High(mapData.ExternalResources) do
145 begin
146 if not CheckFileHash(GameDir + '/wads/',
147 mapData.ExternalResources[i].Name,
148 mapData.ExternalResources[i].md5) then
149 begin
150 g_Console_Add(Format(_lc[I_NET_WAD_DL],
151 [mapData.ExternalResources[i].Name]));
152 e_WriteLog('Downloading Wad `' + mapData.ExternalResources[i].Name +
153 '` from server', MSG_NOTIFY);
154 MC_SEND_ResRequest(mapData.ExternalResources[i].Name);
156 msgStream := g_Net_Wait_Event(NET_MSG_RES_RESPONSE);
157 resData := ResDataFromMsgStream(msgStream);
159 resStream := createDiskFile(GameDir+'/wads/'+mapData.ExternalResources[i].Name);
160 resStream.WriteBuffer(resData.FileData[0], resData.FileSize);
162 resData.FileData := nil;
163 resStream.Free;
164 msgStream.Free;
165 end;
166 end;
168 Result := SaveWAD(MapsDir, ExtractFileName(FileName), mapData.FileData);
169 end;
171 end.