Client LuaCsForBarotrauma
RoundSound.cs
1 #nullable enable
2 using Barotrauma.Sounds;
3 using Microsoft.Xna.Framework;
4 using System;
5 using System.Collections.Generic;
6 using System.Globalization;
7 
8 namespace Barotrauma
9 {
10  class RoundSound
11  {
12  public Sound? Sound;
13  public readonly float Volume;
14  public readonly float Range;
15  public readonly Vector2 FrequencyMultiplierRange;
16  public readonly bool Stream;
17  public readonly bool IgnoreMuffling;
18 
19  public readonly string? Filename;
20 
21  private RoundSound(ContentXElement element, Sound sound)
22  {
23  Filename = sound.Filename;
24  Sound = sound;
25  Stream = sound.Stream;
26  Range = element.GetAttributeFloat("range", 1000.0f);
27  Volume = element.GetAttributeFloat("volume", 1.0f);
28  IgnoreMuffling = element.GetAttributeBool("dontmuffle", false);
29 
30  FrequencyMultiplierRange = new Vector2(1.0f);
31  string freqMultAttr = element.GetAttributeString("frequencymultiplier", element.GetAttributeString("frequency", "1.0"));
32  if (!freqMultAttr.Contains(','))
33  {
34  if (float.TryParse(freqMultAttr, NumberStyles.Any, CultureInfo.InvariantCulture, out float freqMult))
35  {
36  FrequencyMultiplierRange = new Vector2(freqMult);
37  }
38  }
39  else
40  {
41  var freqMult = XMLExtensions.ParseVector2(freqMultAttr, false);
42  if (freqMult.Y >= 0.25f)
43  {
44  FrequencyMultiplierRange = freqMult;
45  }
46  }
47  if (FrequencyMultiplierRange.Y > 4.0f)
48  {
49  DebugConsole.ThrowError($"Loaded frequency range exceeds max value: {FrequencyMultiplierRange} (original string was \"{freqMultAttr}\")",
50  contentPackage: element.ContentPackage);
51  }
52  }
53 
55  {
56  return Rand.Range(FrequencyMultiplierRange.X, FrequencyMultiplierRange.Y);
57  }
58 
59  private static readonly List<RoundSound> roundSounds = new List<RoundSound>();
60  private static readonly Dictionary<string, RoundSound> roundSoundByPath = new Dictionary<string, RoundSound>();
61  public static RoundSound? Load(ContentXElement element, bool stream = false)
62  {
63  if (GameMain.SoundManager?.Disabled ?? true) { return null; }
64 
65  var filename = element.GetAttributeContentPath("file") ?? element.GetAttributeContentPath("sound");
66  if (filename is null)
67  {
68  string errorMsg = "Error when loading round sound (" + element + ") - file path not set";
69  DebugConsole.ThrowError(errorMsg,
70  contentPackage: element.ContentPackage);
71  GameAnalyticsManager.AddErrorEventOnce("RoundSound.LoadRoundSound:FilePathEmpty" + element.ToString(), GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
72  return null;
73  }
74 
75  Sound? existingSound = null;
76  if (roundSoundByPath.TryGetValue(filename.FullPath, out RoundSound? rs) && rs.Sound is { Disposed: false })
77  {
78  existingSound = rs.Sound;
79  }
80 
81  if (existingSound is null)
82  {
83  try
84  {
85  existingSound = GameMain.SoundManager.LoadSound(filename?.FullPath, stream);
86  if (existingSound == null) { return null; }
87  }
88  catch (System.IO.FileNotFoundException e)
89  {
90  string errorMsg = "Failed to load sound file \"" + filename + "\" (file not found).";
91  DebugConsole.ThrowError(errorMsg, e,
92  contentPackage: element.ContentPackage);
93  if (!ContentPackageManager.ModsEnabled)
94  {
95  GameAnalyticsManager.AddErrorEventOnce("RoundSound.LoadRoundSound:FileNotFound" + filename, GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
96  }
97  return null;
98  }
99  catch (System.IO.InvalidDataException e)
100  {
101  string errorMsg = "Failed to load sound file \"" + filename + "\" (invalid data).";
102  DebugConsole.ThrowError(errorMsg, e,
103  contentPackage: element.ContentPackage);
104  GameAnalyticsManager.AddErrorEventOnce("RoundSound.LoadRoundSound:InvalidData" + filename, GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
105  return null;
106  }
107  }
108 
109  RoundSound newSound = new RoundSound(element, existingSound);
110  if (filename is not null && !newSound.Stream)
111  {
112  roundSoundByPath.TryAdd(filename.FullPath, newSound);
113  }
114  roundSounds.Add(newSound);
115  return newSound;
116  }
117 
118  public static void Reload(RoundSound roundSound)
119  {
120  Sound? existingSound = roundSounds.Find(s => s.Filename == roundSound.Filename && s.Stream == roundSound.Stream && s.Sound is { Disposed: false })?.Sound;
121  if (existingSound == null)
122  {
123  try
124  {
125  existingSound = GameMain.SoundManager.LoadSound(roundSound.Filename, roundSound.Stream);
126  }
127  catch (System.IO.FileNotFoundException e)
128  {
129  string errorMsg = "Failed to load sound file \"" + roundSound.Filename + "\".";
130  DebugConsole.ThrowError(errorMsg, e,
131  contentPackage: roundSound.Sound?.XElement?.ContentPackage);
132  GameAnalyticsManager.AddErrorEventOnce("RoundSound.LoadRoundSound:FileNotFound" + roundSound.Filename, GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
133  return;
134  }
135  }
136  roundSound.Sound = existingSound;
137  }
138 
139  public static void RemoveAllRoundSounds()
140  {
141  foreach (var roundSound in roundSounds)
142  {
143  roundSound.Sound?.Dispose();
144  }
145  roundSounds.Clear();
146  roundSoundByPath.Clear();
147  }
148  }
149 }
string? GetAttributeString(string key, string? def)
float GetAttributeFloat(string key, float def)
ContentPackage? ContentPackage
ContentPath? GetAttributeContentPath(string key)
bool GetAttributeBool(string key, bool def)
static Sounds.SoundManager SoundManager
Definition: GameMain.cs:80
static ? RoundSound Load(ContentXElement element, bool stream=false)
Definition: RoundSound.cs:61
static void Reload(RoundSound roundSound)
Definition: RoundSound.cs:118
readonly float Range
Definition: RoundSound.cs:14
readonly Vector2 FrequencyMultiplierRange
Definition: RoundSound.cs:15
static void RemoveAllRoundSounds()
Definition: RoundSound.cs:139
readonly bool Stream
Definition: RoundSound.cs:16
float GetRandomFrequencyMultiplier()
Definition: RoundSound.cs:54
readonly float Volume
Definition: RoundSound.cs:13
readonly? string Filename
Definition: RoundSound.cs:19
readonly bool IgnoreMuffling
Definition: RoundSound.cs:17
Sound(SoundManager owner, string filename, bool stream, bool streamsReliably, ContentXElement xElement=null, bool getFullPath=true)
Definition: Sound.cs:65
readonly ContentXElement XElement
Definition: Sound.cs:21
readonly bool Stream
Definition: Sound.cs:23
readonly string Filename
Definition: Sound.cs:19
Sound LoadSound(string filename, bool stream=false)