DEADSOFTWARE

net: map downloading seems to work
authorKetmar Dark <ketmar@ketmar.no-ip.org>
Sat, 12 Oct 2019 00:55:59 +0000 (03:55 +0300)
committerKetmar Dark <ketmar@ketmar.no-ip.org>
Sat, 12 Oct 2019 15:54:12 +0000 (18:54 +0300)
src/game/g_game.pas
src/game/g_res_downloader.pas
src/shared/utils.pas

index 46251bb7d3e2684ec69a340f2ad415de97f6f821..43ccf4ff22e1b3eb6ddce0e748c52477a87007e0 100644 (file)
@@ -4663,10 +4663,10 @@ begin
           gGameSettings.Options := InMsg.ReadLongWord();
           T := InMsg.ReadLongWord();
 
-          newResPath := g_Res_SearchSameWAD(MapsDir, WadName, gWADHash);
-          if newResPath = '' then
+          //newResPath := g_Res_SearchSameWAD(MapsDir, WadName, gWADHash);
+          //if newResPath = '' then
           begin
-            g_Game_SetLoadingText(_lc[I_LOAD_DL_RES], 0, False);
+            //g_Game_SetLoadingText(_lc[I_LOAD_DL_RES], 0, False);
             newResPath := g_Res_DownloadMapWAD(WadName, gWADHash);
             if newResPath = '' then
             begin
@@ -5012,10 +5012,21 @@ procedure g_Game_ClientWAD(NewWAD: String; const WHash: TMD5Digest);
 var
   gWAD: String;
 begin
-  if LowerCase(NewWAD) = LowerCase(gGameSettings.WAD) then
-    Exit;
-  if not g_Game_IsClient then
+  if not g_Game_IsClient then Exit;
+
+  gWAD := g_Res_DownloadMapWAD(ExtractFileName(NewWAD), WHash);
+  if gWAD = '' then
+  begin
+    g_Game_Free();
+    g_FatalError(Format(_lc[I_GAME_ERROR_MAP_WAD], [ExtractFileName(NewWAD)]));
     Exit;
+  end;
+
+  NewWAD := ExtractRelativePath(MapsDir, gWAD);
+  g_Game_LoadWAD(NewWAD);
+
+  {
+  if LowerCase(NewWAD) = LowerCase(gGameSettings.WAD) then Exit;
   gWAD := g_Res_SearchSameWAD(MapsDir, ExtractFileName(NewWAD), WHash);
   if gWAD = '' then
   begin
@@ -5030,6 +5041,7 @@ begin
   end;
   NewWAD := ExtractRelativePath(MapsDir, gWAD);
   g_Game_LoadWAD(NewWAD);
+  }
 end;
 
 procedure g_Game_RestartRound(NoMapRestart: Boolean = False);
index 72717573b0b9b39303a0d8f4d707891ac350c5b1..d9cf5684c508c43eed986b311e1dcad0aba5a6f9 100644 (file)
@@ -37,120 +37,12 @@ implementation
 
 uses g_language, sfs, utils, wadreader, g_game, hashtable;
 
-const DOWNLOAD_DIR = 'downloads';
-
-type
-  TFileInfo = record
-    diskName: AnsiString; // lowercased
-    baseName: AnsiString; // lowercased
-    md5: TMD5Digest;
-    md5valid: Boolean;
-    nextBaseNameIndex: Integer;
-  end;
+//const DOWNLOAD_DIR = 'downloads';
 
 var
-  knownFiles: array of TFileInfo;
-  knownHash: THashStrInt = nil; // key: base name; value: index
-  scannedDirs: THashStrInt = nil; // key: lowercased dir name
   replacements: THashStrStr = nil;
 
 
