anchor.diff:          ForceDirectories(path);
       end, 'Prepare save dir');
     end;
  +end;
  +
  +
  +//Saves the game in all its glory
  +procedure TKMGame.SaveGameToFile(const aPathName: String; aSaveByPlayer: Boolean; aSaveWorkerThread: TKMWorkerThread;
  +                                 aTimestamp: TDateTime; const aMPLocalDataPathName: String = '');
  +var
  +  mainStream, headerStream, bodyStream, saveStreamTxt: TKMemoryStream;
  +  gameMPLocalData: TKMGameMPLocalData;
  +begin
  +  if BLOCK_SAVE then Exit; // This must be here because of paraller Runner
  +
  +  // We have to wait until basesave is made before first game save
  +  fBaseSaveWorkerThreadHolder.Worker.WaitForAllWorkToComplete;
  +
  +  gLog.AddTime(Format('Saving game at tick %d to ''%s''', [fParams.Tick, aPathName]));
  +
  +  Assert(not fParams.IsMapEditor and (ALLOW_SAVE_IN_REPLAY or not fParams.IsReplay), 'Saving from wrong state');
  +
  +  PrepareSaveFolder(aPathName, aSaveByPlayer, aSaveWorkerThread);
  +
  +  mainStream    := TKMemoryStreamBinary.Create(False); // Not compressed
  +  headerStream  := TKMemoryStreamBinary.Create(False); // Not compressed
  +  bodyStream    := TKMemoryStreamBinary.Create(True);  // Compressed
  +
  +  SaveGameToStream(aTimestamp, headerStream, bodyStream);
   
     //In MP each player has his own perspective, hence we dont save minimaps in the main save file to avoid cheating,
     //but save minimap in separate file with local game data
  
positive.code: end;
  
  
  //Saves the game in all its glory
  procedure TKMGame.SaveGameToFile(const aPathName: String; aSaveByPlayer: Boolean; aSaveWorkerThread: TKMWorkerThread;
                                   aTimestamp: TDateTime; const aMPLocalDataPathName: String = '');
  var
    mainStream, headerStream, bodyStream, saveStreamTxt: TKMemoryStream;
    gameMPLocalData: TKMGameMPLocalData;
  begin
    if BLOCK_SAVE then Exit; // This must be here because of paraller Runner
  
    gLog.AddTime(Format('Saving game at tick %d to ''%s''', [fParams.Tick, aPathName]));
  
    Assert(not fParams.IsMapEditor and (ALLOW_SAVE_IN_REPLAY or not fParams.IsReplay), 'Saving from wrong state');
  
    saveStreamTxt := nil;
    if DoSaveGameAsText then
      saveStreamTxt := TKMemoryStreamText.Create;
  
    mainStream := TKMemoryStreamBinary.Create(False); // Not compressed
    headerStream := TKMemoryStreamBinary.Create(False); // Not compressed
    bodyStream := TKMemoryStreamBinary.Create(True);    // Compressed
  
    SaveGameToStream(aTimestamp, headerStream, bodyStream);
  
    //Makes the folders in case they were deleted.
    //Should do before save Minimap file for MP game
    if (aPathName <> '') then
    begin
      // We can make directories in async too, since all save parts are made in async now
      aSaveWorkerThread.QueueWork(procedure
      var
        path: string;
      begin
        path := ExtractFilePath(aPathName);
        if DirectoryExists(path) then
        begin
          // Delete save folder content, since we want to overwrite old saves
  
negative.code:     function DoRenderGame: Boolean;
  
      procedure MultiplayerRig(aNewGame: Boolean);
  
      procedure PrepareSaveFolder(const aPathName: String; aSaveByPlayer: Boolean; aSaveWorkerThread: TKMWorkerThread);
      procedure SaveGameToStream(aTimestamp: TDateTime; aSaveStream: TKMemoryStream); overload;
      procedure SaveGameToStream(aTimestamp: TDateTime; aHeaderStream, aBodyStream: TKMemoryStream); overload;
      procedure SaveGameToFile(const aPathName: String; aSaveByPlayer: Boolean; aSaveWorkerThread: TKMWorkerThread; aTimestamp: TDateTime; const aMPLocalDataPathName: String = '');
  