Reapply "OBT1.1.0 Merge branch 'dev_pte' into dev"
This reverts commit 046483b9da.
This commit is contained in:
@@ -2143,7 +2143,7 @@ namespace Barotrauma
|
||||
if (existingAffliction == null)
|
||||
{
|
||||
existingAffliction = afflictionPrefab.Instantiate(strength);
|
||||
afflictions.Add(existingAffliction, limb);
|
||||
afflictions.TryAdd(existingAffliction, limb);
|
||||
newAdded = true;
|
||||
}
|
||||
existingAffliction.SetStrength(strength);
|
||||
|
||||
@@ -867,7 +867,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (var stackedItem in item.GetStackedItems())
|
||||
{
|
||||
Item.DeconstructItems.Add(stackedItem);
|
||||
Item.MarkForDeconstruction(stackedItem);
|
||||
}
|
||||
HintManager.OnItemMarkedForDeconstruction(order.OrderGiver);
|
||||
}
|
||||
@@ -875,7 +875,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (var stackedItem in item.GetStackedItems())
|
||||
{
|
||||
Item.DeconstructItems.Remove(stackedItem);
|
||||
Item.UnmarkForDeconstruction(stackedItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1892,7 +1892,7 @@ namespace Barotrauma
|
||||
|
||||
}
|
||||
}
|
||||
else if (Item.DeconstructItems.Contains(item) &&
|
||||
else if (Item.IsMarkedForDeconstruction(item) &&
|
||||
OrderPrefab.Prefabs.TryGet(Tags.DeconstructThis, out OrderPrefab deconstructOrder))
|
||||
{
|
||||
DrawSideIcon(deconstructOrder.SymbolSprite, Direction.Right, TextManager.Get("tooltip.markedfordeconstruction"), GUIStyle.Red, out bool mouseOn);
|
||||
|
||||
@@ -471,11 +471,11 @@ namespace Barotrauma
|
||||
|
||||
if (item0 == null && item1 != null)
|
||||
{
|
||||
item0 = Item.ItemList.Find(it => it.GetComponent<ConnectionPanel>()?.DisconnectedWires.Contains(wire) ?? false);
|
||||
item0 = Item.ItemList.FirstOrDefault(it => it.GetComponent<ConnectionPanel>()?.DisconnectedWires.Contains(wire) ?? false);
|
||||
}
|
||||
else if (item0 != null && item1 == null)
|
||||
{
|
||||
item1 = Item.ItemList.Find(it => it.GetComponent<ConnectionPanel>()?.DisconnectedWires.Contains(wire) ?? false);
|
||||
item1 = Item.ItemList.FirstOrDefault(it => it.GetComponent<ConnectionPanel>()?.DisconnectedWires.Contains(wire) ?? false);
|
||||
}
|
||||
if (item0 != null && item1 != null && SelectedList.Contains(item0) && SelectedList.Contains(item1))
|
||||
{
|
||||
|
||||
@@ -503,86 +503,102 @@ namespace Barotrauma.Sounds
|
||||
mutex = new object();
|
||||
}
|
||||
|
||||
// Use the playingChannels lock to protect both channel assignment AND OpenAL operations.
|
||||
// This prevents race conditions when multiple threads try to play sounds simultaneously
|
||||
// (e.g., during Parallel.ForEach in MapEntity.UpdateAll).
|
||||
int poolIndex = (int)sound.SourcePoolIndex;
|
||||
object channelsLock = sound.Owner.GetPlayingChannelsLock(sound.SourcePoolIndex);
|
||||
|
||||
#if !DEBUG
|
||||
try
|
||||
{
|
||||
#endif
|
||||
if (mutex != null) { Monitor.Enter(mutex); }
|
||||
if (sound.Owner.CountPlayingInstances(sound) < sound.MaxSimultaneousInstances)
|
||||
lock (channelsLock)
|
||||
{
|
||||
ALSourceIndex = sound.Owner.AssignFreeSourceToChannel(this);
|
||||
}
|
||||
|
||||
if (ALSourceIndex >= 0)
|
||||
{
|
||||
if (!IsStream)
|
||||
if (mutex != null) { Monitor.Enter(mutex); }
|
||||
try
|
||||
{
|
||||
Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Buffer, 0);
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
if (sound.Owner.CountPlayingInstancesUnsafe(sound, poolIndex) < sound.MaxSimultaneousInstances)
|
||||
{
|
||||
throw new Exception("Failed to reset source buffer: " + debugName + ", " + Al.GetErrorString(alError));
|
||||
ALSourceIndex = sound.Owner.AssignFreeSourceToChannelUnsafe(this, poolIndex);
|
||||
}
|
||||
|
||||
Sound.FillAlBuffers();
|
||||
if (Sound.Buffers is not { AlBuffer: not 0, AlMuffledBuffer: not 0 }) { return; }
|
||||
|
||||
uint alBuffer = sound.Owner.GetCategoryMuffle(category) || muffled ? Sound.Buffers.AlMuffledBuffer : Sound.Buffers.AlBuffer;
|
||||
Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Buffer, (int)alBuffer);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
if (ALSourceIndex >= 0)
|
||||
{
|
||||
throw new Exception("Failed to bind buffer to source (" + ALSourceIndex.ToString() + ":" + sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex) + "," + alBuffer.ToString() + "): " + debugName + ", " + Al.GetErrorString(alError));
|
||||
}
|
||||
if (!IsStream)
|
||||
{
|
||||
Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Buffer, 0);
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to reset source buffer: " + debugName + ", " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
SetProperties();
|
||||
Sound.FillAlBuffers();
|
||||
if (Sound.Buffers is not { AlBuffer: not 0, AlMuffledBuffer: not 0 }) { return; }
|
||||
|
||||
Al.SourcePlay(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex));
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to play source: " + debugName + ", " + Al.GetErrorString(alError));
|
||||
uint alBuffer = sound.Owner.GetCategoryMuffle(category) || muffled ? Sound.Buffers.AlMuffledBuffer : Sound.Buffers.AlBuffer;
|
||||
Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Buffer, (int)alBuffer);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to bind buffer to source (" + ALSourceIndex.ToString() + ":" + sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex) + "," + alBuffer.ToString() + "): " + debugName + ", " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
SetProperties();
|
||||
|
||||
Al.SourcePlay(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex));
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to play source: " + debugName + ", " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint alBuffer = 0;
|
||||
Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Buffer, (int)alBuffer);
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to reset source buffer: " + debugName + ", " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Looping, Al.False);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to set stream looping state: " + debugName + ", " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
streamShortBuffer = new short[STREAM_BUFFER_SIZE];
|
||||
|
||||
streamBuffers = new uint[4];
|
||||
unqueuedBuffers = new uint[4];
|
||||
streamBufferAmplitudes = new float[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Al.GenBuffer(out streamBuffers[i]);
|
||||
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to generate stream buffers: " + debugName + ", " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
if (!Al.IsBuffer(streamBuffers[i]))
|
||||
{
|
||||
throw new Exception("Generated streamBuffer[" + i.ToString() + "] is invalid! " + debugName);
|
||||
}
|
||||
}
|
||||
Sound.Owner.InitUpdateChannelThread();
|
||||
SetProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
finally
|
||||
{
|
||||
uint alBuffer = 0;
|
||||
Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Buffer, (int)alBuffer);
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to reset source buffer: " + debugName + ", " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Looping, Al.False);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to set stream looping state: " + debugName + ", " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
streamShortBuffer = new short[STREAM_BUFFER_SIZE];
|
||||
|
||||
streamBuffers = new uint[4];
|
||||
unqueuedBuffers = new uint[4];
|
||||
streamBufferAmplitudes = new float[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Al.GenBuffer(out streamBuffers[i]);
|
||||
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to generate stream buffers: " + debugName + ", " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
if (!Al.IsBuffer(streamBuffers[i]))
|
||||
{
|
||||
throw new Exception("Generated streamBuffer[" + i.ToString() + "] is invalid! " + debugName);
|
||||
}
|
||||
}
|
||||
Sound.Owner.InitUpdateChannelThread();
|
||||
SetProperties();
|
||||
if (mutex != null) { Monitor.Exit(mutex); }
|
||||
}
|
||||
}
|
||||
#if !DEBUG
|
||||
@@ -591,12 +607,6 @@ namespace Barotrauma.Sounds
|
||||
{
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
#endif
|
||||
if (mutex != null) { Monitor.Exit(mutex); }
|
||||
#if !DEBUG
|
||||
}
|
||||
#endif
|
||||
|
||||
void SetProperties()
|
||||
|
||||
@@ -417,6 +417,15 @@ namespace Barotrauma.Sounds
|
||||
return sourcePools[(int)poolIndex].ALSources[srcInd];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the lock object for the playing channels array for a specific pool.
|
||||
/// Used to protect OpenAL operations that need to be atomic with channel assignment.
|
||||
/// </summary>
|
||||
public object GetPlayingChannelsLock(SourcePoolIndex poolIndex)
|
||||
{
|
||||
return playingChannels[(int)poolIndex];
|
||||
}
|
||||
|
||||
public int AssignFreeSourceToChannel(SoundChannel newChannel)
|
||||
{
|
||||
if (Disabled) { return -1; }
|
||||
@@ -427,14 +436,25 @@ namespace Barotrauma.Sounds
|
||||
|
||||
lock (playingChannels[poolIndex])
|
||||
{
|
||||
for (int i = 0; i < playingChannels[poolIndex].Length; i++)
|
||||
return AssignFreeSourceToChannelUnsafe(newChannel, poolIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a free source to a channel without locking.
|
||||
/// Caller MUST hold the playingChannels[poolIndex] lock before calling this method.
|
||||
/// </summary>
|
||||
public int AssignFreeSourceToChannelUnsafe(SoundChannel newChannel, int poolIndex)
|
||||
{
|
||||
if (Disabled) { return -1; }
|
||||
|
||||
for (int i = 0; i < playingChannels[poolIndex].Length; i++)
|
||||
{
|
||||
if (playingChannels[poolIndex][i] == null || !playingChannels[poolIndex][i].IsPlaying)
|
||||
{
|
||||
if (playingChannels[poolIndex][i] == null || !playingChannels[poolIndex][i].IsPlaying)
|
||||
{
|
||||
if (playingChannels[poolIndex][i] != null) { playingChannels[poolIndex][i].Dispose(); }
|
||||
playingChannels[poolIndex][i] = newChannel;
|
||||
return i;
|
||||
}
|
||||
if (playingChannels[poolIndex][i] != null) { playingChannels[poolIndex][i].Dispose(); }
|
||||
playingChannels[poolIndex][i] = newChannel;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -476,13 +496,25 @@ namespace Barotrauma.Sounds
|
||||
int count = 0;
|
||||
lock (playingChannels[(int)sound.SourcePoolIndex])
|
||||
{
|
||||
for (int i = 0; i < playingChannels[(int)sound.SourcePoolIndex].Length; i++)
|
||||
count = CountPlayingInstancesUnsafe(sound, (int)sound.SourcePoolIndex);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Counts playing instances without locking.
|
||||
/// Caller MUST hold the playingChannels[poolIndex] lock before calling this method.
|
||||
/// </summary>
|
||||
public int CountPlayingInstancesUnsafe(Sound sound, int poolIndex)
|
||||
{
|
||||
if (Disabled) { return 0; }
|
||||
int count = 0;
|
||||
for (int i = 0; i < playingChannels[poolIndex].Length; i++)
|
||||
{
|
||||
if (playingChannels[poolIndex][i] != null &&
|
||||
playingChannels[poolIndex][i].Sound.Filename == sound.Filename)
|
||||
{
|
||||
if (playingChannels[(int)sound.SourcePoolIndex][i] != null &&
|
||||
playingChannels[(int)sound.SourcePoolIndex][i].Sound.Filename == sound.Filename)
|
||||
{
|
||||
if (playingChannels[(int)sound.SourcePoolIndex][i].IsPlaying) { count++; };
|
||||
}
|
||||
if (playingChannels[poolIndex][i].IsPlaying) { count++; };
|
||||
}
|
||||
}
|
||||
return count;
|
||||
|
||||
Reference in New Issue
Block a user