提交功能

This commit is contained in:
Bob.Song
2026-02-08 16:58:32 +08:00
commit 9dd1e6c278
67 changed files with 4588 additions and 0 deletions

View File

@@ -0,0 +1,106 @@
namespace NBC
{
public class ParallelTaskCollection : TaskCollection
{
private int _currentIndex;
/// <summary>
/// 最大并行数量 (默认为9)
/// </summary>
public int ParallelNum = 9;
protected override NTaskStatus RunTasksAndCheckIfDone()
{
var st = NTaskStatus.Running;
if (CurRunTask.Count < ParallelNum && _currentIndex < RawList.Count)
{
var num = ParallelNum - CurRunTask.Count;
for (var index = 0; index < num; index++)
if (_currentIndex < RawList.Count)
{
CurRunTask.Add(RawList[_currentIndex]);
_currentIndex += 1;
}
}
for (var index = 0; index < CurrentTask.Count; index++)
{
var element = CurrentTask[index];
var childSt = element.Process();
if (FailBreak && childSt == NTaskStatus.Fail)
{
_errorMsg = element.ErrorMsg;
st = NTaskStatus.Fail;
break;
}
if (childSt == NTaskStatus.Success || childSt == NTaskStatus.Fail)
{
CurrentTask.RemoveAt(index);
index--;
FinishList.Add(element);
}
}
if (FinishList.Count >= RawList.Count) st = NTaskStatus.Success;
// for (var index = 0; index < CurrentTask.Count; index++)
// {
// var element = CurrentTask[index];
// var childSt = element.Process();
//
// if (childSt >= Status.Success)
// {
// if (FailBreak && childSt == Status.Fail)
// {
// _errorMsg = element.ErrorMsg;
// st = Status.Fail;
// }
//
// CurrentTask.RemoveAt(index);
// index--;
// FinishList.Add(element);
// }
// }
//
// if (FinishList.Count >= RawList.Count)
// {
// st = Status.Success;
// }
// else if (CurRunTask.Count < ParallelNum && _currentIndex < RawList.Count)
// {
// var num = ParallelNum - CurRunTask.Count;
// for (var index = 0; index < num; index++)
// {
// if (_currentIndex < RawList.Count)
// {
// CurRunTask.Add(RawList[_currentIndex]);
// _currentIndex += 1;
// }
// }
// }
return st;
}
public override void Reset()
{
base.Reset();
_currentIndex = 0;
}
public override void Stop()
{
base.Stop();
_currentIndex = 0;
}
public override void Clear()
{
base.Clear();
_currentIndex = 0;
}
}
}

View File

@@ -0,0 +1,113 @@
namespace NBC
{
public class SequenceTaskCollection : TaskCollection
{
private int _currentIndex;
public override string Info
{
get
{
if (CurrentTask != null && CurrentTask.Count > 0) return CurrentTask[0].Info;
return TaskInfo;
}
}
protected override NTaskStatus RunTasksAndCheckIfDone()
{
var st = NTaskStatus.Running;
if (RawList.Count > 0)
{
if (CurRunTask.Count == 0 && _currentIndex < RawList.Count) CurRunTask.Add(RawList[_currentIndex]);
NTaskStatus curSt;
do
{
var childTask = CurRunTask[0];
curSt = childTask.Process();
if (curSt >= NTaskStatus.Success)
{
if (FailBreak && curSt == NTaskStatus.Fail)
{
_errorMsg = childTask.ErrorMsg;
st = NTaskStatus.Fail;
break;
}
FinishList.Add(childTask);
CurRunTask.RemoveAt(0);
_currentIndex++;
if (_currentIndex < RawList.Count)
CurRunTask.Add(RawList[_currentIndex]);
}
} while (curSt >= NTaskStatus.Success && CurRunTask.Count > 0);
if (FinishList.Count == RawList.Count)
st = NTaskStatus.Success;
}
else
{
st = NTaskStatus.Success;
}
// if (RawList.Count > 0)
// {
// if (FinishList.Count == RawList.Count)
// {
// st = Status.Success;
// }
// else
// {
// if (CurRunTask.Count == 0)
// {
// CurRunTask.Add(RawList[_currentIndex]);
// }
//
// var childTask = CurRunTask[0];
// var curSt = childTask.Process();
//
//
// if (curSt >= Status.Success)
// {
// if (FailBreak && curSt == Status.Fail)
// {
// _errorMsg = childTask.ErrorMsg;
// st = Status.Fail;
// }
//
// FinishList.Add(childTask);
// CurRunTask.RemoveAt(0);
// _currentIndex++;
// }
// }
// }
// else
// {
// st = Status.Success;
// }
return st;
}
public override void Reset()
{
base.Reset();
_currentIndex = 0;
}
public override void Stop()
{
base.Stop();
_currentIndex = 0;
}
public override void Clear()
{
base.Clear();
_currentIndex = 0;
}
}
}

