DEADSOFTWARE

do not use TFileStream directly, use `openDiskFileRO()` and `createDiskFile()` from...
[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, sfs, utils, wadreader;
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 StrEquCI1251(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, filename, files);
34 until FindNext(searchResult) <> 0;
35 finally
36 FindClose(searchResult);
37 end;
38 end;
39 end;
41 function CompareFileHash(const filename: string; const resMd5: TMD5Digest): Boolean;
42 var
43 gResHash: TMD5Digest;
44 fname: string;
45 begin
46 fname := findDiskWad(filename);
47 if length(fname) = 0 then begin result := false; exit; end;
48 gResHash := MD5File(fname);
49 Result := MD5Match(gResHash, resMd5);
50 end;
52 function CheckFileHash(const path, filename: string; const resMd5: TMD5Digest): Boolean;
53 var
54 fname: string;
55 begin
56 fname := findDiskWad(path+filename);
57 if length(fname) = 0 then begin result := false; exit; end;
58 Result := FileExists(fname) and CompareFileHash(fname, resMd5);
59 end;
61 function g_Res_SearchSameWAD(const path, filename: string; const resMd5: TMD5Digest): string;
62 var
63 res: string;
64 files: TStringList;
65 i: Integer;
66 begin
67 Result := '';
69 if CheckFileHash(path, filename, resMd5) then
70 begin
71 Result := path + filename;
72 Exit;
73 end;
75 files := TStringList.Create;
77 FindFiles(path, filename, files);
78 for i := 0 to files.Count - 1 do
79 begin
80 res := files.Strings[i];
81 if CompareFileHash(res, resMd5) then
82 begin
83 Result := res;
84 Break;
85 end;
86 end;
88 files.Free;
89 end;
91 function SaveWAD(const path, filename: string; const data: array of Byte): string;
92 var
93 resFile: TStream;
94 dpt: string;
95 begin
96 try
97 result := path+DOWNLOAD_DIR+'/'+filename;
98 dpt := path+DOWNLOAD_DIR;
99 if not findFileCI(dpt, true) then CreateDir(dpt);
100 resFile := createDiskFile(result);
101 resFile.WriteBuffer(data[0], Length(data));
102 resFile.Free
103 except
104 Result := '';
105 end;
106 end;
108 function g_Res_DownloadWAD(const FileName: string): string;
109 var
110 msgStream: TMemoryStream;
111 resStream: TStream;
112 mapData: TMapDataMsg;
113 i: Integer;
114 resData: TResDataMsg;
115 begin
116 SetLength(mapData.ExternalResources, 0);
117 g_Console_Add(Format(_lc[I_NET_MAP_DL], [FileName]));
118 e_WriteLog('Downloading map `' + FileName + '` from server', MSG_NOTIFY);
119 MC_SEND_MapRequest();
121 msgStream := g_Net_Wait_Event(NET_MSG_MAP_RESPONSE);
122 if msgStream <> nil then
123 begin
124 mapData := MapDataFromMsgStream(msgStream);
125 msgStream.Free;
126 end;
128 for i := 0 to High(mapData.ExternalResources) do
129 begin
130 if not CheckFileHash(GameDir + '/wads/',
131 mapData.ExternalResources[i].Name,
132 mapData.ExternalResources[i].md5) then
133 begin
134 g_Console_Add(Format(_lc[I_NET_WAD_DL],
135 [mapData.ExternalResources[i].Name]));
136 e_WriteLog('Downloading Wad `' + mapData.ExternalResources[i].Name +
137 '` from server', MSG_NOTIFY);
138 MC_SEND_ResRequest(mapData.ExternalResources[i].Name);
140 msgStream := g_Net_Wait_Event(NET_MSG_RES_RESPONSE);
141 resData := ResDataFromMsgStream(msgStream);
143 resStream := createDiskFile(GameDir+'/wads/'+mapData.ExternalResources[i].Name);
144 resStream.WriteBuffer(resData.FileData[0], resData.FileSize);
146 resData.FileData := nil;
147 resStream.Free;
148 msgStream.Free;
149 end;
150 end;
152 Result := SaveWAD(MapsDir, ExtractFileName(FileName), mapData.FileData);
153 end;
155 end.