DEADSOFTWARE

map: look for replacement resource wads only for network client mode
[d2df-sdl.git] / src / game / g_map.pas
index fef17e0bde166a76136071daefde8f9907c31dd9..4b65cbec5ddbd539a20ff3e06b1e8a6be28a787c 100644 (file)
@@ -2,8 +2,7 @@
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation, version 3 of the License ONLY.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -196,6 +195,7 @@ const
   GridTagLift = 1 shl 8; // gLifts
   GridTagBlockMon = 1 shl 9; // gBlockMon
 
+  GridTagSolid = (GridTagWall or GridTagDoor);
   GridTagObstacle = (GridTagStep or GridTagWall or GridTagDoor);
   GridTagLiquid = (GridTagAcid1 or GridTagAcid2 or GridTagWater);
 
@@ -226,7 +226,7 @@ var
   gLiftMap: array of array of DWORD;
   gWADHash: TMD5Digest;
   BackID:  DWORD = DWORD(-1);
-  gExternalResources: TStringList;
+  gExternalResources: array of TDiskFileInfo = nil;
   gMovingWallIds: array of Integer = nil;
 
   gdbg_map_use_accel_render: Boolean = true;
@@ -259,7 +259,8 @@ uses
   Math, g_monsters, g_saveload, g_language, g_netmsg,
   sfs, xstreams, hashtable, wadreader,
   ImagingTypes, Imaging, ImagingUtility,
-  ImagingGif, ImagingNetworkGraphics;
+  ImagingGif, ImagingNetworkGraphics,
+  g_res_downloader;
 
 const
   FLAGRECT: TRectWH = (X:15; Y:12; Width:33; Height:52);
@@ -899,6 +900,21 @@ begin
 end;
 
 
+function GetReplacementWad (WadName: AnsiString): AnsiString;
+begin
+  if (length(WadName) = 0) then
+  begin
+    result := '';
+  end
+  else
+  begin
+    result := WadName;
+    if g_Game_IsClient then result := g_Res_FindReplacementWad(WadName);
+    if (result = WadName) then result := GameDir+'/wads/'+result;
+  end;
+end;
+
+
 function CreateTexture(RecName: AnsiString; Map: string; log: Boolean): Integer;
 var
   WAD: TWADFile;
@@ -957,12 +973,10 @@ begin
   end;
 
   // Çàãðóæàåì ðåñóðñ òåêñòóðû â ïàìÿòü èç WAD'à:
-  WADName := g_ExtractWadName(RecName);
+  WADName := GetReplacementWad(g_ExtractWadName(RecName));
+  if WADName = '' then WADName := Map; //WADName := GameDir+'/wads/'+WADName else
 
   WAD := TWADFile.Create();
-
-  if WADName <> '' then WADName := GameDir+'/wads/'+WADName else WADName := Map;
-
   WAD.ReadFile(WADName);
 
   //txname := RecName;
@@ -1045,11 +1059,12 @@ begin
   end;
 
   // ×èòàåì WAD-ðåñóðñ àíèì.òåêñòóðû èç WAD'à â ïàìÿòü:
-  WADName := g_ExtractWadName(RecName);
+  WADName := GetReplacementWad(g_ExtractWadName(RecName));
+  if WADName = '' then WADName := Map; //WADName := GameDir+'/wads/'+WADName else
 
   WAD := TWADFile.Create();
   try
-    if WADName <> '' then WADName := GameDir+'/wads/'+WADName else WADName := Map;
+    //if WADName <> '' then WADName := GameDir+'/wads/'+WADName else WADName := Map;
 
     WAD.ReadFile(WADName);
 
@@ -1083,8 +1098,7 @@ begin
     end;
 
     // ýòî ïòèöà? ýòî ñàìîë¸ò?
-    if (TextureWAD[0] = 'D') and (TextureWAD[1] = 'F') and
-       (TextureWAD[2] = 'W') and (TextureWAD[3] = 'A') and (TextureWAD[4] = 'D') then
+    if isWadData(TextureWAD, ResLength) then
     begin
       // íåò, ýòî ñóïåðìåí!
       if not WAD.ReadMemory(TextureWAD, ResLength) then
@@ -1447,50 +1461,66 @@ begin
     Result := '';
 end;
 
-procedure addResToExternalResList(res: string);
-begin
-  res := extractWadName(res);
-  if (res <> '') and (gExternalResources.IndexOf(res) = -1) then
-    gExternalResources.Add(res);
-end;
 
-procedure generateExternalResourcesList({mapReader: TMapReader_1}map: TDynRecord);
-//var
-  //textures: TTexturesRec1Array;
-  //textures: TDynField;
-  //trec: TDynRecord;
-  //mapHeader: TMapHeaderRec_1;
-  //i: integer;
-  //resFile: String = '';
+procedure addResToExternalResList (res: AnsiString);
+var
+  uname: AnsiString;
+  f: Integer;
+  fi: TDiskFileInfo;
 begin
