This commit is contained in:
CortexCore
2023-10-02 23:24:56 +08:00
parent 8ef5c7ec0a
commit 947e52e748
183 changed files with 107857 additions and 9378 deletions

View File

@@ -7,6 +7,7 @@ using Cysharp.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
// ReSharper disable StringLiteralTypo
#if NET5_0_OR_GREATER
using Microsoft.Extensions.DependencyInjection;
#endif
@@ -19,6 +20,10 @@ namespace BITKit
}
public class BITApp
{
public static async UniTask SwitchToMainThread()
{
await UniTask.SwitchToSynchronizationContext(SynchronizationContext);
}
public static class Time
{
public static float DeltaTime { get; internal set; }
@@ -59,7 +64,89 @@ namespace BITKit
"TextCopy",
"Blazored",
"TextCopy",
"mattatz"
"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"
};
}
#if NET5_0_OR_GREATER
@@ -144,7 +231,8 @@ namespace BITKit
public static InitializationState State;
public static Assembly[] Assemblies;
public static AppSettings Settings { get; protected set; }
public static async void Start(string appName = nameof(BITApp),AppSettings settings=default)
private static DateTime InitialTime { get; set; }=DateTime.Now;
public static async UniTask Start(string appName = nameof(BITApp),AppSettings settings=default)
{
Time.TimeAsDouble = 0;
Time.DeltaTime = 1 / 60f;
@@ -153,7 +241,7 @@ namespace BITKit
CancellationTokenSource = new CancellationTokenSource();
AppName = appName;
ThreadHelper.LogCurrentThread();
InitialTime = DateTime.Now;
await Init();
}
private static async Task Init()
@@ -182,10 +270,16 @@ namespace BITKit
reflectionHelperWatch.Start();
await ReflectionHelper.Init();
reflectionHelperWatch.Stop();
Stopwatch commandWatch = new();
await BITCommands.InitializeAsync();
commandWatch.Stop();
stopwatch.Stop();
State = InitializationState.Initialized;
BIT4Log.Log<BITApp>($"已完成初始化,耗时:{stopwatch.ElapsedMilliseconds}ms");
BIT4Log.Log<BITApp>($"反射初始化耗时:{reflectionHelperWatch.ElapsedMilliseconds}ms");
}
catch (System.Exception e)
{
@@ -196,11 +290,18 @@ namespace BITKit
}
public static void Stop()
{
var runTime = DateTime.Now - InitialTime;
BIT4Log.Log<BITApp>($"正在停止{nameof(BITApp)}");
CancellationTokenSource.Cancel();
State = InitializationState.None;
BITCommands.Dispose();
BIT4Log.Log<BITApp>($"已停止{nameof(BITApp)}");
BIT4Log.Log<BITApp>($"运行时间:{runTime}");
BIT4Log.Log<BITApp>("Exit Code:0");
}
public static void Run(string path, string WorkingDirectory = "")
{

View File

@@ -1,8 +1,8 @@
#if NETCOREAPP
using System;
using Cysharp.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace BITKit;
public class BITAppForNet
@@ -18,7 +18,7 @@ public class BITAppForNet
BIT4Log.OnSetConsoleColor += color => Console.ForegroundColor = color;
BIT4Log.OnNextLine += Console.WriteLine;
BITApp.Start(name);
await BITApp.Start(name);
await BITBinary.Start();
}
public static UniTask DisposeAsync()

View File

@@ -9,4 +9,14 @@ namespace BITKit
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true, Inherited = true)]
public class CustomTypeAttribute : System.Attribute
{
public readonly Type Type;
public CustomTypeAttribute(Type type)
{
Type = type;
}
}
}

View File