View File

@@ -0,0 +1,88 @@
using System.Collections.Generic;
namespace NBC
{
public abstract class TaskCollection : NTask, ITaskCollection
{
protected readonly List<ITask> CurRunTask;
protected readonly List<ITask> FinishList;
protected readonly List<ITask> RawList;
public TaskCollection(string taskInfo = "")
{
RawList = new List<ITask>();
FinishList = new List<ITask>();
CurRunTask = new List<ITask>();
TaskInfo = taskInfo;
Status = NTaskStatus.None;
}
public virtual int Count => RawList.Count + FinishList.Count;
/// <summary>
/// 任务失败中断任务链
/// </summary>
public virtual bool FailBreak { get; set; }
public List<ITask> CurrentTask => CurRunTask;
public override float Progress
{
get
{
if (Status == NTaskStatus.Success) return 1;
if (Status == NTaskStatus.None) return 0;
var finishCount = FinishList.Count;
for (var index = 0; index < CurRunTask.Count; index++)
{
var element = CurRunTask[index];
finishCount += (int)element.Progress;
}
return finishCount * 1f / RawList.Count;
}
}
public ITaskCollection AddTask(ITask task)
{
RawList.Add(task);
return this;
}
public override void Reset()
{
FinishList.Clear();
CurrentTask.Clear();
Status = NTaskStatus.None;
for (int i = 0, len = RawList.Count; i < len; i++) RawList[i].Reset();
}
public override void Stop()
{
FinishList.Clear();
Status = NTaskStatus.None;
for (var i = 0; i < CurRunTask.Count; i++)
{
var task = CurrentTask[i];
task.Stop();
}
}
public virtual void Clear()
{
FinishList.Clear();
RawList.Clear();
Status = NTaskStatus.None;
}
protected override NTaskStatus OnProcess()
{
return RunTasksAndCheckIfDone();
}
protected abstract NTaskStatus RunTasksAndCheckIfDone();
}
}

View File

@@ -0,0 +1,10 @@
namespace NBC
{
/// <summary>
/// 进度
/// </summary>
public interface IProcess
{
NTaskStatus Process();
}
}

View File

@@ -0,0 +1,49 @@
namespace NBC
{
public interface IRunner
{
/// <summary>
/// 是否暂停
/// </summary>
bool IsPaused { get; set; }
/// <summary>
/// 是否已经终止了
/// </summary>
bool IsKilled { get; }
/// <summary>
/// 当前运行的任务数量
/// </summary>
int RunningTaskNum { get; }
/// <summary>
/// 准备执行的任务数量
/// </summary>
int NeedRunTaskNum { get; }
/// <summary>
/// 执行一个任务
/// </summary>
/// <param name="task">任务对象</param>
void Run(ITask task);
void Process();
/// <summary>
/// 停止任务
/// </summary>
/// <param name="task">任务对象</param>
void StopTask(ITask task);
/// <summary>
/// 停止所有任务
/// </summary>
void StopAllTask();
/// <summary>
/// 终止任务
/// </summary>
void ShutDown();
}
}

View File

