DEADSOFTWARE

78b0b2803ddccde223d34b5705f9def7191d5b63
[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, g_game;
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', 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
140 begin
141 mapData := MapDataFromMsgStream(msgStream);
142 msgStream.Free;
143 end else
144 mapData.FileSize := 0;
146 for i := 0 to High(mapData.ExternalResources) do
147 begin
148 if not CheckFileHash(GameDir + '/wads/',
149 mapData.ExternalResources[i].Name,
150 mapData.ExternalResources[i].md5) then
151 begin
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
161 continue;
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;
169 resStream.Free;
170 msgStream.Free;
171 end;
172 end;
174 Result := SaveWAD(MapsDir, ExtractFileName(FileName), mapData.FileData);
175 if mapData.FileSize = 0 then
176 DeleteFile(Result);
177 end;
179 end.