/// <summary> /// Saves the game to disk in the background. /// </summary> /// <param name="data">The uncompressed save data.</param> private void DoSave(BackgroundSaveData data) { byte[] buffer; try { var stream = data.Stream; long len = stream.Length; // Uh oh if (len >= int.MaxValue) { PUtil.LogError("Save file is too big, game will not save correctly!"); } else { PUtil.LogDebug("Background save to: " + data.FileName); } if (data.Compress) { buffer = SaveLoader.CompressContents(stream.GetBuffer(), (int)len); } else { buffer = stream.ToArray(); } CleanAutosaves(data.FileName); // Write the file header using (var writer = new BinaryWriter(File.Open(data.FileName, FileMode.Create))) { var saveHeader = SaveGame.Instance.GetSaveHeader(true, data.Compress, out SaveGame.Header header); writer.Write(header.buildVersion); writer.Write(header.headerSize); writer.Write(header.headerVersion); writer.Write(header.compression); writer.Write(saveHeader); KSerialization.Manager.SerializeDirectory(writer); writer.Write(buffer); writer.Flush(); } buffer = null; status = SaveStatus.Done; PUtil.LogDebug("Background save complete"); } catch (IOException e) { // Autosave error! PUtil.LogExcWarn(e); status = SaveStatus.IOError; } catch (Exception e) { // Allowing it to continue here will crash with a simdll error PUtil.LogException(e); status = SaveStatus.Failed; } finally { try { // Cannot throw during a finally, or it will discard the original exception data.Dispose(); } catch (Exception e) { PUtil.LogException(e); } } }
/// <summary> /// Saves the game to disk in the background. /// </summary> /// <param name="data">The uncompressed save data.</param> private void DoSave(BackgroundSaveData data) { try { var stream = data.Stream; PUtil.LogDebug("Background save to: " + data.FileName); stream.Seek(0L, SeekOrigin.Begin); CleanAutosaves(); // Write the file header using (var writer = new BinaryWriter(File.Open(data.FileName, FileMode. Create))) { var saveHeader = SaveGame.Instance.GetSaveHeader(true, data.Compress, out SaveGame.Header header); writer.Write(header.buildVersion); writer.Write(header.headerSize); writer.Write(header.headerVersion); writer.Write(header.compression); writer.Write(saveHeader); if (FastSaveOptions.Instance.DelegateSave) { FastSerializationManager.SerializeDirectory(writer); } else { KSerialization.Manager.SerializeDirectory(writer); } writer.Flush(); if (data.Compress) { COMPRESS_CONTENTS.Invoke(writer, stream.GetBuffer(), (int)stream. Length); } else { stream.CopyTo(writer.BaseStream); } } stream.Dispose(); status = SaveStatus.Done; PUtil.LogDebug("Background save complete"); } catch (IOException e) { // Autosave error! PUtil.LogExcWarn(e); status = SaveStatus.IOError; } catch (Exception e) { // Allowing it to continue here will crash with a simdll error PUtil.LogException(e); status = SaveStatus.Failed; } finally { try { // Cannot throw during a finally, or it will discard the original exception data.Dispose(); } catch { } } }
/// <summary> /// Saves the game to disk in the background. /// </summary> /// <param name="data">The uncompressed save data.</param> private void DoSave(BackgroundSaveData data) { try { var stream = data.Stream; PUtil.LogDebug("Background save to: " + data.FileName); stream.Seek(0L, SeekOrigin.Begin); CleanAutosaves(data.FileName); // Write the file header using (var writer = new BinaryWriter(File.Open(data.FileName, FileMode. Create))) { var saveHeader = SaveGame.Instance.GetSaveHeader(true, data.Compress, out SaveGame.Header header); writer.Write(header.buildVersion); writer.Write(header.headerSize); writer.Write(header.headerVersion); writer.Write(header.compression); writer.Write(saveHeader); KSerialization.Manager.SerializeDirectory(writer); writer.Flush(); if (data.Compress) { // SaveLoader.CompressContents is now private using (var compressor = new ZlibStream(writer.BaseStream, CompressionMode.Compress, CompressionLevel.BestSpeed)) { stream.CopyTo(compressor); compressor.Flush(); } } else { stream.CopyTo(writer.BaseStream); } } status = SaveStatus.Done; PUtil.LogDebug("Background save complete"); } catch (IOException e) { // Autosave error! PUtil.LogExcWarn(e); status = SaveStatus.IOError; } catch (Exception e) { // Allowing it to continue here will crash with a simdll error PUtil.LogException(e); status = SaveStatus.Failed; } finally { try { // Cannot throw during a finally, or it will discard the original exception data.Dispose(); } catch (Exception e) { PUtil.LogException(e); } } }
/// <summary> /// Starts saving the game in the background. /// </summary> /// <param name="data">The uncompressed save data.</param> private void StartSave(BackgroundSaveData data) { // Wait until current save is complete (best effort) while (true) { lock (startLock) { if (status != SaveStatus.InProgress) { #if DEBUG PUtil.LogDebug("Switching save to background task"); #endif var task = new Thread(() => DoSave(data)); status = SaveStatus.InProgress; Util.ApplyInvariantCultureToThread(task); task.Priority = System.Threading.ThreadPriority.BelowNormal; task.Name = "Background Autosave"; Thread.MemoryBarrier(); task.Start(); break; } } } }