@@ -0,0 +1,77 @@
using System;
using System.Collections;
namespace NBC
{
public interface ITask : IProcess, IEnumerator
{
NTaskStatus Status { get; }
/// <summary>
/// 当前任务的信息
/// </summary>
string Info { get; }
/// <summary>
/// 错误信息
/// </summary>
string ErrorMsg { get; }
/// <summary>
/// 当前任务的进度
/// </summary>
float Progress { get; }
/// <summary>
/// 任务正在执行
/// </summary>
bool IsRunning { get; }
/// <summary>
/// 任务是否执行完成
/// </summary>
bool IsDone { get; }
/// <summary>
/// 任务参数
/// </summary>
/// <param name="argsName"></param>
object this[string argsName] { get; set; }
/// <summary>
/// 停止任务
/// </summary>
void Stop();
/// <summary>
/// 任务开始回调
/// </summary>
/// <param name="callback"></param>
/// <param name="cover"></param>
/// <returns></returns>
ITask OnStarted(Action<ITask> callback, bool cover = false);
/// <summary>
/// 任务执行回调
/// </summary>
/// <param name="callback"></param>
/// <param name="cover"></param>
/// <returns></returns>
ITask OnUpdated(Action<ITask> callback, bool cover = false);
/// <summary>
/// 任务完成回调
/// </summary>
/// <param name="callback"></param>
/// <param name="cover"></param>
/// <returns></returns>
ITask OnCompleted(Action<ITask> callback, bool cover = false);
/// <summary>
/// 运行任务
/// </summary>
/// <param name="runner">任务运行器</param>
void Run(IRunner runner);
}
}

View File

@@ -0,0 +1,24 @@
using System.Collections.Generic;
namespace NBC
{
public interface ITaskCollection : ITask
{
/// <summary>
/// 当前运行的任务堆栈
/// </summary>
List<ITask> CurrentTask { get; }
/// <summary>
/// 添加一个任务
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
ITaskCollection AddTask(ITask task);
/// <summary>
/// 清理任务列表
/// </summary>
void Clear();
}
}

View File

@@ -0,0 +1,7 @@
namespace NBC
{
public interface ITaskRun
{
void Run(IRunner runner);
}
}

198
Core/Task/NTask.cs Normal file
View File

@@ -0,0 +1,198 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace NBC
{
public abstract class NTask : ITask
{
protected readonly Dictionary<string, object> _argsDic = new();
protected string _errorMsg;
protected float _progress;
protected string TaskInfo;
public virtual string Info
{
get => TaskInfo;
set => TaskInfo = value;
}
public NTaskStatus Status { get; protected set; } = NTaskStatus.None;
public virtual string ErrorMsg => _errorMsg;
public virtual float Progress => _progress;
public virtual bool IsRunning => Status == NTaskStatus.Running;
public virtual bool IsDone => Status == NTaskStatus.Success || Status == NTaskStatus.Fail;
public object this[string argsName]
{
get
{
if (_argsDic.TryGetValue(argsName, out var args)) return args;
return null;
}
set => _argsDic[argsName] = value;
}
public virtual void Stop()
{
Status = NTaskStatus.None;
}
public virtual void Run(IRunner runner)
{
Reset();
runner?.Run(this);
}
public NTaskStatus Process()
{
if (Status == NTaskStatus.None) Start();
Status = OnProcess();
CallUpdateListener();
if (Status == NTaskStatus.Success)
{
_progress = 1;
CallCompleteListener(Status);
}
else if (Status == NTaskStatus.Fail)
{
_progress = 1;
CallCompleteListener(Status);
}
return Status;
}
protected virtual void OnStart()
{
}
protected virtual NTaskStatus OnProcess()
{
return Status;
}
protected void Finish()
{
_progress = 1;
Status = NTaskStatus.Success;
}
protected void Fail(string message)
{
_progress = 1;
Status = NTaskStatus.Fail;
_errorMsg = message;
}
private void Start()
{
Reset();
Status = NTaskStatus.Running;
_progress = 0;
OnStart();
CallStartListener();
}
#region
protected event Action<ITask> OnStartListener;
protected event Action<ITask> OnCompleteListener;
protected event Action<ITask> OnUpdateListener;
public ITask OnStarted(Action<ITask> callback, bool cover = false)
{
if (cover)
OnStartListener = callback;
else
OnStartListener += callback;
return this;
}
public ITask OnUpdated(Action<ITask> callback, bool cover = false)
{
if (cover)
OnUpdateListener = callback;
else
OnUpdateListener += callback;
return this;
}
public ITask OnCompleted(Action<ITask> callback, bool cover = false)
{
if (cover)
OnCompleteListener = callback;
else
OnCompleteListener += callback;
return this;
}
protected void CallStartListener()
{
OnStartListener?.Invoke(this);
}
protected void CallCompleteListener(NTaskStatus taskStatus)
{
OnCompleteListener?.Invoke(this);
_taskCompletionSource?.TrySetResult(null);
}
protected void CallUpdateListener()
{
OnUpdateListener?.Invoke(this);
}
#endregion
#region
private TaskCompletionSource<object> _taskCompletionSource;
/// <summary>
/// 异步操作任务
/// </summary>
public Task Task
{
get
{
if (_taskCompletionSource == null)
{
_taskCompletionSource = new TaskCompletionSource<object>();
if (IsDone)
_taskCompletionSource.SetResult(null);
}
return _taskCompletionSource.Task;
}
}
#endregion
#region IEnumerator
bool IEnumerator.MoveNext()
{
return !IsDone;
}
public virtual void Reset()
{
Status = NTaskStatus.None;
}
object IEnumerator.Current => null;
#endregion
}
}

25
Core/Task/NTaskStatus.cs Normal file
View File

@@ -0,0 +1,25 @@
namespace NBC
{
public enum NTaskStatus
{
/// <summary>
/// 任务还未执行
/// </summary>
None = 0,
/// <summary>
/// 任务运行
/// </summary>
Running,
/// <summary>
/// 任务执行成功
/// </summary>
Success,
/// <summary>
/// 任务执行失败
/// </summary>
Fail
}
}

View File

@@ -0,0 +1,18 @@
namespace NBC
{
/// <summary>
/// 操作信息类
/// </summary>
public class FlushingOperation
{
/// <summary>
/// 是否被终结
/// </summary>
public bool Kill;
/// <summary>
/// 是否暂停
/// </summary>
public bool Paused;
}
}

View File

@@ -0,0 +1,89 @@
using System.Collections.Generic;
namespace NBC
{
public class Runner : IRunner
{
/// <summary>
/// 当前运行的任务
/// </summary>
protected readonly List<ITask> Coroutines = new();
/// <summary>
/// 当前操作的信息
/// </summary>
protected readonly FlushingOperation FlushingOperation = new();
/// <summary>
/// 准备要运行的任务
/// </summary>
protected readonly Queue<ITask> ReadyTask = new();
public bool IsPaused
{
get => FlushingOperation.Paused;
set => FlushingOperation.Paused = value;
}
public bool IsKilled => FlushingOperation.Kill;
public int RunningTaskNum => Coroutines.Count;
public int NeedRunTaskNum => ReadyTask.Count;
public virtual void Run(ITask task)
{
ReadyTask.Enqueue(task);
}
public virtual void Process()
{
var count = ReadyTask.Count;
for (var i = 0; i < count; i++)
{
var task = ReadyTask.Dequeue();
Coroutines.Add(task);
}
if (Coroutines.Count < 1) return;
var index = 0;
bool mustExit;
do
{
var childTask = Coroutines[index];
var st = childTask.Process();
if (st >= NTaskStatus.Success)
Coroutines.Remove(childTask);
else
index++;
mustExit = Coroutines.Count == 0 || index >= Coroutines.Count;
} while (!mustExit);
}
public virtual void StopTask(ITask task)
{
var index = Coroutines.IndexOf(task);
if (index != -1)
{
var t = Coroutines[index];
t.Stop();
Coroutines.RemoveAt(index);
}
}
public virtual void StopAllTask()
{
ReadyTask.Clear();
for (var i = 0; i < Coroutines.Count; i++) Coroutines[i].Stop();
Coroutines.Clear();
}
public virtual void ShutDown()
{
IsPaused = false;
FlushingOperation.Kill = true;
StopAllTask();
}
}
}

View File

@@ -0,0 +1,77 @@
using System.Collections.Generic;
namespace NBC
{
public class RunnerProcess : IProcess
{
/// <summary>
/// 当前运行的任务
/// </summary>
protected readonly List<ITask> Coroutines;
/// <summary>
/// 当前操作的信息
/// </summary>
protected readonly FlushingOperation FlushingOperation;
/// <summary>
/// 准备要运行的任务
/// </summary>
protected readonly Queue<ITask> ReadyTask;
/// <summary>
/// 进程名称
/// </summary>
protected string Name;
public RunnerProcess(string name, List<ITask> coroutines, Queue<ITask> readyTask, FlushingOperation op)
{
Name = name;
Coroutines = coroutines;
ReadyTask = readyTask;
FlushingOperation = op;
}
public NTaskStatus Process()
{
var flag = false;
if (FlushingOperation.Kill)
{
flag = true;
}
else
{
for (var index = 0; index < ReadyTask.Count; index++)
{
// var task = ReadyTask[0];
var task = ReadyTask.Dequeue();
Coroutines.Add(task);
// ReadyTask.RemoveAt(0);
}
if (Coroutines.Count == 0 || FlushingOperation.Paused)
{
flag = false;
}
else
{
var index = 0;
var mustExit = false;
do
{
var childTask = Coroutines[index];
var st = childTask.Process();
if (st >= NTaskStatus.Success)
Coroutines.RemoveAt(index); //.splice(index, 1);
else
index++;
mustExit = Coroutines.Count == 0 || index >= Coroutines.Count;
} while (!mustExit);
}
}
return flag ? NTaskStatus.Success : NTaskStatus.Running;
}
}
}

54
Core/TaskRunner.cs Normal file
View File

@@ -0,0 +1,54 @@
using NBC;
namespace ACBuildService;
/// <summary>
/// 默认任务执行器
/// </summary>
public class TaskRunner : Runner
{
private static TaskRunner mUpdateRunner;
public static TaskRunner Scheduler => mUpdateRunner ??= new TaskRunner();
private readonly List<IProcess> _updateRoutines = new List<IProcess>();
public event Action OnUpdate;
public TaskRunner()
{
Time.OnUpdate += Update;
StartCoroutine(new RunnerProcess("TaskRunner", Coroutines, ReadyTask, FlushingOperation));
}
private void StartCoroutine(IProcess process)
{
var routines = _updateRoutines;
if (!routines.Contains(process))
{
routines.Add(process);
}
}
private void Update()
{
ExecuteRoutines(_updateRoutines);
OnUpdate?.Invoke();
}
private void ExecuteRoutines(List<IProcess> arr)
{
if (arr != null && arr.Count > 0)
{
for (var index = 0; index < arr.Count; index++)
{
var task = arr[index];
var st = task.Process();
if (st == NTaskStatus.Success)
{
arr.RemoveAt(index);
index--;
}
}
}
}
}

88
Core/Time.cs Normal file
View File

@@ -0,0 +1,88 @@
namespace ACBuildService;
public static class Time
{
public const long OneDay = 86400000;
public const long Hour = 3600000;
public const long Minute = 60000;
private static TimeInfo _timeInfo = new TimeInfo();
public static long Now => _timeInfo.Now();
public static long NowSeconds => Now / 1000;
public static DateTime DateTimeNow => DateTime.Now;
public static long FrameTime => _timeInfo.FrameTime;
public static event Action OnUpdate;
public static event Action OnLateUpdate;
internal static void Awake()
{
}
internal static void Update()
{
_timeInfo.Update();
OnUpdate?.Invoke();
}
internal static void LateUpdate()
{
OnLateUpdate?.Invoke();
}
}
public class TimeInfo
{
private int timeZone;
public int TimeZone
{
get => timeZone;
set
{
timeZone = value;
dt = dt1970.AddHours(TimeZone);
}
}
private readonly DateTime dt1970;
private DateTime dt;
public long FrameTime;
public TimeInfo()
{
dt1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
FrameTime = Now();
}
public void Update()
{
FrameTime = Now();
}
/// <summary>
/// 根据时间戳获取时间
/// </summary>
public DateTime ToDateTime(long timeStamp)
{
return dt.AddTicks(timeStamp * 10000);
}
// 线程安全
public long Now()
{
return (DateTime.UtcNow.Ticks - dt1970.Ticks) / 10000;
}
public long Transition(DateTime d)
{
return (d.Ticks - dt.Ticks) / 10000;
}
}