-function findKnownFile (diskName: AnsiString): Integer;
-var
-  idx: Integer;
-  baseName: AnsiString;
-begin
-  result := -1;
-  if not assigned(knownHash) then exit;
-  if (length(diskName) = 0) then exit;
-  baseName := toLowerCase1251(ExtractFileName(diskName));
-  if (not knownHash.get(baseName, idx)) then exit;
-  if (idx < 0) or (idx >= length(knownFiles)) then raise Exception.Create('wutafuck?');
-  while (idx >= 0) do
-  begin
-    if (strEquCI1251(knownFiles[idx].diskName, diskName)) then begin result := idx; exit; end; // i found her!
-    idx := knownFiles[idx].nextBaseNameIndex;
-  end;
-end;
-
-
-function addKnownFile (diskName: AnsiString): Integer;
-var
-  idx: Integer;
-  lastIdx: Integer = -1;
-  baseName: AnsiString;
-  fi: ^TFileInfo;
-begin
-  result := -1;
-  if not assigned(knownHash) then knownHash := THashStrInt.Create();
-  if (length(diskName) = 0) then exit;
-  baseName := toLowerCase1251(ExtractFileName(diskName));
-  if (length(baseName) = 0) then exit;
-  // check if we already have this file
-  if (knownHash.get(baseName, idx)) then
-  begin
-    if (idx < 0) or (idx >= length(knownFiles)) then raise Exception.Create('wutafuck?');
-    while (idx >= 0) do
-    begin
-      if (strEquCI1251(knownFiles[idx].diskName, diskName)) then
-      begin
-        // already here
-        result := idx;
-        exit;
-      end;
-      lastIdx := idx;
-      idx := knownFiles[idx].nextBaseNameIndex;
-    end;
-  end;
-  // this file is not there, append it
-  idx := length(knownFiles);
-  result := idx;
-  SetLength(knownFiles, idx+1); // sorry
-  fi := @knownFiles[idx];
-  fi.diskName := diskName;
-  fi.baseName := baseName;
-  fi.md5valid := false;
-  fi.nextBaseNameIndex := -1;
-  if (lastIdx < 0) then
-  begin
-    // totally new one
-    knownHash.put(baseName, idx);
-  end
-  else
-  begin
-    knownFiles[lastIdx].nextBaseNameIndex := idx;
-  end;
-end;
-
-
-function getKnownFileWithMD5 (diskDir: AnsiString; baseName: AnsiString; const md5: TMD5Digest): AnsiString;
-var
-  idx: Integer;
-begin
-  result := '';
-  if not assigned(knownHash) then exit;
-  if (not knownHash.get(toLowerCase1251(baseName), idx)) then exit;
-  if (idx < 0) or (idx >= length(knownFiles)) then raise Exception.Create('wutafuck?');
-  while (idx >= 0) do
-  begin
-    if (strEquCI1251(knownFiles[idx].diskName, IncludeTrailingPathDelimiter(diskDir)+baseName)) then
-    begin
-      if (not knownFiles[idx].md5valid) then
-      begin
-        knownFiles[idx].md5 := MD5File(knownFiles[idx].diskName);
-        knownFiles[idx].md5valid := true;
-      end;
-      if (MD5Match(knownFiles[idx].md5, md5)) then
-      begin
-        result := knownFiles[idx].diskName;
-        exit;
-      end;
-    end;
-    idx := knownFiles[idx].nextBaseNameIndex;
-  end;
-end;
-
-
 // call this before downloading a new map from a server
 procedure g_Res_ClearReplacementWads ();
 begin
@@ -178,106 +70,86 @@ begin
 end;
 
 
-procedure scanDir (const dirName: AnsiString; calcMD5: Boolean);
+function scanDir (dirName: AnsiString; baseName: AnsiString; const resMd5: TMD5Digest): AnsiString;
 var
   searchResult: TSearchRec;
   dfn: AnsiString;
-  idx: Integer;
+  md5: TMD5Digest;
+  dirs: array of AnsiString;
+  f: Integer;
 begin
-  if not assigned(scannedDirs) then scannedDirs := THashStrInt.Create();
-  dfn := toLowerCase1251(IncludeTrailingPathDelimiter(dirName));
-  if scannedDirs.has(dfn) then exit;
-  scannedDirs.put(dfn, 42);
+  result := '';
+  SetLength(dirs, 0);
+  if (length(baseName) = 0) then exit;
+  dirName := IncludeTrailingPathDelimiter(dirName);
+  e_LogWritefln('scanning dir `%s` for file `%s`...', [dirName, baseName]);
 
