Unstable 1.1.14.0
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
@@ -15,20 +17,20 @@ namespace Barotrauma
|
||||
public abstract bool EndsCoroutine(CoroutineHandle handle);
|
||||
}
|
||||
|
||||
class EnumCoroutineStatus : CoroutineStatus
|
||||
sealed class EnumCoroutineStatus : CoroutineStatus
|
||||
{
|
||||
private enum StatusValue
|
||||
{
|
||||
Running, Success, Failure
|
||||
}
|
||||
|
||||
private readonly StatusValue Value;
|
||||
private readonly StatusValue value;
|
||||
|
||||
private EnumCoroutineStatus(StatusValue value) { Value = value; }
|
||||
private EnumCoroutineStatus(StatusValue value) { this.value = value; }
|
||||
|
||||
public new readonly static EnumCoroutineStatus Running = new EnumCoroutineStatus(StatusValue.Running);
|
||||
public new readonly static EnumCoroutineStatus Success = new EnumCoroutineStatus(StatusValue.Success);
|
||||
public new readonly static EnumCoroutineStatus Failure = new EnumCoroutineStatus(StatusValue.Failure);
|
||||
public new static readonly EnumCoroutineStatus Running = new EnumCoroutineStatus(StatusValue.Running);
|
||||
public new static readonly EnumCoroutineStatus Success = new EnumCoroutineStatus(StatusValue.Success);
|
||||
public new static readonly EnumCoroutineStatus Failure = new EnumCoroutineStatus(StatusValue.Failure);
|
||||
|
||||
public override bool CheckFinished(float deltaTime)
|
||||
{
|
||||
@@ -37,43 +39,74 @@ namespace Barotrauma
|
||||
|
||||
public override bool EndsCoroutine(CoroutineHandle handle)
|
||||
{
|
||||
if (Value == StatusValue.Failure)
|
||||
if (value == StatusValue.Failure)
|
||||
{
|
||||
DebugConsole.ThrowError("Coroutine \"" + handle.Name + "\" has failed");
|
||||
}
|
||||
return Value != StatusValue.Running;
|
||||
return value != StatusValue.Running;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is EnumCoroutineStatus other && Value == other.Value;
|
||||
return obj is EnumCoroutineStatus other && value == other.value;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Value.GetHashCode();
|
||||
return value.GetHashCode();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value.ToString();
|
||||
return value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
sealed class WaitForSeconds : CoroutineStatus
|
||||
{
|
||||
public readonly float TotalTime;
|
||||
|
||||
private float timer;
|
||||
private readonly bool ignorePause;
|
||||
|
||||
public WaitForSeconds(float time, bool ignorePause = true)
|
||||
{
|
||||
timer = time;
|
||||
TotalTime = time;
|
||||
this.ignorePause = ignorePause;
|
||||
}
|
||||
|
||||
public override bool CheckFinished(float deltaTime)
|
||||
{
|
||||
#if !SERVER
|
||||
if (ignorePause || !CoroutineManager.Paused)
|
||||
{
|
||||
timer -= deltaTime;
|
||||
}
|
||||
#else
|
||||
timer -= deltaTime;
|
||||
#endif
|
||||
return timer <= 0.0f;
|
||||
}
|
||||
|
||||
public override bool EndsCoroutine(CoroutineHandle handle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class CoroutineHandle
|
||||
sealed class CoroutineHandle
|
||||
{
|
||||
public readonly IEnumerator<CoroutineStatus> Coroutine;
|
||||
public readonly string Name;
|
||||
|
||||
public Exception Exception;
|
||||
public volatile bool AbortRequested;
|
||||
public Exception? Exception;
|
||||
public bool AbortRequested;
|
||||
|
||||
public Thread Thread;
|
||||
|
||||
public CoroutineHandle(IEnumerator<CoroutineStatus> coroutine, string name = "", bool useSeparateThread = false)
|
||||
public CoroutineHandle(IEnumerator<CoroutineStatus> coroutine, string name = "")
|
||||
{
|
||||
Coroutine = coroutine;
|
||||
Name = string.IsNullOrWhiteSpace(name) ? coroutine.ToString() : name;
|
||||
Name = string.IsNullOrWhiteSpace(name) ? (coroutine.ToString() ?? "") : name;
|
||||
Exception = null;
|
||||
}
|
||||
|
||||
@@ -88,7 +121,7 @@ namespace Barotrauma
|
||||
|
||||
public static bool Paused { get; private set; }
|
||||
|
||||
public static CoroutineHandle StartCoroutine(IEnumerable<CoroutineStatus> func, string name = "", bool useSeparateThread = false)
|
||||
public static CoroutineHandle StartCoroutine(IEnumerable<CoroutineStatus> func, string name = "")
|
||||
{
|
||||
var handle = new CoroutineHandle(func.GetEnumerator(), name);
|
||||
lock (Coroutines)
|
||||
@@ -96,17 +129,6 @@ namespace Barotrauma
|
||||
Coroutines.Add(handle);
|
||||
}
|
||||
|
||||
handle.Thread = null;
|
||||
if (useSeparateThread)
|
||||
{
|
||||
handle.Thread = new Thread(() => { ExecuteCoroutineThread(handle); })
|
||||
{
|
||||
Name = "Coroutine Thread (" + handle.Name + ")",
|
||||
IsBackground = true
|
||||
};
|
||||
handle.Thread.Start();
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
@@ -115,11 +137,12 @@ namespace Barotrauma
|
||||
return StartCoroutine(DoInvokeAfter(action, delay));
|
||||
}
|
||||
|
||||
private static IEnumerable<CoroutineStatus> DoInvokeAfter(Action action, float delay)
|
||||
private static IEnumerable<CoroutineStatus> DoInvokeAfter(Action? action, float delay)
|
||||
{
|
||||
if (action == null)
|
||||
{
|
||||
yield return CoroutineStatus.Failure;
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (delay > 0.0f)
|
||||
@@ -169,20 +192,12 @@ namespace Barotrauma
|
||||
|
||||
private static void HandleCoroutineStopping(Func<CoroutineHandle, bool> filter)
|
||||
{
|
||||
// No lock here because all callers lock for us
|
||||
foreach (CoroutineHandle coroutine in Coroutines)
|
||||
{
|
||||
if (filter(coroutine))
|
||||
{
|
||||
coroutine.AbortRequested = true;
|
||||
if (coroutine.Thread != null)
|
||||
{
|
||||
bool joined = false;
|
||||
while (!joined)
|
||||
{
|
||||
CrossThread.ProcessTasks();
|
||||
joined = coroutine.Thread.Join(TimeSpan.FromMilliseconds(500));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -199,49 +214,13 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void ExecuteCoroutineThread(CoroutineHandle handle)
|
||||
{
|
||||
try
|
||||
{
|
||||
while (!handle.AbortRequested)
|
||||
{
|
||||
if (PerformCoroutineStep(handle)) { return; }
|
||||
Thread.Sleep((int)(DeltaTime * 1000));
|
||||
}
|
||||
}
|
||||
catch (ThreadAbortException)
|
||||
{
|
||||
//not an error, don't worry about it
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
handle.Exception = e;
|
||||
DebugConsole.ThrowError("Coroutine \"" + handle.Name + "\" has thrown an exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsDone(CoroutineHandle handle)
|
||||
{
|
||||
#if !DEBUG
|
||||
try
|
||||
{
|
||||
#endif
|
||||
if (handle.Thread == null)
|
||||
{
|
||||
return PerformCoroutineStep(handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (handle.Thread.ThreadState.HasFlag(ThreadState.Stopped))
|
||||
{
|
||||
if (handle.Exception != null || handle.Coroutine.Current == CoroutineStatus.Failure)
|
||||
{
|
||||
DebugConsole.ThrowError("Coroutine \"" + handle.Name + "\" has failed");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return PerformCoroutineStep(handle);
|
||||
#if !DEBUG
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -256,27 +235,27 @@ namespace Barotrauma
|
||||
#endif
|
||||
}
|
||||
// Updating just means stepping through all the coroutines
|
||||
private static readonly List<CoroutineHandle> coroutinePass = new List<CoroutineHandle>();
|
||||
public static void Update(bool paused, float deltaTime)
|
||||
{
|
||||
Paused = paused;
|
||||
DeltaTime = deltaTime;
|
||||
|
||||
List<CoroutineHandle> coroutineList;
|
||||
// Do not optimize this as a for loop directly over the Coroutines list!
|
||||
// Coroutines are able to spawn new coroutines!
|
||||
lock (Coroutines)
|
||||
{
|
||||
coroutineList = Coroutines.ToList();
|
||||
coroutinePass.AddRange(Coroutines);
|
||||
}
|
||||
|
||||
foreach (var coroutine in coroutineList)
|
||||
foreach (var coroutine in coroutinePass)
|
||||
{
|
||||
if (IsDone(coroutine))
|
||||
if (!IsDone(coroutine)) { continue; }
|
||||
lock (Coroutines)
|
||||
{
|
||||
lock (Coroutines)
|
||||
{
|
||||
Coroutines.Remove(coroutine);
|
||||
}
|
||||
Coroutines.Remove(coroutine);
|
||||
}
|
||||
}
|
||||
coroutinePass.Clear();
|
||||
}
|
||||
|
||||
public static void ListCoroutines()
|
||||
@@ -292,37 +271,4 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class WaitForSeconds : CoroutineStatus
|
||||
{
|
||||
public readonly float TotalTime;
|
||||
|
||||
private float timer;
|
||||
private readonly bool ignorePause;
|
||||
|
||||
public WaitForSeconds(float time, bool ignorePause = true)
|
||||
{
|
||||
timer = time;
|
||||
TotalTime = time;
|
||||
this.ignorePause = ignorePause;
|
||||
}
|
||||
|
||||
public override bool CheckFinished(float deltaTime)
|
||||
{
|
||||
#if !SERVER
|
||||
if (ignorePause || !CoroutineManager.Paused)
|
||||
{
|
||||
timer -= deltaTime;
|
||||
}
|
||||
#else
|
||||
timer -= deltaTime;
|
||||
#endif
|
||||
return timer <= 0.0f;
|
||||
}
|
||||
|
||||
public override bool EndsCoroutine(CoroutineHandle handle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user