-  if gExternalResources = nil then
-    gExternalResources := TStringList.Create;
-
-  gExternalResources.Clear;
-
-  (*
-  {
-  textures := GetTextures(map);
-  for i := 0 to High(textures) do
+  if g_Game_IsClient or not g_Game_IsNet then exit;
+  if (length(res) = 0) then exit; // map wad
+  res := extractWadName(res);
+  if (length(res) = 0) then exit; // map wad
+  uname := toLowerCase1251(res);
+  // do not add duplicates
+  for f := 0 to High(gExternalResources) do
   begin
-    addResToExternalResList(resFile);
+    if (gExternalResources[f].userName = uname) then exit;
   end;
-  }
+  // add new resource
+  fi.userName := uname;
+  if (not GetDiskFileInfo(GameDir+'/wads/'+res, fi)) then
+  begin
+    fi.tag := -1;
+  end
+  else
+  begin
+    fi.tag := 0; // non-zero means "cannot caclucate hash"
+    try
+      fi.hash := MD5File(fi.diskName);
+    except
+      fi.tag := -1;
+    end;
+  end;
+  //e_LogWritefln('addext: res=[%s]; uname=[%s]; diskName=[%s]', [res, fi.userName, fi.diskName]);
+  SetLength(gExternalResources, length(gExternalResources)+1);
+  gExternalResources[High(gExternalResources)] := fi;
+end;
+
 
-  textures := map['texture'];
-  if (textures <> nil) then
+procedure compactExtResList ();
+var
+  src, dest: Integer;
+begin
+  src := 0;
+  dest := 0;
+  for src := 0 to High(gExternalResources) do
   begin
-    for trec in textures do
+    if (gExternalResources[src].tag = 0) then
     begin
-      addResToExternalResList(resFile);
+      // copy it
+      if (dest <> src) then gExternalResources[dest] := gExternalResources[src];
+      Inc(dest);
     end;
   end;
+  if (dest <> length(gExternalResources)) then SetLength(gExternalResources, dest);
+end;
 
-  textures := nil;
-  *)
-
-  //mapHeader := GetMapHeader(map);
 
+procedure generateExternalResourcesList (map: TDynRecord);
+begin
+  SetLength(gExternalResources, 0);
   addResToExternalResList(map.MusicName);
   addResToExternalResList(map.SkyName);
 end;
@@ -1675,7 +1705,7 @@ begin
     if (gCurrentMap = nil) then
     begin
       FileName := g_ExtractWadName(Res);
-      e_WriteLog('Loading map WAD: '+FileName, TMsgType.Notify);
+      e_LogWritefln('Loading map WAD [%s] (res=[%s])', [FileName, Res], TMsgType.Notify);
       g_Game_SetLoadingText(_lc[I_LOAD_WAD_FILE], 0, False);
 
       WAD := TWADFile.Create();
@@ -1835,7 +1865,14 @@ begin
               ntn := CreateTexture(rec.Resource, FileName, True);
               if (ntn < 0) then g_SimpleError(Format(_lc[I_GAME_ERROR_TEXTURE_SIMPLE], [rec.Resource]));
             end;
-            if (ntn < 0) then ntn := CreateNullTexture(rec.Resource);
+            if (ntn < 0) then
+            begin
+              ntn := CreateNullTexture(rec.Resource);
+            end
+            else
+            begin
+              addResToExternalResList(rec.Resource);
+            end;
 
             rec.tagInt := ntn; // remember texture number
           end;
@@ -2260,7 +2297,7 @@ begin
   finally
     sfsGCEnable(); // enable releasing unused volumes
     //mapReader.Free();
-    e_ClearInputBuffer(); // why not?
+    e_UnpressAllKeys; // why not?
     if not mapOk then
     begin
       gCurrentMap.Free();
@@ -2269,6 +2306,7 @@ begin
     end;
   end;
 
+  compactExtResList();
   e_WriteLog('Done loading map.', TMsgType.Notify);
   Result := True;
 end;
@@ -2514,6 +2552,7 @@ var
   a, d, j: Integer;
   m: Word;
   s: String;
+  b: Byte;
 
   procedure UpdatePanelArray(var panels: TPanelArray);
   var
@@ -2564,6 +2603,15 @@ begin
               s := _lc[I_PLAYER_FLAG_BLUE];
             g_Game_Message(Format(_lc[I_MESSAGE_FLAG_RETURN], [AnsiUpperCase(s)]), 144);
 
+            if (((gPlayer1 <> nil) and (((gPlayer1.Team = TEAM_RED) and (a = FLAG_RED)) or ((gPlayer1.Team = TEAM_BLUE) and (a = FLAG_BLUE))))
+            or ((gPlayer2 <> nil) and (((gPlayer2.Team = TEAM_RED) and (a = FLAG_RED)) or ((gPlayer2.Team = TEAM_BLUE) and (a = FLAG_BLUE))))) then
+              b := 0
+            else
+              b := 1;
+
+            if not sound_ret_flag[b].IsPlaying() then
+              sound_ret_flag[b].Play();
+
             if g_Game_IsNet then
               MH_SEND_FlagEvent(FLAG_STATE_RETURNED, a, 0);
             Continue;