-  if (FindFirst(dirName+'/*', faAnyFile, searchResult) <> 0) then exit;
+  // scan files
+  if (FindFirst(dirName+'*', faAnyFile, searchResult) <> 0) then exit;
   try
     repeat
-      if (searchResult.Attr and faDirectory) = 0 then
+      if ((searchResult.Attr and faDirectory) = 0) then
       begin
-        dfn := dirName+'/'+searchResult.Name;
-        idx := addKnownFile(dfn);
-        if (calcMD5) and (idx >= 0) then
+        if (isWadNamesEqu(searchResult.Name, baseName)) then
         begin
-          if (not knownFiles[idx].md5valid) then
+          dfn := dirName+searchResult.Name;
+          if FileExists(dfn) then
           begin
-            knownFiles[idx].md5 := MD5File(knownFiles[idx].diskName);
-            knownFiles[idx].md5valid := true;
+            e_LogWritefln('  found `%s`...', [dfn]);
+            md5 := MD5File(dfn);
+            if MD5Match(md5, resMd5) then
+            begin
+              e_LogWritefln('    MATCH `%s`...', [dfn]);
+              SetLength(dirs, 0);
+              result := dfn;
+              exit;
+            end;
           end;
         end;
       end
-      else if (searchResult.Name <> '.') and (searchResult.Name <> '..') then
+      else
       begin
-        scanDir(IncludeTrailingPathDelimiter(dirName)+searchResult.Name, calcMD5);
+        if (searchResult.Name <> '.') and (searchResult.Name <> '..') then
+        begin
+          dfn := dirName+searchResult.Name;
+          SetLength(dirs, Length(dirs)+1);
+          dirs[length(dirs)-1] := dfn;
+        end;
       end;
     until (FindNext(searchResult) <> 0);
   finally
     FindClose(searchResult);
   end;
-end;
-
 
-function CompareFileHash(const filename: AnsiString; const resMd5: TMD5Digest): Boolean;
-var
-  gResHash: TMD5Digest;
-  fname: AnsiString;
-begin
-  fname := findDiskWad(filename);
-  if length(fname) = 0 then begin result := false; exit; end;
-  gResHash := MD5File(fname);
-  Result := MD5Match(gResHash, resMd5);
-end;
-
-function CheckFileHash(const path, filename: AnsiString; const resMd5: TMD5Digest): Boolean;
-var
-  fname: AnsiString;
-begin
-  fname := findDiskWad(path+filename);
-  if length(fname) = 0 then begin result := false; exit; end;
-  Result := FileExists(fname) and CompareFileHash(fname, resMd5);
+  // scan subdirs
+  for f := 0 to High(dirs) do
+  begin
+    dfn := dirs[f];
+    result := scanDir(dfn, baseName, resMd5);
+    if (length(result) <> 0) then begin SetLength(dirs, 0); exit; end;
+  end;
+  SetLength(dirs, 0);
 end;
 
 
 function g_Res_SearchResWad (asMap: Boolean; fname: AnsiString; const resMd5: TMD5Digest): AnsiString;
-var
-  f: Integer;
 begin
   result := '';
   //if not assigned(scannedDirs) then scannedDirs := THashStrInt.Create();
   if (asMap) then
   begin
-    if CheckFileHash(GameDir+'/maps', fname, resMd5) then
-    begin
-      result := findDiskWad(GameDir+'/maps/'+fname);
-      if (length(result) <> 0) then exit;
-    end;
-    scanDir(GameDir+'/maps/downloads', true);
+    result := scanDir(GameDir+'/maps', ExtractFileName(fname), resMd5);
   end
   else
   begin
-    if CheckFileHash(GameDir+'/wads', fname, resMd5) then
-    begin
-      result := findDiskWad(GameDir+'/wads/'+fname);
-      if (length(result) <> 0) then exit;
-    end;
-    scanDir(GameDir+'/wads/downloads', true);
+    result := scanDir(GameDir+'/wads', ExtractFileName(fname), resMd5);
   end;