@@ -0,0 +1,87 @@
using System;
using Cysharp.Threading.Tasks;
namespace BITKit.Auth
{
/// <summary>
/// 授权服务
/// </summary>
public interface IAuthService
{
/// <summary>
/// 是否已授权
/// </summary>
bool IsAuthorized { get; }
/// <summary>
/// 是否正在授权
/// </summary>
bool IsAuthorizing { get; }
/// <summary>
/// 异步开始授权
/// </summary>
/// <param name="token">令牌</param>
UniTask AuthorizeAsync(string token);
/// <summary>
/// 异步取消授权
/// </summary>
/// <returns></returns>
UniTask CancelAuthorizationAsync();
/// <summary>
/// 开始授权的回调
/// </summary>
event Action<string> OnAuthorize;
/// <summary>
/// 已授权的回调
/// </summary>
event Action<string> OnAuthorized;
/// <summary>
/// 取消授权的回调
/// </summary>
event Action<string> UnAuthorize;
/// <summary>
/// 授权失败的回调
/// </summary>
event Action<string> OnAuthorizeFailure;
}
public abstract class AuthServiceImplement:IAuthService
{
protected abstract IAuthService service { get; }
bool IAuthService.IsAuthorized => service.IsAuthorized;
bool IAuthService.IsAuthorizing => service.IsAuthorizing;
UniTask IAuthService.AuthorizeAsync(string token)
{
return service.AuthorizeAsync(token);
}
UniTask IAuthService.CancelAuthorizationAsync()
{
return service.CancelAuthorizationAsync();
}
event Action<string> IAuthService.OnAuthorize
{
add => service.OnAuthorize += value;
remove => service.OnAuthorize -= value;
}
event Action<string> IAuthService.OnAuthorized
{
add => service.OnAuthorized += value;
remove => service.OnAuthorized -= value;
}
event Action<string> IAuthService.UnAuthorize
{
add => service.UnAuthorize += value;
remove => service.UnAuthorize -= value;
}
event Action<string> IAuthService.OnAuthorizeFailure
{
add => service.OnAuthorizeFailure += value;
remove => service.OnAuthorizeFailure -= value;
}
}
}

View File

