Refactors event, entity, and physics management to use thread-safe and lock-free data structures (Immutable collections, ConcurrentQueue, ConcurrentDictionary, Channel) for improved concurrency and performance. Replaces O(n) queue lookups with O(1) set/dictionary checks, ensures atomic updates for shared state, and optimizes queue draining and deferred action processing. Updates related code to use new APIs and patterns, and adds documentation for thread safety and workflow.
101 lines
3.5 KiB
C#
101 lines
3.5 KiB
C#
using Barotrauma.Networking;
|
|
using Microsoft.Xna.Framework;
|
|
using System;
|
|
using System.Collections.Immutable;
|
|
using System.Threading;
|
|
|
|
namespace Barotrauma
|
|
{
|
|
/// <summary>
|
|
/// Unlocks a "locked" pathways between locations, if there are any such paths adjacent to the current location.
|
|
/// </summary>
|
|
class UnlockPathAction : EventAction
|
|
{
|
|
private static volatile ImmutableHashSet<LocationConnection> _pathsUnlockedThisRound =
|
|
ImmutableHashSet<LocationConnection>.Empty;
|
|
|
|
public static void ResetPathsUnlockedThisRound()
|
|
{
|
|
_pathsUnlockedThisRound = ImmutableHashSet<LocationConnection>.Empty;
|
|
}
|
|
|
|
private static void AddUnlockedPath(LocationConnection connection)
|
|
{
|
|
ImmutableHashSet<LocationConnection> original, updated;
|
|
do
|
|
{
|
|
original = _pathsUnlockedThisRound;
|
|
updated = original.Add(connection);
|
|
} while (Interlocked.CompareExchange(ref _pathsUnlockedThisRound, updated, original) != original);
|
|
}
|
|
|
|
public UnlockPathAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
|
|
|
|
private bool isFinished = false;
|
|
|
|
public override bool IsFinished(ref string goTo)
|
|
{
|
|
return isFinished;
|
|
}
|
|
|
|
public override void Reset()
|
|
{
|
|
isFinished = false;
|
|
}
|
|
|
|
public override void Update(float deltaTime)
|
|
{
|
|
if (isFinished) { return; }
|
|
if (GameMain.GameSession?.Map?.CurrentLocation?.Connections != null)
|
|
{
|
|
foreach (LocationConnection connection in GameMain.GameSession?.Map?.CurrentLocation?.Connections)
|
|
{
|
|
if (!connection.Locked) { continue; }
|
|
connection.Locked = false;
|
|
AddUnlockedPath(connection);
|
|
#if SERVER
|
|
NotifyUnlock(connection);
|
|
#else
|
|
new GUIMessageBox(string.Empty, TextManager.Get("pathunlockedgeneric"),
|
|
Array.Empty<LocalizedString>(), type: GUIMessageBox.Type.InGame, iconStyle: "UnlockPathIcon", relativeSize: new Vector2(0.3f, 0.15f), minSize: new Point(512, 128));
|
|
#endif
|
|
}
|
|
}
|
|
|
|
isFinished = true;
|
|
}
|
|
|
|
public override string ToDebugString()
|
|
{
|
|
return $"{ToolBox.GetDebugSymbol(isFinished)} {nameof(UnlockPathAction)}";
|
|
}
|
|
|
|
#if SERVER
|
|
public static void NotifyPathsUnlockedThisRound(Client client)
|
|
{
|
|
foreach (LocationConnection connection in _pathsUnlockedThisRound)
|
|
{
|
|
NotifyUnlock(connection, client);
|
|
}
|
|
}
|
|
|
|
private static void NotifyUnlock(LocationConnection connection)
|
|
{
|
|
foreach (Client client in GameMain.Server.ConnectedClients)
|
|
{
|
|
NotifyUnlock(connection, client);
|
|
}
|
|
}
|
|
|
|
private static void NotifyUnlock(LocationConnection connection, Client client)
|
|
{
|
|
IWriteMessage outmsg = new WriteOnlyMessage();
|
|
outmsg.WriteByte((byte)ServerPacketHeader.EVENTACTION);
|
|
outmsg.WriteByte((byte)EventManager.NetworkEventType.UNLOCKPATH);
|
|
outmsg.WriteUInt16((UInt16)GameMain.GameSession.Map.Connections.IndexOf(connection));
|
|
GameMain.Server.ServerPeer.Send(outmsg, client.Connection, DeliveryMethod.Reliable);
|
|
}
|
|
#endif
|
|
}
|
|
}
|