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))
77  {
78  if (rs.Sound is { Disposed: false })
79  {
80  existingSound = rs.Sound;
81  }
82  else
83  {
84  roundSoundByPath.Remove(filename.FullPath);
85  }
86  }
87 
88  if (existingSound is null)
89  {
90  try
91  {
92  existingSound = GameMain.SoundManager.LoadSound(filename?.FullPath, stream);
93  if (existingSound == null) { return null; }
94  }
95  catch (System.IO.FileNotFoundException e)
96  {
97  string errorMsg = "Failed to load sound file \"" + filename + "\" (file not found).";
98  DebugConsole.ThrowError(errorMsg, e,
99  contentPackage: element.ContentPackage);
100  if (!ContentPackageManager.ModsEnabled)
101  {
102  GameAnalyticsManager.AddErrorEventOnce("RoundSound.LoadRoundSound:FileNotFound" + filename, GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
103  }
104  return null;
105  }
106  catch (System.IO.InvalidDataException e)
107  {
108  string errorMsg = "Failed to load sound file \"" + filename + "\" (invalid data).";
109  DebugConsole.ThrowError(errorMsg, e,
110  contentPackage: element.ContentPackage);
111  GameAnalyticsManager.AddErrorEventOnce("RoundSound.LoadRoundSound:InvalidData" + filename, GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
112  return null;
113  }
114  }
115 
116  RoundSound newSound = new RoundSound(element, existingSound);
117  if (filename is not null && !newSound.Stream)
118  {
119  roundSoundByPath.TryAdd(filename.FullPath, newSound);
120  }
121  roundSounds.Add(newSound);
122  return newSound;
123  }
124 
125  public static void Reload(RoundSound roundSound)
126  {
127  Sound? existingSound = roundSounds.Find(s => s.Filename == roundSound.Filename && s.Stream == roundSound.Stream && s.Sound is { Disposed: false })?.Sound;
128  if (existingSound == null)
129  {
130  try
131  {
132  existingSound = GameMain.SoundManager.LoadSound(roundSound.Filename, roundSound.Stream);
133  }
134  catch (System.IO.FileNotFoundException e)
135  {
136  string errorMsg = "Failed to load sound file \"" + roundSound.Filename + "\".";
137  DebugConsole.ThrowError(errorMsg, e,
138  contentPackage: roundSound.Sound?.XElement?.ContentPackage);
139  GameAnalyticsManager.AddErrorEventOnce("RoundSound.LoadRoundSound:FileNotFound" + roundSound.Filename, GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
140  return;
141  }
142  }
143  roundSound.Sound = existingSound;
144  }
145 
146  public static void RemoveAllRoundSounds()
147  {
148  foreach (var roundSound in roundSounds)
149  {
150  roundSound.Sound?.Dispose();
151  }
152  roundSounds.Clear();
153  roundSoundByPath.Clear();
154  }
155  }
156 }
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:125
readonly float Range
Definition: RoundSound.cs:14
readonly Vector2 FrequencyMultiplierRange
Definition: RoundSound.cs:15
static void RemoveAllRoundSounds()
Definition: RoundSound.cs:146
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)