@@ -1,4 +1,5 @@
#if UNITY
#if NET5_0_OR_GREATER
#else
using UnityEngine;
#endif
using System;
@@ -6,7 +7,9 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using Cysharp.Threading.Tasks;
#if NET5_0_OR_GREATER
using Microsoft.SqlServer.Server;
#endif
using Newtonsoft.Json;
namespace BITKit
@@ -14,27 +17,37 @@ namespace BITKit
public class BITBinary
{
private static readonly Dictionary<string, INetMessageReader> netReaders = new();
private static readonly List<Type> serializableTypes = new();
#if NET5_0_OR_GREATER
public static readonly List<Type> serializableTypes = new();
#endif
public static async UniTask Start()
{
netReaders.Clear();
#if NET5_0_OR_GREATER
serializableTypes.Clear();
#endif
foreach (var x in await ReflectionHelper.GetInstances<INetMessageReader>())
{
var typeName = x.GetMessageType().FullName;
if (typeName == null) continue;
netReaders.Add(typeName, x);
BIT4Log.Log<BITBinary>($"已注册类型:{typeName}");
}
#if NET5_0_OR_GREATER
var serializes = await ReflectionHelper.GetInstances<IBinarySerialize>();
#if UNITY
serializes = serializes.Where(x => x is not UnityEngine.Object);
#else
#endif
foreach (var x in serializes)
{
serializableTypes.Add(x.GetType());
BIT4Log.Log<BITBinary>($"已注册类型:{x.GetType().FullName}");
}
// #if NET5_0_OR_GREATER
// #else
// serializes = serializes.Where(x => x is not UnityEngine.Object);
// #endif
// foreach (var x in serializes)
// {
// serializableTypes.Add(x.GetType());
// BIT4Log.Log<BITBinary>($"已注册类型:{x.GetType().FullName}");
// }
}
public static object Read<T>(byte[] buffer) => (T)ReadAsValue(buffer);
@@ -60,18 +73,12 @@ namespace BITKit
var typeName = reader.ReadString();
if (netReaders.TryGetValue(typeName, out var netReader))
{
return netReader.ReadBinaryAsObject(reader);
}
var json = reader.ReadString();
json = reader.ReadString();
try
{
if (BITSharp.TryGetTypeFromFullName(typeName, out var type))
{
return JsonConvert.DeserializeObject(json, type);
}
}
catch (Exception)
{
@@ -119,10 +126,12 @@ namespace BITKit
{
netReader.WriteBinaryAsObject(writer,value);
}
#if NET5_0_OR_GREATER
else if( value is IBinarySerialize serialize)
{
serialize.Write(writer);
}
#endif
else
{
//throw new Exception($"没有找到{value.GetType().Name}的Binary写入方法");
@@ -139,10 +148,12 @@ namespace BITKit
{
return true;
}
else if (serializableTypes.Any(x => x.FullName == typeName))
#if NET5_0_OR_GREATER
else if (serializableTypes.Any(x => x.FullName == typeName))
{
return true;
}
#endif
return false;
}

View File

@@ -54,6 +54,19 @@ namespace BITKit
}
public static async void Excute(string cmd)
{
var cmdSplit = cmd.Split("|");
if (cmdSplit.Length is 1 or 0)
{
cmdSplit = cmd.Split("\n");
}
if (cmdSplit.Length > 1)
{
foreach (var x in cmdSplit)
{
Excute(x);
}
return;
}
await UniTask.SwitchToThreadPool();
await TaskHelper.WaitUntil(() => state is InitializationState.Initialized);
var split = cmd.Split(" ").ToList();
@@ -87,27 +100,24 @@ namespace BITKit
}
static Dictionary<string, MethodInfo> methodInfos = new();
static InitializationState state;
[ExcuteOnStart]
public static void Start()
public static async UniTask InitializeAsync()
{
try
{
Init();
await Init();
}
catch (System.Exception e)
{
BIT4Log.LogException(e);
}
}
[ExcuteOnStop]
public static void Stop()
public static void Dispose()
{
state = 0;
methodInfos.Clear();
}
static async void Init()
private static async UniTask Init()
{
state = InitializationState.Initializing;
await UniTask.SwitchToThreadPool();

View File

@@ -0,0 +1,20 @@
using System;
using System.Security.Cryptography;
namespace BITKit.Crypto
{
public class BITCrypto:ICryptography
{
public string Salt { get; set; } = "2196F3";
public string Hash(string password)
{
var data = System.Text.Encoding.UTF8.GetBytes(password + Salt);
return Convert.ToBase64String(data);
}
public bool Verify(string password, string hash)
{
return Hash(password) == hash;
}
}
}

View File

@@ -0,0 +1,26 @@
namespace BITKit.Crypto
{
/// <summary>
/// 加密接口
/// </summary>
public interface ICryptography
{
/// <summary>
/// 盐
/// </summary>
public string Salt { get; set; }
/// <summary>
/// 获取Hash
/// </summary>
/// <param name="password"></param>
/// <returns></returns>
public string Hash(string password);
/// <summary>
/// 验证密码是否有效
/// </summary>
/// <param name="password">明文密码</param>
/// <param name="hash"></param>
/// <returns></returns>
public bool Verify(string password, string hash);
}
}

Binary file not shown.

View File

@@ -3,7 +3,10 @@ using System.Collections.Generic;
namespace BITKit
{
/// <summary>
/// 双缓冲区
/// </summary>
/// <typeparam name="T"></typeparam>
public interface IDoubleBuffer<T>
{
T Current { get; }
@@ -11,7 +14,10 @@ namespace BITKit
event Action<T> OnRelease;
bool TryGetRelease(out T result);
}
/// <summary>
/// <see cref="IDoubleBuffer{T}"/>
/// </summary>
/// <typeparam name="T"></typeparam>
public class DoubleBuffer<T> : IDoubleBuffer<T>
{
public T Current

View File

@@ -1,5 +1,9 @@
using System.Threading;
using System;
using System.ComponentModel.Design;
#if NET5_0_OR_GREATER
using Microsoft.Extensions.DependencyInjection;
#endif
namespace BITKit.Core.Entites
{
/// <summary>
@@ -8,14 +12,11 @@ namespace BITKit.Core.Entites
public interface IEntity
{
ulong Id { get; }
#if NET5_0_OR_GREATER
bool TryGetComponent<T>(out T component) where T : IEntityComponent;
CancellationToken CancellationToken { get; }
bool TryGetComponent<T>(out T component);
IEntityComponent[] Components { get; }
bool RegisterComponent<T>(T component) where T : IEntityComponent;
#else
#endif
bool RegisterComponent<T>(T component);
IServiceProvider ServiceProvider { get; }
}
/// <summary>
/// 基本实体组件
@@ -24,6 +25,9 @@ namespace BITKit.Core.Entites
{
Type BaseType { get; }
IEntity Entity { get; set; }
#if NET5_0_OR_GREATER
void BuildService(IServiceCollection serviceCollection);
#endif
}
/// <summary>
/// 基本实体服务
@@ -61,24 +65,28 @@ namespace BITKit.Core.Entites
/// <param name="id"></param>
/// <returns></returns>
IEntity Get(ulong id);
/// <summary>
/// 查询Entity,例如
/// </summary>
/// <para>var rotationEntities=EntitiesService.Query&lt;RotationComponent&gt;</para>
IEntity[] Query<T>() where T : IEntityComponent;
IEntity[] Query<T>();
/// <summary>
/// 查询1个组件
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
T[] QueryComponents<T>() where T : IEntityComponent;
T[] QueryComponents<T>();
/// <summary>
/// 查询2个组件
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="T1"></typeparam>
/// <returns></returns>
ValueTuple<T,T1>[] QueryComponents<T,T1>()where T : IEntityComponent where T1 : IEntityComponent;
ValueTuple<T, T1>[] QueryComponents<T, T1>();
/// <summary>
/// 查询3个组件
/// </summary>
@@ -86,7 +94,7 @@ namespace BITKit.Core.Entites
/// <typeparam name="T1"></typeparam>
/// <typeparam name="T2"></typeparam>
/// <returns></returns>
ValueTuple<T,T1,T2>[] QueryComponents<T,T1,T2>() where T : IEntityComponent where T1 : IEntityComponent where T2 : IEntityComponent;
ValueTuple<T, T1, T2>[] QueryComponents<T, T1, T2>();
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace BITKit
{
public static class FuncExtensions
{
public static IEnumerable<Func<T0,T1>> CastAsFunc<T0,T1>(this Func<T0,T1> self)
{
return self.GetInvocationList().Cast<Func<T0, T1>>();
}
}
}

View File

@@ -0,0 +1,19 @@
using System.Net.Http;
using System.Text;
using System.Threading;
using Cysharp.Threading.Tasks;
using Newtonsoft.Json;
namespace BITKit
{
public static class HttpClientExtensions
{
public static async UniTask<string> PostJsonAsync(this HttpClient self, string requestUrl, object value , CancellationToken cancellationToken=default)
{
var json = JsonConvert.SerializeObject(value);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response =await self.PostAsync(requestUrl, content, cancellationToken);
return await response.Content.ReadAsStringAsync();
}
}
}

View File

@@ -33,6 +33,8 @@ namespace BITKit.Apps
/// </summary>
event Action<string> OnDownloadComplete;
event Action OnDetectedLatestVersion;
/// <summary>
/// 下载最新版本
/// </summary>

View File

@@ -44,6 +44,19 @@ namespace BITKit
return list;
}
public static bool TryGetIndexOf<T>(this IEnumerable<T> self, Func<T, bool> factory, out int index)
{
index = -1;
var enumerable = self as T[] ?? self.ToArray();
for (var i = 0; i < enumerable.Length; i++)
{
var item = enumerable.ElementAt(i);
if (!factory.Invoke(item)) continue;
index = i;
return true;
}
return false;
}
public static bool Contains<T>(IEnumerable<T> a, IEnumerable<T> b)
{
foreach (var x in b)

View File

@@ -0,0 +1,83 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
// ReSharper disable CheckNamespace
namespace BITKit
// ReSharper restore CheckNamespace
{
public record ContextModel
{
public static ContextModel Get(object data)
{
return new ContextModel()
{
StatusCode = 200,
Message = "success",
Data = data
};
}
public static ContextModel Error(string message)
{
return new ContextModel()
{
StatusCode = 500,
Message = message,
Data = false
};
}
public static ContextModel GetFromJson(string json)
{
try
{
var result = new ContextModel();
var jObject = JObject.Parse(json);
if(jObject.TryGetValue("status_code",out var statusCode))
result.StatusCode = statusCode.Value<int>();
if(jObject.TryGetValue("message",out var message))
result.Message = message.Value<string>();
if (jObject.TryGetValue("data", out var data))
result.Data = data;
return JsonConvert.DeserializeObject<ContextModel>(json);
}
catch (Exception e)
{
BIT4Log.Warning(json);
throw;
}
}
public static implicit operator string(ContextModel self)
{
return self.ToString();
}
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
[JsonProperty("status_code")]
public int StatusCode;
[JsonProperty("message")]
public string Message=string.Empty;
[JsonProperty("data")]
public object Data=string.Empty;
[JsonIgnore]
public bool IsSuccess => StatusCode is 200 or 0;
public bool TryAs<T>(out T value)
{
switch (Data)
{
case T t:
value = t;
return true;
case JToken jToken:
value = jToken.ToObject<T>();
return true;
default:
value = default;
return false;
}
}
}
}

View File

@@ -1,34 +0,0 @@
using Newtonsoft.Json;
// ReSharper disable CheckNamespace
namespace BITKit
// ReSharper restore CheckNamespace
{
public record ContextModel
{
public static ContextModel Get(object data)
{
return new ContextModel()
{
code = 200,
message = "success",
data = data
};
}
public static ContextModel Error(object data)
{
return new ContextModel()
{
code = 500,
message = "failed",
data = data
};
}
public static implicit operator string(ContextModel self)
{
return JsonConvert.SerializeObject(self);
}
public int code;
public string message=string.Empty;
public object data=string.Empty;
}
}

View File

@@ -1,6 +1,6 @@
#if UNITY
#else
#if NET5_0_OR_GREATER
using System.ComponentModel.DataAnnotations;
#else
#endif
using System;

View File

@@ -0,0 +1,15 @@
using System;
using System.Net;
using System.Net.Http;
namespace BITKit.Net.Http
{
public interface IHttpListenerService
{
bool IsListening { get; }
int Port { get; set; }
public event Func<HttpListenerRequest,HttpContent> OnRequest;
void Start();
void Stop();
}
}

View File

@@ -0,0 +1,105 @@
using System;
using System.Net;
using System.Net.Http;
using System.Threading;
namespace BITKit.Net.Http
{
public class HttpListenerService:IHttpListenerService
{
public bool IsListening=>_httpListener.IsListening;
public int Port { get; set; }
private readonly HttpListener _httpListener = new();
public event Func<HttpListenerRequest,HttpContent> OnRequest;
private readonly CancellationTokenSource _cancellationTokenSource = new();
private CancellationToken _cancellationToken=>_cancellationTokenSource.Token;
public HttpListenerService()
{
Port = 7001;
}
public HttpListenerService(int port)
{
Port = port;
}
public void Start()
{
if (HttpListener.IsSupported is false)
{
throw new NotImplementedException("HttpListener is not supported this platform");
}
_httpListener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
//_httpListener.Prefixes.Add($"http://localhost:{Port}/");
#if NET5_0_OR_GREATER
_httpListener.Prefixes.Add($"http://localhost:{Port}/");
#else
_httpListener.Prefixes.Add($"http://*:{Port}/");
#endif
Thread thread = new(Process);
thread.Start();
}
public void Stop()
{
_cancellationTokenSource.Cancel();
_httpListener.Stop();
BIT4Log.Log<IHttpListenerService>("Is Trying To Stop");
}
private void Process()
{
_httpListener.Start();
BIT4Log.Log<IHttpListenerService>($"{Port}\tIs Listening");
while (_cancellationToken.IsCancellationRequested is false)
{
var result = _httpListener.BeginGetContext(ListenerCallback, _httpListener);
result.AsyncWaitHandle.WaitOne();
}
BIT4Log.Log<IHttpListenerService>($"{Port}\tStopped");
}
private void ListenerCallback(IAsyncResult result)
{
if (_cancellationToken.IsCancellationRequested) return;
var context = _httpListener.EndGetContext(result);
var request = context.Request;
var response = context.Response;
var output = response.OutputStream;
if (request.RawUrl is "/favicon.ico")
{
output.Close();
response.Close();
return;
}
// 启用CORS
response.Headers.Add("Access-Control-Allow-Origin", "*"); // 允许任何来源访问,生产环境应更具体设置
response.Headers.Add("Access-Control-Allow-Methods", "*"); // 允许的HTTP方法
response.Headers.Add("Access-Control-Allow-Headers", "*"); // 允许的标头
var content = OnRequest?.Invoke(request);
var buffer = StringHelper.GetBytes(ContextModel.Error("没有注册请求事件"));
if (content is not null)
{
#if NET5_0_OR_GREATER
buffer = content!.ReadAsByteArrayAsync(_cancellationToken).Result;
#else
buffer = content!.ReadAsByteArrayAsync().Result;
#endif
}
response.ContentLength64 = buffer.Length;
output.Write(buffer);
output.Close();
response.Close();
}
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Net;
namespace BITKit.Net.LAN
{
public interface ILANBroadcaster
{
int Port { get; set; }
byte[] Buffer { get; set; }
event Action<EndPoint, string> OnReceive;
void StartBroadcast();
void StopBroadcast();
void StartListen();
void StopListen();
}
}

View File

@@ -0,0 +1,108 @@
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace BITKit.Net.LAN
{
/// <summary>
/// 基于UDP的LAN广播
/// </summary>
public class UdpBasedLanBroadcaster : ILANBroadcaster
{
public int Port { get; set; }
public byte[] Buffer { get; set; } = StringHelper.GetBytes("Hello World");
private bool _isBroadcasting;
private bool _isListening;
public UdpBasedLanBroadcaster()
{
}
public event Action<EndPoint, string> OnReceive;
public void StartBroadcast()
{
_isBroadcasting = true;
Thread thread = new(Process)
{
IsBackground = true
};
thread.Start();
BIT4Log.Log<ILANBroadcaster>($"开始广播端口{Port}");
}
public void StopBroadcast()
{
_isBroadcasting = false;
BIT4Log.Log<ILANBroadcaster>($"停止广播端口 {Port}");
}
public void StartListen()
{
_isListening = true;
var thread = new Thread(ReceiveThread)
{
IsBackground = true
};
thread.Start();
BIT4Log.Log<ILANBroadcaster>($"开始监听端口:{Port}");
}
public void StopListen()
{
_isListening = false;
BIT4Log.Log<ILANBroadcaster>($"停止监听端口{Port}");
}
private void Process()
{
var udpClient = new UdpClient(new IPEndPoint(IPAddress.Any, 0));
var endpoint = new IPEndPoint(IPAddress.Broadcast, Port);
//其实 IPAddress.Broadcast 就是 255.255.255.255
//下面代码与上面有相同的作用
//IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("255.255.255.255"), 8080);
try
{
while (_isBroadcasting)
{
udpClient.Send(Buffer, Buffer.Length, endpoint);
Thread.Sleep(1000);
}
}
catch (Exception e)
{
BIT4Log.LogException(e);
}
udpClient.Dispose();
}
private void ReceiveThread()
{
try
{
var udpClient = new UdpClient(new IPEndPoint(IPAddress.Any, Port));
var endpoint = new IPEndPoint(IPAddress.Any, 0);
while (_isListening)
{
var buf = udpClient.Receive(ref endpoint);
var msg = Encoding.Default.GetString(buf);
if (OnReceive is not null)
OnReceive(endpoint, msg);
else
BIT4Log.Log<ILANBroadcaster>($"Receive From {endpoint}:\t{msg}");
Thread.Sleep(500);
}
}
catch (Exception e)
{
BIT4Log.LogException(e);
}
}
}
}

View File

@@ -7,11 +7,11 @@
}
public interface IOptional<T>
{
bool Allow { get; }
T Value { get; }
bool Allow { get; set; }
T Value { get; set; }
}
[System.Serializable]
public record Optional<T> : IOptional<T>
public class Optional<T> : IOptional<T>
{
#if NET5_0_OR_GREATER
bool allow;
@@ -23,8 +23,18 @@
T value;
#endif
public bool Allow { get => allow; set => allow = value;}
public T Value { get => value; set => this.value = value; }
public void SetValueThenAllow(T newValue) => value = newValue;
public T Value
{
get => value;
set=>this.value=value;
}
public void SetValueThenAllow(T newValue)
{
value = newValue;
allow = true;
}
public void Clear()
{
Allow = false;

View File

@@ -1,9 +1,12 @@
namespace BITKit
using System;
namespace BITKit
{
/// <summary>
/// 订阅者,发布者下发任务给支持并优先级最高的订阅者
/// </summary>
/// <typeparam name="T"></typeparam>
[Obsolete]
public interface TaskSubscriber<in T>
{
/// <summary>
@@ -22,6 +25,7 @@
/// 发布接口,向发布者下发任务
/// </summary>
/// <typeparam name="T"></typeparam>
[Obsolete("Use Func Instanced",true)]
public interface TaskPublisher<in T>
{
/// <summary>

View File

@@ -1,4 +1,5 @@
using System;
// ReSharper disable UnassignedGetOnlyAutoProperty
namespace BITKit.UX
{
@@ -44,7 +45,7 @@ namespace BITKit.UX
}
public abstract class UXPanelImplement:IUXPanel
{
private IUXPanel _iuxPanelImplementation1;
protected virtual IUXPanel _iuxPanelImplementation1 { get; }
protected abstract IUXPanel _iuxPanelImplementation { get; }
public bool IsAnimate => _iuxPanelImplementation.IsAnimate;

View File

@@ -11,6 +11,7 @@ namespace BITKit
public const string Status = "Status";
public const string State = "State";
public const string Settings = "Settings";
public const string Services = "Services";
public const string AudioClip = "AudioClip";
public const string AudioSource = "AudioSource";
public const string Paths = "Paths";

View File

@@ -4,6 +4,7 @@
{
string Get();
string Value => Get();
string Replace(string value) => Get().Replace("{x}",value);
}
public interface IReference<T>
@@ -37,9 +38,12 @@
{
this.value = value;
}
#if UNITY_EDITOR
[UnityEngine.TextArea]
#endif
public string value;
public override string Get() => value;
public override string ToString() => value;
}
[System.Serializable]

View File

@@ -5,17 +5,12 @@ namespace BITKit
{
public class ValidHandle
{
public ValidHandle() { Init(); }
public ValidHandle() {}
public ValidHandle(Action<bool> boolDelegate)
{
AddListener(boolDelegate);
Init();
EventOnEnableChanged?.Invoke(enableHandle);
}
void Init()
{
AddListener(OnInoke);
}
public static implicit operator bool(ValidHandle validHandle)
{
return validHandle.enableHandle;
@@ -24,8 +19,6 @@ namespace BITKit
public bool Allow => this;
private bool enableHandle;
private int enableElementCount;
private int disableElementCount;
private readonly List<object> objs = new List<object>();
private readonly List<object> disableObjs = new List<object>();
private bool tempEnable;
@@ -43,7 +36,7 @@ namespace BITKit
}
CheckEnable();
}
protected virtual void CheckEnable()
protected void CheckEnable()
{
tempEnable = objs.Count > 0 && disableObjs.Count == 0;
if (tempEnable != enableHandle)
@@ -51,13 +44,8 @@ namespace BITKit
enableHandle = tempEnable;
if (EventOnEnableChanged is not null)
EventOnEnableChanged.Invoke(enableHandle);
OnEnable(enableHandle);
}
enableElementCount = objs.Count;
disableElementCount = disableObjs.Count;
}
protected virtual void OnEnable(bool enable) { }
public virtual void RemoveElement(object obj)
{
if (objs.Contains(obj))
@@ -93,7 +81,7 @@ namespace BITKit
}
CheckEnable();
}
public virtual void RemoveDisableElements(object obj)
public void RemoveDisableElements(object obj)
{
if (disableObjs.Contains(obj))
{
@@ -104,7 +92,7 @@ namespace BITKit
}
CheckEnable();
}
public virtual void SetElements(object obj, bool add = true)
public void SetElements(object obj, bool add = true)
{
if (add)
{
@@ -126,29 +114,33 @@ namespace BITKit
RemoveDisableElements(obj);
}
}
public virtual void Invoke()
public void Invoke()
{
bool enable = disableObjs.Count == 0 && objs.Count > 0;
EventOnEnableChanged.Invoke(enable);
var enable = disableObjs.Count == 0 && objs.Count > 0;
EventOnEnableChanged?.Invoke(enable);
}
public virtual void Invoke(bool value)
public void Invoke(bool value)
{
EventOnEnableChanged.Invoke(value);
EventOnEnableChanged?.Invoke(value);
}
public virtual void OnInoke(bool value)
{
}
public virtual void AddListener(Action<bool> action)
public void AddListener(Action<bool> action)
{
EventOnEnableChanged+= action;
}
public virtual void RemoveListener(Action<bool> action)
public void RemoveListener(Action<bool> action)
{
if(EventOnEnableChanged is not null && action is not null)
{
EventOnEnableChanged -= action;
}
}
public void Clear()
{
objs.Clear();
disableObjs.Clear();
Invoke();
}
}
}

View File

@@ -18,7 +18,6 @@ namespace BITKit
[BITCommand]
public static void Set(string key, string value)
{
Data.Set(key, value);
if (Guid.TryParse(value, out var guidResult))
{
Data.Set(key, guidResult);
@@ -35,6 +34,10 @@ namespace BITKit
{
Data.Set(key, intResult);
}
else
{
Data.Set(key, value);
}
}
[BITCommand]
public static void SetContainer(string key, string typeName, string json)

View File

@@ -32,6 +32,12 @@ namespace BITKit
return GetPath(paths);
}
public static void EnsureDirectoryCreated(string path)
{
path = Path.GetDirectoryName(path);
if (Directory.Exists(path) is true) return;
if (path != null) Directory.CreateDirectory(path);
}
public static string GetFilePath(params string[] paths)
{