Client LuaCsForBarotrauma
CreatureMetrics.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Xml.Linq;
4 using System.Linq;
5 using Barotrauma.IO;
6 using XmlWriterSettings = System.Xml.XmlWriterSettings;
7 #nullable enable
8 
9 namespace Barotrauma
10 {
11  public static class CreatureMetrics
12  {
13  private const string path = "creature_metrics.xml";
14 
18  public static HashSet<Identifier> RecentlyEncountered { get; private set; } = new HashSet<Identifier>();
19  public static HashSet<Identifier> Encountered { get; private set; } = new HashSet<Identifier>();
20  public static HashSet<Identifier> Unlocked { get; private set; } = new HashSet<Identifier>();
21  public static HashSet<Identifier> Killed { get; private set; } = new HashSet<Identifier>();
22  public static bool IsInitialized { get; private set; }
23  public static bool UnlockAll { get; set; }
24 
25  public static void Init()
26  {
27  IsInitialized = true;
28  if (File.Exists(path))
29  {
30  Load();
31  }
32  Save();
33  }
34 
35  private static void Load()
36  {
37  XDocument doc = XMLExtensions.TryLoadXml(path);
38  XElement? root = doc?.Root;
39  if (root == null)
40  {
41  DebugConsole.AddWarning($"Failed to load creature metrics from {path}!");
42  return;
43  }
44  UnlockAll = root.GetAttributeBool(nameof(UnlockAll), UnlockAll);
45  Unlocked = new HashSet<Identifier>(root.GetAttributeIdentifierArray(nameof(Unlocked), Array.Empty<Identifier>()));
46  Encountered = new HashSet<Identifier>(root.GetAttributeIdentifierArray(nameof(Encountered), Array.Empty<Identifier>()));
47  Killed = new HashSet<Identifier>(root.GetAttributeIdentifierArray(nameof(Killed), Array.Empty<Identifier>()));
48  SyncSets();
49  }
50 
51  public static void Save()
52  {
53  if (!IsInitialized)
54  {
55  throw new Exception("Creature Metrics not yet initialized!");
56  }
57  SyncSets();
58  XDocument configDoc = new XDocument();
59  XElement root = new XElement("CreatureMetrics");
60  configDoc.Add(root);
61  root.SetAttributeValue(nameof(UnlockAll), UnlockAll);
62  root.SetAttributeValue(nameof(Unlocked), string.Join(",", Unlocked).Trim().ToLowerInvariant());
63  root.SetAttributeValue(nameof(Encountered), string.Join(",", Encountered).Trim().ToLowerInvariant());
64  root.SetAttributeValue(nameof(Killed), string.Join(",", Killed).Trim().ToLowerInvariant());
65  configDoc.SaveSafe(path);
66  XmlWriterSettings settings = new XmlWriterSettings
67  {
68  Indent = true,
69  OmitXmlDeclaration = true,
70  NewLineOnAttributes = true
71  };
72  try
73  {
74  using var writer = XmlWriter.Create(path, settings);
75  configDoc.WriteTo(writer);
76  writer.Flush();
77  }
78  catch (Exception e)
79  {
80  DebugConsole.ThrowError("Saving creature metrics failed.", e);
81  GameAnalyticsManager.AddErrorEventOnce("CreatureMetrics.Save:SaveFailed", GameAnalyticsManager.ErrorSeverity.Error,
82  "Saving creature metrics failed.\n" + e.Message + "\n" + e.StackTrace.CleanupStackTrace());
83  }
84  }
85 
86  public static void RecordKill(Identifier species)
87  {
88  AddEncounter(species);
89  if (!Killed.Contains(species))
90  {
91  Killed.Add(species);
92  }
93  }
94 
95  public static void AddEncounter(Identifier species)
96  {
97  if (species == CharacterPrefab.HumanSpeciesName) { return; }
98  if (Encountered.Contains(species)) { return; }
99  Encountered.Add(species);
100  RecentlyEncountered.Add(species);
101  UnlockInEditor(species);
102  }
103 
104  private static IEnumerable<CharacterFile>? vanillaCharacters;
105  public static void UnlockInEditor(Identifier species)
106  {
107  if (species == CharacterPrefab.HumanSpeciesName) { return; }
108  if (Unlocked.Contains(species)) { return; }
109  vanillaCharacters ??= GameMain.VanillaContent.GetFiles<CharacterFile>();
110  var contentFile = CharacterPrefab.FindBySpeciesName(species);
111  if (contentFile == null) { return; }
112  if (!vanillaCharacters.Contains(contentFile.ContentFile))
113  {
114  // Don't try to unlock custom characters. They are always unlocked.
115  return;
116  }
117  Unlocked.Add(species);
118  }
119 
120  private static void SyncSets()
121  {
122  // Ensure that all killed are also encountered and both unlocked.
123  // Otherwise we could permanently hide some creatures by manually adding them to the encountered or by removing from unlocked in the xml file.
124  foreach (var species in Killed)
125  {
126  Encountered.Add(species);
127  }
128  foreach (var species in Encountered)
129  {
130  Unlocked.Add(species);
131  }
132  }
133  }
134 }
static XmlWriter Create(string path, System.Xml.XmlWriterSettings settings)
Definition: SafeIO.cs:163