-  for f := Low(knownFiles) to High(knownFiles) do
-  begin
-    if (not knownFiles[f].md5valid) then continue;
-    if (MD5Match(knownFiles[f].md5, resMd5)) then
-    begin
-      result := knownFiles[f].diskName;
-      exit;
-    end;
-  end;
-  //resStream := createDiskFile(GameDir+'/wads/'+mapData.ExternalResources[i].Name);
 end;
 
 
 function g_Res_SearchSameWAD (const path, filename: AnsiString; const resMd5: TMD5Digest): AnsiString;
 begin
-  scanDir(path, false);
-  result := getKnownFileWithMD5(path, filename, resMd5);
+  result := scanDir(path, filename, resMd5);
 end;
 
 
@@ -287,9 +159,7 @@ var
   resList: TStringList;
   f, res: Integer;
   strm: TStream;
-  mmd5: TMD5Digest;
   fname: AnsiString;
-  idx: Integer;
   wadname: AnsiString;
 begin
   //SetLength(mapData.ExternalResources, 0);
@@ -357,22 +227,6 @@ begin
         result := '';
         exit;
       end;
-      mmd5 := MD5File(fname);
-      if (not MD5Match(mmd5, mapHash)) then
-      begin
-        e_WriteLog('error downloading map file `'+FileName+'` (bad hash)', TMsgType.Fatal);
-        result := '';
-        exit;
-      end;
-      idx := addKnownFile(fname);
-      if (idx < 0) then
-      begin
-        e_WriteLog('error downloading map file `'+FileName+'`', TMsgType.Fatal);
-        result := '';
-        exit;
-      end;
-      knownFiles[idx].md5 := mmd5;
-      knownFiles[idx].md5valid := true;
       result := fname;
     end;
 
@@ -391,6 +245,7 @@ begin
       else
       begin
         fname := GameDir+'/wads/downloads/'+tf.diskName;
+        e_LogWritefln('downloading resource `%s` to `%s`...', [tf.diskName, fname]);
         try
           strm := createDiskFile(fname);
         except
@@ -413,15 +268,6 @@ begin
           result := '';
           exit;
         end;
-        idx := addKnownFile(fname);
-        if (idx < 0) then
-        begin
-          e_WriteLog('error downloading map file `'+FileName+'`', TMsgType.Fatal);
-          result := '';
-          exit;
-        end;
-        knownFiles[idx].md5 := tf.hash;
-        knownFiles[idx].md5valid := true;
         g_Res_PutReplacementWad(tf.diskName, fname);
       end;
     end;
index 5cd2af8831b8e7a1673338b1895691610f7f463a..a854ca45bc922f155465ed98a32daad0710ced8c 100644 (file)
@@ -104,6 +104,8 @@ function findFileCI (var pathname: AnsiString; lastIsDir: Boolean=false): Boolea
 
 // return fixed AnsiString or empty AnsiString
 function findDiskWad (fname: AnsiString): AnsiString;
+// slashes must be normalized!
+function isWadNamesEqu (wna, wnb: AnsiString): Boolean;
 
 // they throws
 function openDiskFileRO (pathname: AnsiString): TStream;
@@ -1148,6 +1150,28 @@ end;
 
 const fileExtensions: array [0..6] of AnsiString = ('.dfz', '.wad', '.dfwad', '.pk3', '.pak', '.zip', '.dfzip');
 
+function isWadNamesEqu (wna, wnb: AnsiString): Boolean;
+var
+  ext, newExt: AnsiString;
+  found: Boolean;
+begin
+  result := StrEquCI1251(wna, wnb);
+  if result then exit;
+  // check first ext
+  ext := getFilenameExt(wna);
+  found := false;
+  for newExt in fileExtensions do if (StrEquCI1251(ext, newExt)) then begin found := true; break; end;
+  if not found then exit;
+  // check second ext
+  ext := getFilenameExt(wnb);
+  found := false;
+  for newExt in fileExtensions do if (StrEquCI1251(ext, newExt)) then begin found := true; break; end;
+  if not found then exit;
+  wna := forceFilenameExt(wna, '');
+  wnb := forceFilenameExt(wnb, '');
+  result := StrEquCI1251(wna, wnb);
+end;
+
 function findDiskWad (fname: AnsiString): AnsiString;
 var
   origExt: AnsiString = '';