DEADSOFTWARE

game: disable corpses for server
[d2df-sdl.git] / src / game / g_saveload.pas
index dec46f1ec720c21b68354583873296986d5f161a..14539ddd88f6ef4ba2dedcb505d08a6a39f0fc5c 100644 (file)
@@ -1,9 +1,8 @@
-(* Copyright (C)  DooM 2D:Forever Developers
+(* Copyright (C)  Doom 2D: Forever Developers
  *
  * 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
@@ -19,8 +18,7 @@ unit g_saveload;
 interface
 
 uses
-  SysUtils, Classes,
-  e_graphics, g_phys, g_textures;
+  SysUtils, Classes, g_phys, g_textures;
 
 
 function g_GetSaveName (n: Integer; out valid: Boolean): AnsiString;
@@ -38,11 +36,17 @@ procedure Obj_LoadState (o: PObj; st: TStream);
 implementation
 
 uses
+  {$IFDEF ENABLE_GIBS}
+    g_gibs,
+  {$ENDIF}
+  {$IFDEF ENABLE_CORPSES}
+    g_corpses,
+  {$ENDIF}
   MAPDEF, utils, xstreams,
   g_game, g_items, g_map, g_monsters, g_triggers,
-  g_basic, g_main, Math, wadreader,
+  g_basic, Math, wadreader,
   g_weapons, g_player, g_console,
-  e_log, g_language;
+  e_log, e_res, g_language, g_options;
 
 const
   SAVE_SIGNATURE = $56534644; // 'DFSV'
@@ -102,9 +106,7 @@ end;
 
 function buildSaveName (n: Integer): AnsiString;
 begin
-  result := '';
-  if (n < 0) or (n > 65535) then exit;
-  result := formatstrf('%sSAVGAME%s.DAT', [DataDir, n]);
+  result := 'SAVGAME' + IntToStr(n) + '.DAT'
 end;
 
 
@@ -113,21 +115,33 @@ var
   st: TStream = nil;
   ver: Byte;
   stlen: Word;
+  filename: AnsiString;
 begin
   valid := false;
   result := '';
   if (n < 0) or (n > 65535) then exit;
   try
     // Îòêðûâàåì ôàéë ñîõðàíåíèé
-    st := openDiskFileRO(buildSaveName(n));
+    filename := buildSaveName(n);
+    st := e_OpenResourceRO(SaveDirs, filename);
     try
-      if not utils.checkSign(st, 'DFSV') then raise XStreamError.Create('invalid save game signature');
+      if not utils.checkSign(st, 'DFSV') then
+      begin
+        e_LogWritefln('GetSaveName: not a save file: ''%s''', [st], TMsgType.Warning);
+        //raise XStreamError.Create('invalid save game signature');
+        exit;
+      end;
       ver := utils.readByte(st);
       if (ver < 7) then
       begin
         utils.readLongWord(st); // section size
         stlen := utils.readWord(st);
-        if (stlen < 1) or (stlen > 64) then raise XStreamError.Create('invalid save game version');
+        if (stlen < 1) or (stlen > 64) then
+        begin
+          e_LogWritefln('GetSaveName: not a save file: ''%s''', [st], TMsgType.Warning);
+          //raise XStreamError.Create('invalid save game version');
+          exit;
+        end;
         // Èìÿ ñýéâà
         SetLength(result, stlen);
         st.ReadBuffer(result[1], stlen);
@@ -144,15 +158,78 @@ begin
       st.Free();
     end;
   except
-    on e: Exception do
     begin
-      e_WriteLog('GetSaveName Error: '+e.message, MSG_WARNING);
-      {$IF DEFINED(D2F_DEBUG)}e_WriteStackTrace(e.message);{$ENDIF}
+      //e_WriteLog('GetSaveName Error: '+e.message, MSG_WARNING);
+      //{$IF DEFINED(D2F_DEBUG)}e_WriteStackTrace(e.message);{$ENDIF}
       result := '';
     end;
   end;
 end;
 
+procedure g_Player_Corpses_SaveState (st: TStream);
+  {$IFDEF ENABLE_CORPSES}
+    var i: Integer;
+  {$ENDIF}
+  var count: Integer;
+begin
+  count := 0;
+  {$IFDEF ENABLE_CORPSES}
+    for i := 0 to High(gCorpses) do
+      if (gCorpses[i] <> nil) then
+        Inc(count);
+  {$ENDIF}
+  utils.writeInt(st, LongInt(count));
+  {$IFDEF ENABLE_CORPSES}
+    if count > 0 then
+    begin
+      for i := 0 to High(gCorpses) do
+      begin
+        if gCorpses[i] <> nil then
+        begin
+          utils.writeStr(st, gCorpses[i].Model.GetName());
+          utils.writeBool(st, gCorpses[i].Mess);
+          gCorpses[i].SaveState(st);
+        end;
+      end;
+    end;
+  {$ENDIF}
+end;
+
+procedure g_Player_Corpses_LoadState (st: TStream);
+  {$IFDEF ENABLE_CORPSES}
+    var str: String; b: Boolean; i: Integer;
+  {$ENDIF}
+  var count: Integer;
+begin
+  assert(st <> nil);
+
+  {$IFDEF ENABLE_GIBS}
+    g_Gibs_RemoveAll;
+  {$ENDIF}
+  {$IFDEF ENALBE_SHELLS}
+    g_Shells_RemoveAll; // ???
+  {$ENDIF}
+  {$IFDEF ENABLE_CORPSES}
+    g_Corpses_RemoveAll;
+  {$ENDIF}
+
+  count := utils.readLongInt(st);
+
+  {$IFDEF ENABLE_CORPSES}
+    if (count < 0) or (count > Length(gCorpses)) then
+      raise XStreamError.Create('invalid number of corpses');
+    for i := 0 to count - 1 do
+    begin
+      str := utils.readStr(st);
+      b := utils.readBool(st);
+      gCorpses[i] := TCorpse.Create(0, 0, str, b);
+      gCorpses[i].LoadState(st);
+    end;
+  {$ELSE}
+    if count <> 0 then
+      raise XStreamError.Create('corpses not supported in this version');
+  {$ENDIF}
+end;
 
 function g_SaveGameTo (const filename: AnsiString; const aname: AnsiString; deleteOnError: Boolean=true): Boolean;
 var
@@ -162,7 +239,7 @@ var
 begin
   result := false;
   try
-    st := createDiskFile(filename);
+    st := e_CreateResource(SaveDirs, filename);
     try
       utils.writeSign(st, 'DFSV');
       utils.writeInt(st, Byte(SAVE_VERSION));
@@ -172,7 +249,7 @@ begin
       //if (Length(gCurrentMapFileName) <> 0) then e_LogWritefln('SAVE: current map is ''%s''...', [gCurrentMapFileName]);
       utils.writeStr(st, gCurrentMapFileName);
       // Ïóòü ê êàðòå
-      utils.writeStr(st, gGameSettings.WAD);
+      utils.writeStr(st, ExtractFileName(gGameSettings.WAD));
       // Èìÿ êàðòû
       utils.writeStr(st, g_ExtractFileName(gMapInfo.Map));
       // Êîëè÷åñòâî èãðîêîâ
@@ -267,9 +344,10 @@ begin
       begin
         st.Free();
         g_Console_Add(_lc[I_GAME_ERROR_SAVE]);
-        e_WriteLog('SaveState Error: '+e.message, MSG_WARNING);
+        e_WriteLog('SaveState Error: '+e.message, TMsgType.Warning);
         if deleteOnError then DeleteFile(filename);
         {$IF DEFINED(D2F_DEBUG)}e_WriteStackTrace(e.message);{$ENDIF}
+e_WriteStackTrace(e.message);
         result := false;
       end;
   end;
@@ -301,12 +379,12 @@ begin
   result := false;
 
   try
-    st := openDiskFileRO(filename);
+    st := e_OpenResourceRO(SaveDirs, filename);
     try
       if not utils.checkSign(st, 'DFSV') then raise XStreamError.Create('invalid save game signature');
       if (utils.readByte(st) <> SAVE_VERSION) then raise XStreamError.Create('invalid save game version');
 
-      e_WriteLog('Loading saved game...', MSG_NOTIFY);
+      e_WriteLog('Loading saved game...', TMsgType.Notify);
 
       {$IF DEFINED(D2F_DEBUG)}try{$ENDIF}
         //g_Game_Free(false); // don't free textures for the same map
@@ -390,11 +468,9 @@ begin
         end;
         g_Game_ExecuteEvent('ongamestart');
 
-        // Óñòàíîâêà ðàçìåðîâ îêîí èãðîêîâ
-        g_Game_SetupScreenSize();
-
         // Çàãðóçêà è çàïóñê êàðòû
-        if not g_Game_StartMap(WAD_Path+':\'+Map_Name, True, curmapfile) then
+        //FIXME: save/load `asMegawad`
+        if not g_Game_StartMap(false{asMegawad}, WAD_Path+':\'+Map_Name, True, curmapfile) then
         begin
           g_FatalError(Format(_lc[I_GAME_ERROR_MAP_LOAD], [WAD_Path + ':\' + Map_Name]));
           exit;
@@ -490,14 +566,26 @@ begin
       st.Free();
     end;
   except
+    on e: EFileNotFoundException do
+      begin
+        g_Console_Add(_lc[I_GAME_ERROR_LOAD]);
+        g_Console_Add('LoadState Error: '+e.message);
+        e_WriteLog('LoadState Error: '+e.message, TMsgType.Warning);
+        gLoadGameMode := false;
+        result := false;
+      end;
     on e: Exception do
       begin
         g_Console_Add(_lc[I_GAME_ERROR_LOAD]);
-        e_WriteLog('LoadState Error: '+e.message, MSG_WARNING);
-        {$IF DEFINED(D2F_DEBUG)}e_LogWritefln('stream error position: 0x%08x', [errpos], MSG_WARNING);{$ENDIF}
+        g_Console_Add('LoadState Error: '+e.message);
+        e_WriteLog('LoadState Error: '+e.message, TMsgType.Warning);
+        {$IF DEFINED(D2F_DEBUG)}e_LogWritefln('stream error position: 0x%08x', [errpos], TMsgType.Warning);{$ENDIF}
         gLoadGameMode := false;
-        result := true;
-        if not gameCleared then g_Game_Free();
+        result := false;
+        if gState <> STATE_MENU then
+          g_FatalError(_lc[I_GAME_ERROR_LOAD])
+        else if not gameCleared then
+          g_Game_Free();
         {$IF DEFINED(D2F_DEBUG)}e_WriteStackTrace(e.message);{$ENDIF}
       end;
   end;
@@ -506,16 +594,12 @@ end;
 
 function g_SaveGame (n: Integer; const aname: AnsiString): Boolean;
 begin
-  result := false;
-  if (n < 0) or (n > 65535) then exit;
   result := g_SaveGameTo(buildSaveName(n), aname, true);
 end;
 
 
 function g_LoadGame (n: Integer): Boolean;
 begin
-  result := false;
-  if (n < 0) or (n > 65535) then exit;
   result := g_LoadGameFrom(buildSaveName(n));
 end;