This commit is contained in:
CortexCore
2025-02-24 23:02:43 +08:00
parent 41715e4413
commit 8261a458e2
105 changed files with 2934 additions and 696 deletions

View File

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 66cea81a8a712d348aded0734f12d2ef
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

31
Src/Core/BITKit.asmdef Normal file
View File

@@ -0,0 +1,31 @@
{
"name": "BITKit",
"rootNamespace": "",
"references": [
"GUID:75469ad4d38634e559750d17036d5f7c",
"GUID:66d2ae14764cc7d49aad4b16930747c0",
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
"GUID:e6234d6c1f7bf4e4db20eddc411c00b8",
"GUID:15fc0a57446b3144c949da3e2b9737a9",
"GUID:f51ebe6a0ceec4240a699833d6309b23",
"GUID:4307f53044263cf4b835bd812fc161a4",
"GUID:df380645f10b7bc4b97d4f5eb6303d95",
"GUID:d8b63aba1907145bea998dd612889d6b",
"GUID:d525ad6bd40672747bde77962f1c401e",
"GUID:e34a5702dd353724aa315fb8011f08c3",
"GUID:4988cf9794f41d64c884876ab6574b89",
"GUID:e0cd26848372d4e5c891c569017e11f1",
"GUID:517785bb4600a5140b47eac5fa49b8fc",
"GUID:a11ff146d38b27a44af87b4b4d9c4ecb",
"GUID:8c1b5e158961445498f8a66188fbb2e3"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": true,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 14fe60d984bf9f84eac55c6ea033a8f4
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -2,13 +2,11 @@ using System.Dynamic;
namespace BITKit.Entities
{
public interface IdComponent
public class IdComponent
{
ulong Id { get; set; }
}
public interface IdComponent_String
{
string DbId { get; }
public int Id { get; set; }
public string Name { get; set; }
public string Group { get; set; }
}
}

View File

@@ -0,0 +1,10 @@
using System.Collections;
using System.Collections.Generic;
namespace BITKit.Entities
{
public class LocalPlayerComponent
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 46172bbdf3a15d4458646b3e80b6702c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -5,28 +5,42 @@ using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.AccessControl;
using System.Threading;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace BITKit.Entities
{
public class EntitiesService:IEntitiesService
public class EntitiesService:IEntitiesService,IDisposable
{
private readonly ConcurrentDictionary<int, IEntity> _entities = new();
private readonly ConcurrentDictionary<Type, IEntity[]> _queryCache = new();
private readonly ConcurrentDictionary<(Type,Type), IEntity[]> _query2ComponentsCache = new();
private readonly ConcurrentDictionary<(Type,Type,Type), IEntity[]> _query3ComponentsCache = new();
private readonly ILogger<EntitiesService> _logger;
private static int _count;
public EntitiesService()
{
_count++;
}
public EntitiesService(ILogger<EntitiesService> logger)
{
_count++;
_logger = logger;
}
private static readonly ConcurrentDictionary<int, IEntity> Entities = new();
public event Action<IEntity> OnAdd;
public event Action<IEntity> OnRemove;
public IEntity[] Entities => _entities.Values.ToArray();
IEntity[] IEntitiesService.Entities => Entities.Values.ToArray();
public bool Register(IEntity entity)
{
if (!_entities.TryAdd(entity.Id, entity)) return false;
if (!Entities.TryAdd(entity.Id, entity)) return false;
OnAdd?.Invoke(entity);
return true;
}
public bool UnRegister(IEntity entity)
{
if (!_entities.TryRemove(entity.Id, out _)) return false;
if (!Entities.TryRemove(entity.Id, out _)) return false;
OnRemove?.Invoke(entity);
return true;
}
@@ -34,17 +48,17 @@ namespace BITKit.Entities
private readonly CancellationTokenSource _cancellationTokenSource = new();
public IEntity Get(int id)
{
return _entities[id];
return Entities[id];
}
public bool TryGetEntity(int id, out IEntity entity)
{
return _entities.TryGetValue(id, out entity);
return Entities.TryGetValue(id, out entity);
}
public IEntity GetOrAdd(int id, Func<int, IEntity> factory)
{
return _entities.GetOrAdd(id, factory);
return Entities.GetOrAdd(id, factory);
}
public IEntity[] Query<T>()
@@ -54,16 +68,36 @@ namespace BITKit.Entities
public T[] QueryComponents<T>()
{
throw new NotImplementedException();
var list = new List<T>();
foreach (var entity in Entities.Values)
{
if (entity.ServiceProvider.GetService<T>() is { } t1)
{
list.Add(t1);
}
}
return list.ToArray();
// return _queryCache.GetOrAdd(typeof(T), type =>
// {
// return _entities.Values.Where(entity => entity.TryGetComponent(out T component)).ToArray();
// }).Cast<T>().ToArray();
}
public (T, T1)[] QueryComponents<T, T1>()
{
throw new NotImplementedException();
// List<(T, T1)> list = new();
var list = new List<(T, T1)>();
foreach (var entity in Entities.Values)
{
if (entity.ServiceProvider.GetService<T>() is { } t1 &&
entity.ServiceProvider.GetService<T1>() is { } t2)
{
list.Add((t1, t2));
}
}
return list.ToArray();
// List<(T, T1)> list = new();
// foreach (var entity in _entities.Values)
// {
// if (entity.TryGetComponent(out T t) && entity.TryGetComponent(out T1 t1))
@@ -73,7 +107,18 @@ namespace BITKit.Entities
}
public (T, T1, T2)[] QueryComponents<T, T1, T2>()
{
throw new NotImplementedException();
var list = new List<(T, T1, T2)>();
foreach (var entity in Entities.Values)
{
if (entity.ServiceProvider.GetService<T>() is { } t1 &&
entity.ServiceProvider.GetService<T1>() is { } t2 &&
entity.ServiceProvider.GetService<T2>() is { } t3)
{
list.Add((t1, t2, t3));
}
}
return list.ToArray();
// List<(T, T1, T2)> list = new();
// foreach (var entity in _entities.Values)
// {
@@ -85,7 +130,19 @@ namespace BITKit.Entities
public (T, T1, T2, T3)[] QueryComponents<T, T1, T2, T3>()
{
throw new NotImplementedException();
var list = new List<(T, T1, T2, T3)>();
foreach (var entity in Entities.Values)
{
if (entity.ServiceProvider.GetService<T>() is { } t1 &&
entity.ServiceProvider.GetService<T1>() is { } t2 &&
entity.ServiceProvider.GetService<T2>() is { } t3 &&
entity.ServiceProvider.GetService<T3>() is { } t4)
{
list.Add((t1, t2, t3, t4));
}
}
return list.ToArray();
// List<(T, T1, T2, T3)> list = new();
// foreach (var entity in _entities.Values)
// {
@@ -97,7 +154,20 @@ namespace BITKit.Entities
public (T, T1, T2, T3, T4)[] QueryComponents<T, T1, T2, T3, T4>()
{
throw new NotImplementedException();
var list = new List<(T, T1, T2, T3, T4)>();
foreach (var entity in Entities.Values)
{
if (entity.ServiceProvider.GetService<T>() is { } t1 &&
entity.ServiceProvider.GetService<T1>() is { } t2 &&
entity.ServiceProvider.GetService<T2>() is { } t3 &&
entity.ServiceProvider.GetService<T3>() is { } t4 &&
entity.ServiceProvider.GetService<T4>() is { } t5)
{
list.Add((t1, t2, t3, t4, t5));
}
}
return list.ToArray();
// List<(T, T1, T2, T3, T4)> list = new();
// foreach (var entity in _entities.Values)
// {
@@ -109,7 +179,21 @@ namespace BITKit.Entities
public (T, T1, T2, T3, T4, T5)[] QueryComponents<T, T1, T2, T3, T4, T5>()
{
throw new NotImplementedException();
var list = new List<(T, T1, T2, T3, T4, T5)>();
foreach (var entity in Entities.Values)
{
if (entity.ServiceProvider.GetService<T>() is { } t1 &&
entity.ServiceProvider.GetService<T1>() is { } t2 &&
entity.ServiceProvider.GetService<T2>() is { } t3 &&
entity.ServiceProvider.GetService<T3>() is { } t4 &&
entity.ServiceProvider.GetService<T4>() is { } t5 &&
entity.ServiceProvider.GetService<T5>() is { } t6)
{
list.Add((t1, t2, t3, t4, t5, t6));
}
}
return list.ToArray();
// List<(T, T1, T2, T3, T4, T5)> list = new();
// foreach (var entity in _entities.Values)
// {
@@ -121,7 +205,22 @@ namespace BITKit.Entities
public (T, T1, T2, T3, T4, T5, T6)[] QueryComponents<T, T1, T2, T3, T4, T5, T6>()
{
throw new NotImplementedException();
var list = new List<(T, T1, T2, T3, T4, T5, T6)>();
foreach (var entity in Entities.Values)
{
if (entity.ServiceProvider.GetService<T>() is { } t1 &&
entity.ServiceProvider.GetService<T1>() is { } t2 &&
entity.ServiceProvider.GetService<T2>() is { } t3 &&
entity.ServiceProvider.GetService<T3>() is { } t4 &&
entity.ServiceProvider.GetService<T4>() is { } t5 &&
entity.ServiceProvider.GetService<T5>() is { } t6 &&
entity.ServiceProvider.GetService<T6>() is { } t7)
{
list.Add((t1, t2, t3, t4, t5, t6, t7));
}
}
return list.ToArray();
// List<(T, T1, T2, T3, T4, T5, T6)> list = new();
// foreach (var entity in _entities.Values)
// {
@@ -131,10 +230,38 @@ namespace BITKit.Entities
// return list.ToArray();
}
public ValueTuple<T, T1, T2, T3, T4, T5, T6, TRest>[] QueryComponents<T, T1, T2, T3, T4, T5, T6, TRest>() where TRest : struct
public ValueTuple<T, T1, T2, T3, T4, T5, T6, TRest>[] QueryComponents<T, T1, T2, T3, T4, T5, T6, TRest>()
where TRest : struct
{
throw new NotImplementedException();
// throw new NotImplementedException();
var list = new List<ValueTuple<T, T1, T2, T3, T4, T5, T6, TRest>>();
foreach (var entity in Entities.Values)
{
if (entity.ServiceProvider.GetService<T>() is { } t1 &&
entity.ServiceProvider.GetService<T1>() is { } t2 &&
entity.ServiceProvider.GetService<T2>() is { } t3 &&
entity.ServiceProvider.GetService<T3>() is { } t4 &&
entity.ServiceProvider.GetService<T4>() is { } t5 &&
entity.ServiceProvider.GetService<T5>() is { } t6 &&
entity.ServiceProvider.GetService<T6>() is { } t7 &&
entity.ServiceProvider.GetService<TRest>() is { } t8)
{
list.Add(new ValueTuple<T, T1, T2, T3, T4, T5, T6, TRest>(t1, t2, t3, t4, t5, t6, t7, t8));
}
}
return list.ToArray();
}
public void Dispose()
{
_count--;
if (_count <= 0)
{
Entities.Clear();
}
_logger.LogInformation($"已释放,还剩{_count}个实例");
_cancellationTokenSource?.Dispose();
}
}
}

View File

@@ -24,7 +24,6 @@ namespace BITKit.Entities
/// </summary>
public interface IEntitiesService
{
/// <summary>
/// 当添加Entity时
/// </summary>

8
Src/Core/Hotkey.meta Normal file
View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ad41977c90d905e4fa0efdcfd3260ccc
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,14 @@
{
"name": "BITKit.Hotkey",
"rootNamespace": "",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": true
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3abaaefa7af558d44ba20cea1c43d602
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace BITKit.UX.Hotkey
{
public interface IHotkeyProvider
{
string Name { get; }
string Description { get; }
object Data { get; }
bool Enabled { get; }
Action OnPerform { get; }
float HoldDuration => 0;
}
public struct HotkeyProvider : IHotkeyProvider
{
public string Name { get; set; }
public string Description { get; set; }
public object Data { get; set; }
public bool Enabled { get; set; }
public Action OnPerform { get; set; }
public float HoldDuration { get; set; }
}
public interface IHotkeyCollection
{
IEnumerable<IHotkeyProvider> Hotkeys { get; }
void Register(IHotkeyProvider hotkey);
void UnRegister(IHotkeyProvider hotkey);
}
public class HotkeyCollection:IHotkeyCollection
{
private readonly HashSet<IHotkeyProvider> _hotkeys = new();
public IEnumerable<IHotkeyProvider> Hotkeys => _hotkeys;
public void Register(IHotkeyProvider hotkey)
{
_hotkeys.Add(hotkey);
}
public void UnRegister(IHotkeyProvider hotkey)
{
_hotkeys.Remove(hotkey);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0ad36bc56dd5406418bf8ea67f4bc010
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -53,7 +53,13 @@ namespace BITKit
public interface IScriptableItemProperty
{
}
/// <summary>
/// 控制器(分)类
/// </summary>
public interface IScriptableControllerClass
{
}
/// <summary>
/// 基础物品
/// </summary>
@@ -88,6 +94,11 @@ namespace BITKit
/// 属性
/// </summary>
IReadOnlyDictionary<Type, IScriptableItemProperty> Properties { get; }
/// <summary>
/// 控制器类
/// </summary>
IScriptableControllerClass ControllerClass { get; }
/// <summary>
/// 价值

View File

@@ -14,6 +14,7 @@ using BITKit.IO;
using BITKit.UX;
using Cysharp.Threading.Tasks;
using Microsoft.CSharp;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace BITKit.Mod
@@ -133,17 +134,26 @@ namespace BITKit.Mod
var list=new List<ModPackage>();
var path = Path.Combine(Environment.CurrentDirectory, "Mods");
var dir = new DirectoryInfo(path);
dir.Create();
foreach (var x in dir.GetDirectories())
try
{
var file = Path.Combine(x.FullName,ModPackage.DefaultFileName);
if(File.Exists(file) is false)continue;
var package = JsonConvert.DeserializeObject<ModPackage>(await File.ReadAllTextAsync(file))!;
package.PackagePath = file;
package.WorkDirectory = x.FullName;
list.Add(package);
var dir = new DirectoryInfo(path);
dir.Create();
foreach (var x in dir.GetDirectories())
{
var file = Path.Combine(x.FullName,ModPackage.DefaultFileName);
if(File.Exists(file) is false)continue;
var package = JsonConvert.DeserializeObject<ModPackage>(await File.ReadAllTextAsync(file))!;
package.PackagePath = file;
package.WorkDirectory = x.FullName;
list.Add(package);
}
}
catch (Exception e)
{
BIT4Log.LogException(e);
}
return list.ToArray();
}
@@ -200,19 +210,16 @@ namespace BITKit.Mod
private static CancellationTokenSource _CancellationTokenSource;
private static readonly ConcurrentDictionary<string,IMod> _InstalledMods=new();
public static async UniTask Initialize()
public static async UniTask Initialize(ILogger logger=null)
{
BIT4Log.Log<ModService>("Mod服务已启动");
logger?.LogInformation("Mod服务已启动");
_CancellationTokenSource = new CancellationTokenSource();
try
{
try
{
var modPath = Path.Combine(Environment.CurrentDirectory, "Mods\\");
var modPath = Path.Combine(Environment.CurrentDirectory, @"Mods\");
PathHelper.EnsureDirectoryCreated(modPath);
var directoryInfo = new DirectoryInfo(modPath);
foreach (var fileInfo in directoryInfo.GetFiles())
@@ -238,18 +245,16 @@ namespace BITKit.Mod
}
catch (Exception e)
{
BIT4Log.Warning<ModService>("自动加载Mod失败");
logger?.LogWarning("自动加载Mod失败");
BIT4Log.LogException(e);
}
}
catch (Exception e)
{
logger?.LogWarning("Mod服务遇到了错误,已停止");
BIT4Log.LogException(e);
BIT4Log.Warning<ModService>("Mod服务遇到了错误,已停止");
}
}
public static void Dispose()
@@ -336,7 +341,7 @@ namespace BITKit.Mod
}
var fileInfo = new FileInfo(path);
var fileInfo = new FileInfo(path);
switch (fileInfo.Extension)
{
case ".dll":
@@ -360,6 +365,10 @@ namespace BITKit.Mod
}
public static async UniTask Load(IMod mod)
{
await IsBusy;
using var _ = IsBusy.GetHandle();
mod.OnInitialize();
OnModLoad?.Invoke(mod);
BIT4Log.Log<ModService>($"加载Mod:{mod.GetType().FullName}");
@@ -381,7 +390,7 @@ namespace BITKit.Mod
BIT4Log.Log<ModService>($"卸载Mod:{mod.GetType().FullName}");
}
public static async void Install(IMod mod)
public static async UniTask Install(IMod mod)
{
await IsBusy;
@@ -404,11 +413,12 @@ namespace BITKit.Mod
mod.OnInitialized();
OnModLoaded?.Invoke(mod);
}
public static void UnInstall(IMod mod)
public static async UniTask UnInstall(IMod mod)
{
await IsBusy;
using var _ = IsBusy.GetHandle();
if(_InstalledMods.ContainsKey(mod.PackageName) is false) return;
_InstalledMods.TryRemove(mod.PackageName);
Mods = _InstalledMods.Values.ToArray();

View File

@@ -8,7 +8,20 @@ namespace BITKit.Mod
public partial class ModService
{
public static Func<string, UniTask<object>> LoadAssetAsyncFactory;
public static Func<string[], UniTask<IReadOnlyList<object>>> LoadAssetsAsyncFactory;
public static async UniTask<IReadOnlyList<T>> LoadAssets<T>(params string[] tags)
{
var list = new List<T>();
foreach (var func in LoadAssetsAsyncFactory.CastAsFunc())
{
foreach (var obj in await func.Invoke(tags))
{
list.Add((T)obj);
}
}
return list;
}
public static async UniTask<T> LoadAsset<T>(string location) where T : class
{
if (LoadAssetAsyncFactory is null)

View File

@@ -272,6 +272,14 @@ namespace BITKit
using var ms = new MemoryStream();
using var writer = new BinaryWriter(ms);
foreach (var parameterInfo in methodInfo.GetParameters())
{
if (parameterInfo.IsOut)
{
codeBuilder.AppendLine($"{parameterInfo.Name} = default;");
}
}
codeBuilder.AppendLine(" using var ms = new MemoryStream();");
codeBuilder.AppendLine(" using var writer = new BinaryWriter(ms);");
codeBuilder.AppendLine(" writer.Write((byte)NetCommandType.Rpc);");
@@ -466,6 +474,7 @@ namespace BITKit
{
options= options.AddReferences(referencedAssembly);
}
options = options.AddReferences(typeof(BITApp).Assembly);
var assembly = BITSharp.Compile(code, options);

View File

@@ -110,6 +110,11 @@ namespace BITKit
{
codeBuilder.AppendLine(GenerateMethod(method));
}
foreach (var eventInfo in type.GetEvents())
{
codeBuilder.AppendLine(GenerateEvent(eventInfo));
}
codeBuilder.AppendLine(AfterGenerate(type));
@@ -136,25 +141,32 @@ namespace BITKit
public virtual string GenerateMethod(MethodInfo methodInfo)
{
var codeBuilder = new StringBuilder();
HashSet<MethodInfo> propertyMethods = new();
HashSet<MethodInfo> ignoreMethods = new();
foreach (var eventInfo in methodInfo.DeclaringType!.GetEvents())
{
ignoreMethods.Add(eventInfo.AddMethod);
ignoreMethods.Add(eventInfo.RemoveMethod);
}
foreach (var propertyInfo in methodInfo.DeclaringType!.GetProperties())
{
if (propertyInfo.GetMethod is not null)
{
propertyMethods.Add(propertyInfo.GetMethod);
ignoreMethods.Add(propertyInfo.GetMethod);
}
if (propertyInfo.SetMethod is not null)
{
propertyMethods.Add(propertyInfo.SetMethod);
ignoreMethods.Add(propertyInfo.SetMethod);
}
}
if(propertyMethods.Contains(methodInfo))return string.Empty;
if(ignoreMethods.Contains(methodInfo))return string.Empty;
string methodName = methodInfo.Name;
string parameters = string.Join(", ", methodInfo.GetParameters()
.Select(p => $"{CSharpName(p.ParameterType)} {p.Name}"));
.Select(p => $"{(p.IsOut?"out":string.Empty)} {CSharpName(p.IsOut?p.ParameterType.GetElementType():p.ParameterType)} {p.Name}"));
var isAwaitable = methodInfo.ReturnType.GetMethod(nameof(Task.GetAwaiter)) != null;
@@ -194,7 +206,17 @@ namespace BITKit
public virtual string GenerateMethodContext(MethodInfo methodInfo)
{
return methodInfo.ReturnType == typeof(void) ? string.Empty : $"return default;";
var codeBuilder = new StringBuilder();
foreach (var parameterInfo in methodInfo.GetParameters())
{
if (parameterInfo.IsOut)
{
codeBuilder.AppendLine($"{parameterInfo.Name} = default;");
}
}
codeBuilder.AppendLine(methodInfo.ReturnType == typeof(void) ? string.Empty : $"return default;");
return codeBuilder.ToString();
}
public virtual string GenerateField(FieldInfo fieldInfo)
@@ -209,7 +231,7 @@ namespace BITKit
public virtual string GenerateEvent(EventInfo eventInfo)
{
throw new NotImplementedException();
return $"public event {CSharpName(eventInfo.EventHandlerType)} {eventInfo.Name};";
}
}
#if UNITY_5_3_OR_NEWER
@@ -257,7 +279,6 @@ namespace BITKit
{
result.Add(fieldInfo.FieldType.Assembly);
}
foreach (var propertyInfo in type.GetProperties())
{
result.Add(propertyInfo.PropertyType.Assembly);
@@ -269,6 +290,10 @@ namespace BITKit
{
result.Add(argument.Assembly);
}
foreach (var parameterInfo in methodInfo.GetParameters())
{
result.Add(parameterInfo.ParameterType.Assembly);
}
}
return result;
}
@@ -295,7 +320,24 @@ namespace BITKit
using var ms = new MemoryStream();
var result = script.GetCompilation().Emit(ms);
if (!result.Success) throw new Exception(string.Join("\n",result.Diagnostics));
if (!result.Success)
{
var report = new StringBuilder();
report.AppendLine(code);
foreach (var reference in script.GetCompilation().References)
{
report.AppendLine("Assembly referenced:" + reference.Display);
}
foreach (var diagnostic in result.Diagnostics)
{
report.AppendLine(diagnostic.ToString());
}
throw new Exception(report.ToString());
}
ms.Seek(0, SeekOrigin.Begin);
var assembly = Assembly.Load(ms.ToArray()); // 加载程序集

View File

@@ -25,8 +25,8 @@ namespace BITKit.StateMachine
public bool Enabled { get; set; } = true;
public T CurrentState { get;private set; }
public T NextOrCurrentState => _nextTargetState.IfNotAllow(CurrentState);
private T _nextState;
public event Action<T, T> OnStateChanging;
public event Func<T, T, UniTask> OnStateChangeAsync;
public event Action<T, T> OnStateChanged;
public event Action<T> OnStateRegistered;
public IReadOnlyDictionary<int, T> Dictionary => _dictionary;
@@ -53,21 +53,18 @@ namespace BITKit.StateMachine
{
if (CurrentState is null) return;
using var _ = IsBusy.GetHandle();
await CurrentState.OnStateUpdateAsync(deltaTime);
CurrentState.OnStateUpdate(deltaTime);
await CurrentState.OnStateUpdateAsync(deltaTime);
}
public async void DisposeState()
{
await IsBusy;
if(_cancellationTokenSource.IsCancellationRequested)return;
if (_cancellationTokenSource.IsCancellationRequested) return;
if (CurrentState is null) return;
using var _ = IsBusy.GetHandle();
if (CurrentState is not null)
{
CurrentState.Enabled = false;
}
CurrentState.Enabled = false;
await CurrentState.OnStateExitAsync(CurrentState, null);
CurrentState.OnStateExit(CurrentState, null);
CurrentState = null;
@@ -108,10 +105,15 @@ namespace BITKit.StateMachine
}
_nextTargetState.SetValueThenAllow(nextState);
await IsBusy;
if(CurrentState==nextState)return;
if(_cancellationTokenSource.IsCancellationRequested)return;
using var _ = IsBusy.GetHandle();
OnStateChanging?.Invoke(CurrentState,nextState);
if (_dictionary.TryAdd(nextState.Identifier, nextState))
await OnStateChangeAsync.UniTaskFunc(CurrentState,nextState);
if (nextState is not null && _dictionary.TryAdd(nextState.Identifier, nextState))
{
await nextState.InitializeAsync();
if(_cancellationTokenSource.IsCancellationRequested)return;
@@ -125,6 +127,11 @@ namespace BITKit.StateMachine
CurrentState.OnStateExit(CurrentState,nextState);
}
if (_nextTargetState.Allow && _nextTargetState.Value != nextState)
{
return;
}
var tempState = CurrentState;
CurrentState = _nextTargetState.Value;
_nextTargetState.Clear();

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
@@ -44,11 +45,16 @@ namespace BITKit.StateMachine
UniTask OnStateExitAsync(IState old, IState newState);
}
public interface IStateMachine<T> where T:IState
public interface IMicroStateMachine<T>
{
T CurrentState { get; }
event Action<T, T> OnStateChanged;
T TransitionState<TState>() where TState : T;
T TransitionState(T state);
}
public interface IStateMachine<T>:IMicroStateMachine<T> where T:IState
{
bool Enabled { get; set; }
T CurrentState { get; }
event Action<T,T> OnStateChanged;
event Action<T> OnStateRegistered;
event Action<T> OnStateUnRegistered;
@@ -56,13 +62,72 @@ namespace BITKit.StateMachine
void Initialize();
void UpdateState(float deltaTime);
void DisposeState();
T TransitionState<TState>() where TState : T;
T TransitionState(T state);
void Register(T newState) => throw new NotImplementedException("未实现的接口");
void UnRegister(T newState) => throw new NotImplementedException("未实现的接口");
void InvokeOnStateRegistered(T state){}
void InvokeOnStateUnRegistered(T state){}
}
public class MicroStateMachine<T> : IMicroStateMachine<T>
{
public T CurrentState { get; private set; }
public event Action<T, T> OnStateChanged;
private readonly ConcurrentDictionary<Type,T> _stateDictionary=new();
public T TransitionState<TState>() where TState : T
{
var state = _stateDictionary.GetOrAdd(typeof(TState), Activator.CreateInstance<TState>());
return TransitionState(state);
}
public T TransitionState(T state)
{
_stateDictionary.TryAdd(state.GetType(), state);
if (Equals(state, CurrentState)) return default;
var currentState = CurrentState;
CurrentState = state;
OnStateChanged?.Invoke(currentState, state);
return state;
}
}
public abstract class StateAsync:IStateAsync
{
public virtual bool Enabled { get; set; }
public virtual void Initialize()
{
}
public virtual void OnStateEntry(IState old)
{
}
public virtual void OnStateUpdate(float deltaTime)
{
}
public virtual void OnStateExit(IState old, IState newState)
{
}
public virtual int Identifier { get; set; }
public virtual UniTask InitializeAsync()
{
return UniTask.CompletedTask;
}
public virtual UniTask OnStateEntryAsync(IState old)
{ return UniTask.CompletedTask;
}
public virtual UniTask OnStateUpdateAsync(float deltaTime)
{ return UniTask.CompletedTask;
}
public virtual UniTask OnStateExitAsync(IState old, IState newState)
{ return UniTask.CompletedTask;
}
}
public static class StateMachineUtils
{
public static void Register<T>(this IStateMachine<T> stateMachine, T newState) where T : IState

View File

@@ -30,6 +30,7 @@ namespace BITKit.UX
/// 该面板是否启用玩家输入
/// </summary>
bool AllowInput { get; }
object Root { get; }
/// <summary>
/// 事件回调,当面板被打开时触发
/// </summary>
@@ -43,6 +44,8 @@ namespace BITKit.UX
event Func<UniTask> OnExitAsync;
event Action OnExitCompleted;
public event Action OnInitiated;
public event Func<UniTask> OnInitiatedAsync;
void OnTick(float deltaTime);
}
}

View File

@@ -1,5 +1,6 @@
using System;
using Cysharp.Threading.Tasks;
using Unity.Mathematics;
namespace BITKit.UX
{
@@ -52,6 +53,13 @@ namespace BITKit.UX
/// 面板改变回调
/// </summary>
public event Action<IUXPanel, IUXPanel> OnPanelChanged;
/// <summary>
/// 获取可交互的元素
/// </summary>
/// <param name="position"></param>
/// <param name="obj"></param>
/// <returns></returns>
public bool TryPick(float2 position, out object obj);
}
}

View File

@@ -10,7 +10,7 @@ namespace BITKit.WorldNode
/// </summary>
public interface IWorldNodeService
{
public IReadOnlyDictionary<int, IWorldNode> WorldNodes { get; }
public IReadOnlyDictionary<int, HashSet<IWorldNode>> WorldNodes { get; }
public void RegisterNode(IWorldNode node);
public event Action<IWorldNode> OnNodeRegistered;
}
@@ -21,12 +21,12 @@ namespace BITKit.WorldNode
public class WorldNodeService : IWorldNodeService,IDisposable
{
public static event Action<IWorldNode> OnNodeRegistered;
IReadOnlyDictionary<int, IWorldNode> IWorldNodeService.WorldNodes => WorldNodes;
private static readonly ConcurrentDictionary<int, IWorldNode> WorldNodes = new();
IReadOnlyDictionary<int, HashSet<IWorldNode>> IWorldNodeService.WorldNodes => WorldNodes;
private static readonly ConcurrentDictionary<int, HashSet<IWorldNode>> WorldNodes = new();
public void RegisterNode(IWorldNode node)
{
OnNodeRegistered?.Invoke(node);
WorldNodes.TryAdd(node.Id, node);
WorldNodes.GetOrCreate(node.Id).Add(node);
}
event Action<IWorldNode> IWorldNodeService.OnNodeRegistered
{

View File

@@ -0,0 +1,39 @@
#if UNITY_5_3_OR_NEWER
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace BITKit.WorldNode
{
public sealed class UnityNode : MonoBehaviour,IWorldNode
{
[SerializeReference, SubclassSelector] private IWorldNodeService worldNodeService = new WorldNodeService();
[SerializeReference, SubclassSelector] private IWorldNode worldNode;
public int Id { get; set; }
public IWorldNode WorldNode => worldNode;
public object WorldObject
{
get => gameObject;
set=>throw new InvalidOperationException("Cannot set WorldObject");
}
private void Start()
{
if (worldNode is null)
{
Debug.LogWarning("WorldNode is null");
return;
}
Id = gameObject.GetInstanceID();
worldNode.Id = Id;
worldNode.WorldObject = gameObject;
worldNode.Initialize();
worldNodeService.RegisterNode(worldNode);
Destroy(this);
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 054d7fc7589c04d4a8412a6f82b32d6c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -20,17 +20,24 @@ namespace BITKit.WorldNode
[SerializeReference,SubclassSelector]
#endif
private IReference description;
#if UNITY_5_3_OR_NEWER
public void Initialize()
{
Name = name?.Value;
Description = description?.Value;
}
#endif
public int Id { get; set; }
public object WorldObject { get; set; }
public string Name => name?.Value;
public string Description => description?.Value;
public string Name { get; set; }
public string Description { get; set; }
}
public sealed class WorldInfoNodeService : IDisposable
{
public IReadOnlyDictionary<int, WorldInfoNode> WorldInfoNodes => _infoNodes;
public IReadOnlyDictionary<int, WorldInfoNode> WorldInfoNodes => InfoNodes;
private readonly IWorldNodeService _worldNodeService;
private readonly ConcurrentDictionary<int, WorldInfoNode> _infoNodes = new();
private static readonly ConcurrentDictionary<int, WorldInfoNode> InfoNodes = new();
public WorldInfoNodeService(IWorldNodeService worldNodeService)
{
@@ -42,12 +49,12 @@ namespace BITKit.WorldNode
private void OnNodeRegistered(IWorldNode obj)
{
if (obj is not WorldInfoNode infoNode) return;
_infoNodes.TryAdd(obj.Id, infoNode);
InfoNodes.TryAdd(obj.Id, infoNode);
}
public void Dispose()
{
_infoNodes.Clear();
InfoNodes.Clear();
}
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace BITKit.WorldNode
{
[Serializable]
public struct WorldInfoNpcStartNode:IWorldNode
{
public string Address;
public int Id { get; set; }
public object WorldObject { get; set; }
public void Initialize()
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f2fba06a66e155a4580df30630f030fc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -14,6 +14,22 @@ namespace BITKit
}
public class ValueWrapper<T> : IWrapper<T>
{
public ValueWrapper()
{
var type = typeof(T);
if (type == typeof(string))
{
_value = string.Empty.As<T>();
return;
}
if(type.IsAbstract || type.IsInterface)return;
// 检查类型是否具有公共无参数构造函数
var constructor = type.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null);
if (constructor is not null)
{
_value = Activator.CreateInstance<T>();
}
}
public Action<T, T> OnValueChanged { get; set; }
public T Value
@@ -27,7 +43,7 @@ namespace BITKit
}
}
private T _value = typeof(T) == typeof(string) ? string.Empty.As<T>() : Activator.CreateInstance<T>();
private T _value;
public object Obj
{
get => Value;

10
Src/Core/package.json Normal file
View File

@@ -0,0 +1,10 @@
{
"name": "com.bitkit.unity",
"displayName": "BITKit",
"version": "2024.3.31",
"unity": "2022.3",
"description": "BITKit.net 适用于Unity,Godot,Asp以及NetCore控制台的C#框架",
"keywords": [ "BITKit", "Framework","dotnet",".net" ],
"license": "MIT",
"dependencies": {}
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ff52becbcebf89b4f833a5a47cc44e55
PackageManifestImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: