BITFALL/Assets/BITKit/Core/Applation/BITApp.cs

321 lines
11 KiB
C#
Raw Normal View History

2023-08-12 01:43:24 +08:00
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using Cysharp.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
2023-10-02 23:24:56 +08:00
// ReSharper disable StringLiteralTypo
2023-08-12 01:43:24 +08:00
#if NET5_0_OR_GREATER
using Microsoft.Extensions.DependencyInjection;
#endif
namespace BITKit
{
public class AppIsNotPlayingException : Exception
{
public override string Message => "Application Is Not Playing";
}
public class BITApp
{
2023-10-02 23:24:56 +08:00
public static async UniTask SwitchToMainThread()
{
await UniTask.SwitchToSynchronizationContext(SynchronizationContext);
}
2023-08-12 01:43:24 +08:00
public static class Time
{
2023-10-29 15:27:13 +08:00
public static float ElapsedTime { get; internal set; }
2023-08-12 01:43:24 +08:00
public static float DeltaTime { get; internal set; }
public static double TimeAsDouble { get; internal set; }
}
[System.Serializable]
public record AppSettings
{
public bool AllowInitialize = true;
public List<string> whiteList = new();
public List<string> blackList = new()
{
"System",
"Unity",
"UnityEngine",
"Microsoft",
"Godot",
"Internal",
"GodotPlugins",
// ReSharper disable once StringLiteralTypo
"Cysharp",
"kcp2k",
2023-08-23 01:59:40 +08:00
"Swashbuckle",
"Newtonsoft",
"Lightbug",
"NiceIO",
"AndroidPlayerBuildProgram",
"Steamworks",
"AYellowpaper",
"Utilities",
"mattatz",
"AmazingAssets",
"MeshCombineStudio",
"kcp2k",
"AYellowpaper",
"MudBlazor",
"TextCopy",
"Blazored",
"TextCopy",
2023-10-02 23:24:56 +08:00
"mattatz",
"TrailsFX",
"Knife",
"Needle",
"NiceIO",
"AndroidPlayerBuildProgram",
"DocCodeExamples",
"System",
"UnityEngine",
"Unity",
"Microsoft",
"UnityEditor",
"Google",
"Mono",
"ZXing",
"ImmersiveVRTools",
"MonKey",
"FLib",
"Kcp",
"Udx",
"Sirenix",
"TMPro",
"RotaryHeart",
"Cinemachine",
"ParadoxNotion",
"Net",
"VSCodeEditor",
"AOT",
"UnityEditorInternal",
"UnityEngineInternal",
"JetBrains",
"Bee",
"NotInvited",
"HighlightPlus",
"DG",
"Hierarchy2",
"Cysharp",
"JetBrains",
"Packages",
"Newtonsoft_X",
"Binding",
"NodeCanvas",
"SaveDuringPlay",
"LimWorks",
"MagicaCloth2",
"FastScriptReload",
"ParrelSync",
"KinematicCharacterController",
"LimWorksEditor",
"BuildComponent",
"dnlib",
"BigIntegerLibrary",
"Ionic",
"log4net",
"ImmersiveVrToolsCommon",
"NUnit",
"HarmonyLib",
"MonoMod",
"WebDav",
"PlasticGui",
"Codice",
"GluonGui",
"PlasticPipe",
"XDiffGui",
"MacFsWatcher",
"MacUI",
"PlayerBuildProgramLibrary",
"ExCSS",
"ScriptCompilationBuildProgram",
"BeeBuildProgramCommon",
"Accessibility",
"CodiceApp",
"Newtonsoft",
"MergetoolGui",
"TreeEditor",
"MackySoft",
"FullscreenEditor",
"mattatz",
"AYellowpaper",
"kcp2k",
"MeshCombineStudio",
"AmazingAssets",
"Utilities"
2023-08-12 01:43:24 +08:00
};
}
#if NET5_0_OR_GREATER
/// <summary>
/// 依赖服务集合
/// </summary>
public static ServiceCollection ServiceCollection { get; internal set; } = new();
/// <summary>
/// 依赖服务提供接口
/// </summary>
2023-08-23 01:59:40 +08:00
public static ServiceProvider ServiceProvider { get; internal set; }
2023-08-12 01:43:24 +08:00
/// <summary>
/// 服务创建后的回调
/// </summary>
public static Action<ServiceProvider> OnServiceProviderBuilded;
#endif
/// <summary>
/// 主线程
/// </summary>
public static SynchronizationContext SynchronizationContext { get; private set; }
[System.Serializable]
public class OpenPath : IAction, IDisposable
{
public string path;
public void Dispose()
{
path = null;
}
public void Execute()
{
//path = string.IsNullOrEmpty(path) ? Environment.CurrentDirectory : path.Replace(@"/", @"\");
var path = Environment.ExpandEnvironmentVariables(this.path);
path = string.IsNullOrEmpty(path) ? Environment.CurrentDirectory : System.IO.Path.Combine(Environment.CurrentDirectory, path);
BIT4Log.Log<OpenPath>($"正在打开文件夹:{path}");
try
{
var process = Process.Start("explorer.exe", path);
SwitchToThisWindow(process.MainWindowHandle, true);
}
catch (System.Exception e)
{
BIT4Log.LogException(e);
}
}
}
[System.Serializable]
public class OpenAPP : IAction, IDisposable
{
public string path;
public string WorkingDirectory;
public void Dispose()
{
path = WorkingDirectory = null;
}
public void Execute()
{
if (File.Exists(path))
{
ProcessStartInfo startInfo = new(path)
{
UseShellExecute = true
};
if (string.IsNullOrEmpty(WorkingDirectory) is false)
{
startInfo.WorkingDirectory = WorkingDirectory;
}
var process = Process.Start(startInfo);
SwitchToThisWindow(process.MainWindowHandle, true);
}
}
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern bool SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
public static string AppName { get; private set; } = nameof(BITApp);
2023-08-23 01:59:40 +08:00
private static CancellationTokenSource CancellationTokenSource = new();
public static CancellationToken CancellationToken => CancellationTokenSource.Token;
2023-08-12 01:43:24 +08:00
public static InitializationState State;
public static Assembly[] Assemblies;
public static AppSettings Settings { get; protected set; }
2023-10-02 23:24:56 +08:00
private static DateTime InitialTime { get; set; }=DateTime.Now;
public static async UniTask Start(string appName = nameof(BITApp),AppSettings settings=default)
2023-08-12 01:43:24 +08:00
{
Time.TimeAsDouble = 0;
Time.DeltaTime = 1 / 60f;
SynchronizationContext=SynchronizationContext.Current;
Settings = settings??new AppSettings();
CancellationTokenSource = new CancellationTokenSource();
AppName = appName;
ThreadHelper.LogCurrentThread();
2023-10-02 23:24:56 +08:00
InitialTime = DateTime.Now;
2023-08-12 01:43:24 +08:00
await Init();
}
private static async Task Init()
{
try
{
if (State is not InitializationState.None)
{
2023-08-23 01:59:40 +08:00
BIT4Log.Warning("警告:上次启动可能未正确退出");
return;
2023-08-12 01:43:24 +08:00
}
//加载app-settings.json
var appSettingsPath = Path.Combine(Environment.CurrentDirectory, "appsettings.json");
if (PathHelper.TryGetText(appSettingsPath,out var json))
{
DataParser.Set(json);
BIT4Log.Log<BITApp>("已加载全局appsettings");
}
//内部反射初始化
ThreadHelper.InitAPP();
await UniTask.SwitchToThreadPool();
ThreadHelper.LogCurrentThread();
Stopwatch stopwatch = new();
stopwatch.Start();
Stopwatch reflectionHelperWatch = new();
reflectionHelperWatch.Start();
2023-08-23 01:59:40 +08:00
await ReflectionHelper.Init();
2023-08-12 01:43:24 +08:00
reflectionHelperWatch.Stop();
2023-10-02 23:24:56 +08:00
Stopwatch commandWatch = new();
await BITCommands.InitializeAsync();
commandWatch.Stop();
2023-08-23 01:59:40 +08:00
2023-08-12 01:43:24 +08:00
stopwatch.Stop();
State = InitializationState.Initialized;
2023-08-23 01:59:40 +08:00
BIT4Log.Log<BITApp>($"已完成初始化,耗时:{stopwatch.ElapsedMilliseconds}ms");
2023-10-02 23:24:56 +08:00
BIT4Log.Log<BITApp>($"反射初始化耗时:{reflectionHelperWatch.ElapsedMilliseconds}ms");
2023-08-12 01:43:24 +08:00
}
catch (System.Exception e)
{
2023-08-23 01:59:40 +08:00
BIT4Log.Warning<BITApp>($"{nameof(BITApp)}初始化错误:");
2023-08-12 01:43:24 +08:00
BIT4Log.LogException(e);
}
2023-11-02 20:58:55 +08:00
#if NET5_0_OR_GREATER
ServiceProvider = ServiceCollection.BuildServiceProvider();
#endif
2023-08-12 01:43:24 +08:00
}
2023-08-23 01:59:40 +08:00
public static void Stop()
2023-08-12 01:43:24 +08:00
{
2023-10-02 23:24:56 +08:00
var runTime = DateTime.Now - InitialTime;
2023-08-12 01:43:24 +08:00
BIT4Log.Log<BITApp>($"正在停止{nameof(BITApp)}");
CancellationTokenSource.Cancel();
State = InitializationState.None;
2023-10-02 23:24:56 +08:00
BITCommands.Dispose();
2023-08-12 01:43:24 +08:00
BIT4Log.Log<BITApp>($"已停止{nameof(BITApp)}");
2023-10-20 19:31:12 +08:00
BIT4Log.Log<BITApp>($"运行时间:{runTime.ToString("hh\\:mm\\:ss")}");
2023-08-12 01:43:24 +08:00
BIT4Log.Log<BITApp>("Exit Code:0");
2023-10-02 23:24:56 +08:00
2023-08-12 01:43:24 +08:00
}
public static void Run(string path, string WorkingDirectory = "")
{
using var open = new OpenAPP() { path = path, WorkingDirectory = WorkingDirectory };
open.Execute();
}
public static void Open(string path)
{
using var open = new OpenPath() { path = path };
open.Execute();
}
}
}