DEADSOFTWARE

9547335009a7296361e17b018196f7e6846c3278
[d2df-sdl.git] / src / game / g_res_downloader.pas
1 unit g_res_downloader;
3 interface
5 uses sysutils, Classes, md5, g_net, g_netmsg, g_console, g_main, e_log;
7 function g_Res_SearchSameWAD(const path, filename: string; const resMd5: TMD5Digest): string;
8 function g_Res_DownloadWAD(const FileName: string): string;
10 implementation
12 uses g_language;
14 const DOWNLOAD_DIR = 'downloads';
16 procedure FindFiles(const dirName, filename: string; var files: TStringList);
17 var
18 searchResult: TSearchRec;
19 begin
20 if FindFirst(dirName+'/*', faAnyFile, searchResult) = 0 then
21 begin
22 try
23 repeat
24 if (searchResult.Attr and faDirectory) = 0 then
25 begin
26 if searchResult.Name = filename then
27 begin
28 files.Add(dirName+'/'+filename);
29 Exit;
30 end;
31 end
32 else if (searchResult.Name <> '.') and (searchResult.Name <> '..') then
33 FindFiles(IncludeTrailingPathDelimiter(dirName)+searchResult.Name,
34 filename, files);
35 until FindNext(searchResult) <> 0;
36 finally
37 FindClose(searchResult);
38 end;
39 end;
40 end;
42 function CompareFileHash(const filename: string; const resMd5: TMD5Digest): Boolean;
43 var
44 gResHash: TMD5Digest;
45 begin
46 gResHash := MD5File(filename);
47 Result := MD5Match(gResHash, resMd5);
48 end;
50 function CheckFileHash(const path, filename: string; const resMd5: TMD5Digest): Boolean;
51 begin
52 Result := FileExists(path + filename) and CompareFileHash(path + filename, resMd5);
53 end;
55 function g_Res_SearchSameWAD(const path, filename: string; const resMd5: TMD5Digest): string;
56 var
57 res: string;
58 files: TStringList;
59 i: Integer;
60 begin
61 Result := '';
63 if CheckFileHash(path, filename, resMd5) then
64 begin
65 Result := path + filename;
66 Exit;
67 end;
69 files := TStringList.Create;
71 FindFiles(path, filename, files);
72 for i := 0 to files.Count - 1 do
73 begin
74 res := files.Strings[i];
75 if CompareFileHash(res, resMd5) then
76 begin
77 Result := res;
78 Break;
79 end;
80 end;
82 files.Free;
83 end;
85 function SaveWAD(const path, filename: string; const data: array of Byte): string;
86 var
87 resFile: TFileStream;
88 begin
89 try
90 Result := path + DOWNLOAD_DIR + '/' + filename;
91 if not DirectoryExists(path + DOWNLOAD_DIR) then
92 begin
93 CreateDir(path + DOWNLOAD_DIR);
94 end;
95 resFile := TFileStream.Create(Result, fmCreate);
96 resFile.WriteBuffer(data[0], Length(data));
97 resFile.Free
98 except
99 Result := '';
100 end;
101 end;
103 function g_Res_DownloadWAD(const FileName: string): string;
104 var
105 msgStream: TMemoryStream;
106 resStream: TFileStream;
107 mapData: TMapDataMsg;
108 i: Integer;
109 resData: TResDataMsg;
110 begin
111 SetLength(mapData.ExternalResources, 0);
112 g_Console_Add(Format(_lc[I_NET_MAP_DL], [FileName]));
113 e_WriteLog('Downloading map `' + FileName + '` from server', MSG_NOTIFY);
114 MC_SEND_MapRequest();
116 msgStream := g_Net_Wait_Event(NET_MSG_MAP_RESPONSE);
117 if msgStream <> nil then
118 begin
119 mapData := MapDataFromMsgStream(msgStream);
120 msgStream.Free;
121 end;
123 for i := 0 to High(mapData.ExternalResources) do
124 begin
125 if not CheckFileHash(GameDir + '/wads/',
126 mapData.ExternalResources[i].Name,
127 mapData.ExternalResources[i].md5) then
128 begin
129 g_Console_Add(Format(_lc[I_NET_WAD_DL],
130 [mapData.ExternalResources[i].Name]));
131 e_WriteLog('Downloading Wad `' + mapData.ExternalResources[i].Name +
132 '` from server', MSG_NOTIFY);
133 MC_SEND_ResRequest(mapData.ExternalResources[i].Name);
135 msgStream := g_Net_Wait_Event(NET_MSG_RES_RESPONSE);
136 resData := ResDataFromMsgStream(msgStream);
138 resStream := TFileStream.Create(GameDir+'/wads/'+
139 mapData.ExternalResources[i].Name,
140 fmCreate);
141 resStream.WriteBuffer(resData.FileData[0], resData.FileSize);
143 resData.FileData := nil;
144 resStream.Free;
145 msgStream.Free;
146 end;
147 end;
149 Result := SaveWAD(MapsDir, ExtractFileName(FileName), mapData.FileData);
150 end;
152 end.