public static void Save(bool message, bool permitBackgroundWrite) { if (Saving) { return; } ++m_Saves; NetState.FlushAll(); NetState.Pause(); WaitForWriteCompletion(); //Blocks Save until current disk flush is done. Saving = true; m_DiskWriteHandle.Reset(); if (message) { Broadcast(0x35, false, AccessLevel.Player, "The world is saving, please wait."); } SaveStrategy strategy = SaveStrategy.Acquire(); Console.WriteLine("Core: Using {0} save strategy", strategy.Name.ToLowerInvariant()); Console.WriteLine("World: Saving..."); Stopwatch watch = Stopwatch.StartNew(); if (!Directory.Exists("Saves/Mobiles/")) { Directory.CreateDirectory("Saves/Mobiles/"); } if (!Directory.Exists("Saves/Items/")) { Directory.CreateDirectory("Saves/Items/"); } if (!Directory.Exists("Saves/Guilds/")) { Directory.CreateDirectory("Saves/Guilds/"); } try { EventSink.InvokeBeforeWorldSave(new BeforeWorldSaveEventArgs()); } catch (Exception e) { throw new Exception("FATAL: Exception in EventSink.BeforeWorldSave", e); } if (m_Metrics) { using (SaveMetrics metrics = new SaveMetrics()) strategy.Save(metrics, permitBackgroundWrite); } else { strategy.Save(null, permitBackgroundWrite); } try { EventSink.InvokeWorldSave(new WorldSaveEventArgs(message)); } catch (Exception e) { throw new Exception("FATAL: Exception in EventSink.WorldSave", e); } watch.Stop(); Saving = false; if (!permitBackgroundWrite) { NotifyDiskWriteComplete(); //Sets the DiskWriteHandle. If we allow background writes, we leave this upto the individual save strategies. } ProcessSafetyQueues(); strategy.ProcessDecay(); Console.WriteLine("Save finished in {0:F2} seconds.", watch.Elapsed.TotalSeconds); if (message) { Broadcast(0x35, false, AccessLevel.Player, "World save done in {0:F1} seconds.", watch.Elapsed.TotalSeconds); } NetState.Resume(); try { EventSink.InvokeAfterWorldSave(new AfterWorldSaveEventArgs()); } catch (Exception e) { throw new Exception("FATAL: Exception in EventSink.AfterWorldSave", e); } }