|
@ -7,6 +7,8 @@ using Cysharp.Threading.Tasks;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
// ReSharper disable StringLiteralTypo
|
// ReSharper disable StringLiteralTypo
|
||||||
#if NET5_0_OR_GREATER
|
#if NET5_0_OR_GREATER
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
@ -18,10 +20,9 @@ namespace BITKit
|
||||||
{
|
{
|
||||||
public override string Message => "Application Is Not Playing";
|
public override string Message => "Application Is Not Playing";
|
||||||
}
|
}
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
public class BITApp
|
public class BITApp
|
||||||
{
|
{
|
||||||
public static int Count => _count++;
|
|
||||||
private static int _count;
|
|
||||||
public static async UniTask SwitchToMainThread()
|
public static async UniTask SwitchToMainThread()
|
||||||
{
|
{
|
||||||
#if UNITY_5_3_OR_NEWER
|
#if UNITY_5_3_OR_NEWER
|
||||||
|
@ -168,7 +169,6 @@ namespace BITKit
|
||||||
"MySql",
|
"MySql",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#if NET5_0_OR_GREATER
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 依赖服务集合
|
/// 依赖服务集合
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -176,13 +176,18 @@ namespace BITKit
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 依赖服务提供接口
|
/// 依赖服务提供接口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static ServiceProvider ServiceProvider { get; internal set; }
|
public static ServiceProvider ServiceProvider { get; private set; }
|
||||||
|
public static ServiceProvider BuildServiceProvider()
|
||||||
|
{
|
||||||
|
var value = ServiceProvider = ServiceCollection.BuildServiceProvider();
|
||||||
|
OnServiceProviderBuild?.Invoke(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 服务创建后的回调
|
/// 服务创建后的回调
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static Action<ServiceProvider> OnServiceProviderBuilded;
|
public static Action<ServiceProvider> OnServiceProviderBuild;
|
||||||
#endif
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 主线程
|
/// 主线程
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -254,7 +259,6 @@ namespace BITKit
|
||||||
private static DateTime InitialTime { get; set; }=DateTime.Now;
|
private static DateTime InitialTime { get; set; }=DateTime.Now;
|
||||||
public static async UniTask Start(string appName = nameof(BITApp),AppSettings settings=default)
|
public static async UniTask Start(string appName = nameof(BITApp),AppSettings settings=default)
|
||||||
{
|
{
|
||||||
_count = 0;
|
|
||||||
Time.TimeAsDouble = 0;
|
Time.TimeAsDouble = 0;
|
||||||
Time.DeltaTime = 1 / 60f;
|
Time.DeltaTime = 1 / 60f;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: ef5795e833a88cd4b8c1485d4b50ebfd
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -2,7 +2,7 @@
|
||||||
{
|
{
|
||||||
public static class BITMapper
|
public static class BITMapper
|
||||||
{
|
{
|
||||||
public static void Map<T>(T source, T target) where T : class
|
public static T Map<T>(object source, T target) where T : class
|
||||||
{
|
{
|
||||||
foreach (var info in source.GetType().GetProperties(ReflectionHelper.Flags))
|
foreach (var info in source.GetType().GetProperties(ReflectionHelper.Flags))
|
||||||
{
|
{
|
||||||
|
@ -23,6 +23,7 @@
|
||||||
targetInfo?.SetValue(target, value);
|
targetInfo?.SetValue(target, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return target;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,50 +137,58 @@ namespace BITKit
|
||||||
}
|
}
|
||||||
public static void Write(BinaryWriter writer, object value)
|
public static void Write(BinaryWriter writer, object value)
|
||||||
{
|
{
|
||||||
if (value is not string && value is IList enumerable)
|
try
|
||||||
{
|
{
|
||||||
var pars = enumerable.Cast<object>().ToArray();
|
if (value is not string && value is IList enumerable)
|
||||||
writer.Write(true);
|
|
||||||
writer.Write(value.GetType().GetElementType()!.FullName!);
|
|
||||||
writer.Write(pars.Length);
|
|
||||||
foreach (var obj in pars)
|
|
||||||
{
|
{
|
||||||
WriteInterel(writer, obj);
|
var pars = enumerable.Cast<object>().ToArray();
|
||||||
}
|
writer.Write(true);
|
||||||
}
|
writer.Write(value.GetType().GetElementType()!.FullName!);
|
||||||
else
|
writer.Write(pars.Length);
|
||||||
{
|
foreach (var obj in pars)
|
||||||
writer.Write(false);
|
{
|
||||||
WriteInterel(writer,value);
|
WriteInterel(writer, obj);
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
void WriteInterel(BinaryWriter writer, object value)
|
|
||||||
{
|
|
||||||
var typeName = value.GetType().FullName;
|
|
||||||
writer.Write(typeName!);
|
|
||||||
if (netReaders.TryGetValue(typeName, out var netReader))
|
|
||||||
{
|
|
||||||
netReader.WriteBinaryAsObject(writer,value);
|
|
||||||
}
|
|
||||||
else if (value is IBinarySerialize serialize)
|
|
||||||
{
|
|
||||||
serialize.Write(writer);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
try
|
writer.Write(false);
|
||||||
{
|
WriteInterel(writer,value);
|
||||||
writer.Write(JsonConvert.SerializeObject(value));
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
BIT4Log.Warning<BITBinary>(typeName);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
void WriteInterel(BinaryWriter writer, object value)
|
||||||
|
{
|
||||||
|
var typeName = value.GetType().FullName;
|
||||||
|
writer.Write(typeName!);
|
||||||
|
if (netReaders.TryGetValue(typeName, out var netReader))
|
||||||
|
{
|
||||||
|
netReader.WriteBinaryAsObject(writer,value);
|
||||||
|
}
|
||||||
|
else if (value is IBinarySerialize serialize)
|
||||||
|
{
|
||||||
|
serialize.Write(writer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
writer.Write(JsonConvert.SerializeObject(value));
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
BIT4Log.Warning<BITBinary>(typeName);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public static bool IsSupport(object obj) => IsSupport(obj.GetType().FullName);
|
public static bool IsSupport(object obj) => IsSupport(obj.GetType().FullName);
|
||||||
public static bool IsSupport(Type type) => IsSupport(type.FullName);
|
public static bool IsSupport(Type type) => IsSupport(type.FullName);
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: de545a8f794806c468d90c634c53582a
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -28,7 +28,7 @@ namespace BITKit.CommandPattern
|
||||||
void Release();
|
void Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class CommandSequence:List<ICommand>,IBinarySerialize
|
public sealed class CommandSequence:List<ICommand>,Microsoft.SqlServer.Server.IBinarySerialize
|
||||||
{
|
{
|
||||||
public void Read(BinaryReader r)
|
public void Read(BinaryReader r)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: fa98aca39a218e24cafafaf926cafa1c
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 11c54e9541abd79499031d2fd92af224
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 4273bb14e8bf75943bcac37ef781c9fd
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 8016d8e2215fd544b81c945f11090744
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -3,5 +3,6 @@ namespace BITKit
|
||||||
public interface IDescription
|
public interface IDescription
|
||||||
{
|
{
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
|
public string Description { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 549453866297ec84f8fcb28c9da7b1f0
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 7f0710f16fd119f44a922b5e83c7d57b
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -54,79 +54,87 @@ namespace BITKit.Entities
|
||||||
|
|
||||||
public T[] QueryComponents<T>()
|
public T[] QueryComponents<T>()
|
||||||
{
|
{
|
||||||
return _queryCache.GetOrAdd(typeof(T), type =>
|
throw new NotImplementedException();
|
||||||
{
|
// return _queryCache.GetOrAdd(typeof(T), type =>
|
||||||
return _entities.Values.Where(entity => entity.TryGetComponent(out T component)).ToArray();
|
// {
|
||||||
}).Cast<T>().ToArray();
|
// return _entities.Values.Where(entity => entity.TryGetComponent(out T component)).ToArray();
|
||||||
|
// }).Cast<T>().ToArray();
|
||||||
}
|
}
|
||||||
public (T, T1)[] QueryComponents<T, T1>()
|
public (T, T1)[] QueryComponents<T, T1>()
|
||||||
{
|
{
|
||||||
List<(T, T1)> list = new();
|
throw new NotImplementedException();
|
||||||
foreach (var entity in _entities.Values)
|
// List<(T, T1)> list = new();
|
||||||
{
|
// foreach (var entity in _entities.Values)
|
||||||
if (entity.TryGetComponent(out T t) && entity.TryGetComponent(out T1 t1))
|
// {
|
||||||
list.Add((t, t1));
|
// if (entity.TryGetComponent(out T t) && entity.TryGetComponent(out T1 t1))
|
||||||
}
|
// list.Add((t, t1));
|
||||||
return list.ToArray();
|
// }
|
||||||
|
// return list.ToArray();
|
||||||
}
|
}
|
||||||
public (T, T1, T2)[] QueryComponents<T, T1, T2>()
|
public (T, T1, T2)[] QueryComponents<T, T1, T2>()
|
||||||
{
|
{
|
||||||
List<(T, T1, T2)> list = new();
|
throw new NotImplementedException();
|
||||||
foreach (var entity in _entities.Values)
|
// List<(T, T1, T2)> list = new();
|
||||||
{
|
// foreach (var entity in _entities.Values)
|
||||||
if (entity.TryGetComponent(out T t) && entity.TryGetComponent(out T1 t1) && entity.TryGetComponent(out T2 t2))
|
// {
|
||||||
list.Add((t, t1, t2));
|
// if (entity.TryGetComponent(out T t) && entity.TryGetComponent(out T1 t1) && entity.TryGetComponent(out T2 t2))
|
||||||
}
|
// list.Add((t, t1, t2));
|
||||||
return list.ToArray();
|
// }
|
||||||
|
// return list.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public (T, T1, T2, T3)[] QueryComponents<T, T1, T2, T3>()
|
public (T, T1, T2, T3)[] QueryComponents<T, T1, T2, T3>()
|
||||||
{
|
{
|
||||||
List<(T, T1, T2, T3)> list = new();
|
throw new NotImplementedException();
|
||||||
foreach (var entity in _entities.Values)
|
// List<(T, T1, T2, T3)> list = new();
|
||||||
{
|
// foreach (var entity in _entities.Values)
|
||||||
if (entity.TryGetComponent(out T t) && entity.TryGetComponent(out T1 t1) && entity.TryGetComponent(out T2 t2) && entity.TryGetComponent(out T3 t3))
|
// {
|
||||||
list.Add((t, t1, t2, t3));
|
// if (entity.TryGetComponent(out T t) && entity.TryGetComponent(out T1 t1) && entity.TryGetComponent(out T2 t2) && entity.TryGetComponent(out T3 t3))
|
||||||
}
|
// list.Add((t, t1, t2, t3));
|
||||||
return list.ToArray();
|
// }
|
||||||
|
// return list.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public (T, T1, T2, T3, T4)[] QueryComponents<T, T1, T2, T3, T4>()
|
public (T, T1, T2, T3, T4)[] QueryComponents<T, T1, T2, T3, T4>()
|
||||||
{
|
{
|
||||||
List<(T, T1, T2, T3, T4)> list = new();
|
throw new NotImplementedException();
|
||||||
foreach (var entity in _entities.Values)
|
// List<(T, T1, T2, T3, T4)> list = new();
|
||||||
{
|
// foreach (var entity in _entities.Values)
|
||||||
if (entity.TryGetComponent(out T t) && entity.TryGetComponent(out T1 t1) && entity.TryGetComponent(out T2 t2) && entity.TryGetComponent(out T3 t3) && entity.TryGetComponent(out T4 t4))
|
// {
|
||||||
list.Add((t, t1, t2, t3, t4));
|
// if (entity.TryGetComponent(out T t) && entity.TryGetComponent(out T1 t1) && entity.TryGetComponent(out T2 t2) && entity.TryGetComponent(out T3 t3) && entity.TryGetComponent(out T4 t4))
|
||||||
}
|
// list.Add((t, t1, t2, t3, t4));
|
||||||
return list.ToArray();
|
// }
|
||||||
|
// return list.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public (T, T1, T2, T3, T4, T5)[] QueryComponents<T, T1, T2, T3, T4, T5>()
|
public (T, T1, T2, T3, T4, T5)[] QueryComponents<T, T1, T2, T3, T4, T5>()
|
||||||
{
|
{
|
||||||
List<(T, T1, T2, T3, T4, T5)> list = new();
|
throw new NotImplementedException();
|
||||||
foreach (var entity in _entities.Values)
|
// List<(T, T1, T2, T3, T4, T5)> list = new();
|
||||||
{
|
// foreach (var entity in _entities.Values)
|
||||||
if (entity.TryGetComponent(out T t) && entity.TryGetComponent(out T1 t1) && entity.TryGetComponent(out T2 t2) && entity.TryGetComponent(out T3 t3) && entity.TryGetComponent(out T4 t4) && entity.TryGetComponent(out T5 t5))
|
// {
|
||||||
list.Add((t, t1, t2, t3, t4, t5));
|
// if (entity.TryGetComponent(out T t) && entity.TryGetComponent(out T1 t1) && entity.TryGetComponent(out T2 t2) && entity.TryGetComponent(out T3 t3) && entity.TryGetComponent(out T4 t4) && entity.TryGetComponent(out T5 t5))
|
||||||
}
|
// list.Add((t, t1, t2, t3, t4, t5));
|
||||||
return list.ToArray();
|
// }
|
||||||
|
// return list.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public (T, T1, T2, T3, T4, T5, T6)[] QueryComponents<T, T1, T2, T3, T4, T5, T6>()
|
public (T, T1, T2, T3, T4, T5, T6)[] QueryComponents<T, T1, T2, T3, T4, T5, T6>()
|
||||||
{
|
{
|
||||||
List<(T, T1, T2, T3, T4, T5, T6)> list = new();
|
throw new NotImplementedException();
|
||||||
foreach (var entity in _entities.Values)
|
// List<(T, T1, T2, T3, T4, T5, T6)> list = new();
|
||||||
{
|
// foreach (var entity in _entities.Values)
|
||||||
if (entity.TryGetComponent(out T t) && entity.TryGetComponent(out T1 t1) && entity.TryGetComponent(out T2 t2) && entity.TryGetComponent(out T3 t3) && entity.TryGetComponent(out T4 t4) && entity.TryGetComponent(out T5 t5) && entity.TryGetComponent(out T6 t6))
|
// {
|
||||||
list.Add((t, t1, t2, t3, t4, t5, t6));
|
// if (entity.TryGetComponent(out T t) && entity.TryGetComponent(out T1 t1) && entity.TryGetComponent(out T2 t2) && entity.TryGetComponent(out T3 t3) && entity.TryGetComponent(out T4 t4) && entity.TryGetComponent(out T5 t5) && entity.TryGetComponent(out T6 t6))
|
||||||
}
|
// list.Add((t, t1, t2, t3, t4, t5, t6));
|
||||||
return list.ToArray();
|
// }
|
||||||
|
// 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();
|
||||||
|
// throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
@ -7,9 +8,25 @@ namespace BITKit.Entities
|
||||||
{
|
{
|
||||||
public class Entity : IEntity, IDisposable
|
public class Entity : IEntity, IDisposable
|
||||||
{
|
{
|
||||||
|
private class EntityServiceProvider : IServiceProvider
|
||||||
|
{
|
||||||
|
public ServiceProvider ServiceProvider;
|
||||||
|
public readonly List<Object> Services = new();
|
||||||
|
public object GetService(Type serviceType)
|
||||||
|
{
|
||||||
|
var value = ServiceProvider.GetService(serviceType);
|
||||||
|
if (value != null)
|
||||||
|
{
|
||||||
|
Services.TryAdd(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Entity()
|
public Entity()
|
||||||
{
|
{
|
||||||
RegisterComponent<IEntity>(this);
|
ServiceCollection.AddSingleton<IEntity>(this);
|
||||||
}
|
}
|
||||||
public void WaitForInitializationComplete()
|
public void WaitForInitializationComplete()
|
||||||
{
|
{
|
||||||
|
@ -19,51 +36,26 @@ namespace BITKit.Entities
|
||||||
public CancellationToken CancellationToken => _cancellationTokenSource.Token;
|
public CancellationToken CancellationToken => _cancellationTokenSource.Token;
|
||||||
private readonly CancellationTokenSource _cancellationTokenSource = new();
|
private readonly CancellationTokenSource _cancellationTokenSource = new();
|
||||||
|
|
||||||
public bool TryGetComponent<T>(out T component)
|
public IServiceProvider ServiceProvider
|
||||||
{
|
{
|
||||||
var value = ServiceProvider.GetService<T>();
|
get
|
||||||
if (value != null)
|
|
||||||
{
|
{
|
||||||
component = value;
|
if (_serviceProvider is not null)
|
||||||
return true;
|
{
|
||||||
|
return _serviceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
var value = new EntityServiceProvider()
|
||||||
|
{
|
||||||
|
ServiceProvider = ServiceCollection.BuildServiceProvider()
|
||||||
|
};
|
||||||
|
_serviceProvider = value;
|
||||||
|
return _serviceProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
component = default!;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetComponent(Type type, out IEntityComponent component)
|
|
||||||
{
|
|
||||||
var value = ServiceProvider.GetService(type);
|
|
||||||
if (value != null)
|
|
||||||
{
|
|
||||||
component = (IEntityComponent)value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
component = default!;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEntityComponent[] Components => ServiceCollection.OfType<IEntityComponent>().ToArray();
|
|
||||||
|
|
||||||
public bool RegisterComponent<T>(T component)
|
|
||||||
{
|
|
||||||
_services.Add(component);
|
|
||||||
ServiceCollection.AddSingleton(typeof(T), component);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IServiceProvider ServiceProvider => _serviceProvider ??= ServiceCollection.BuildServiceProvider();
|
|
||||||
public IServiceCollection ServiceCollection { get; } = new ServiceCollection();
|
public IServiceCollection ServiceCollection { get; } = new ServiceCollection();
|
||||||
private IServiceProvider _serviceProvider;
|
private EntityServiceProvider _serviceProvider;
|
||||||
private readonly CacheList<object> _services = new();
|
public object[] GetServices()=> _serviceProvider.Services.ToArray();
|
||||||
|
|
||||||
public object[] GetServices()
|
|
||||||
{
|
|
||||||
return _services.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Inject(object obj)
|
public void Inject(object obj)
|
||||||
{
|
{
|
||||||
foreach (var fieldInfo in obj.GetType().GetFields(ReflectionHelper.Flags))
|
foreach (var fieldInfo in obj.GetType().GetFields(ReflectionHelper.Flags))
|
||||||
|
@ -78,14 +70,10 @@ namespace BITKit.Entities
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_cancellationTokenSource.Cancel();
|
_cancellationTokenSource.Cancel();
|
||||||
_cancellationTokenSource.Dispose();
|
_serviceProvider.ServiceProvider.Dispose();
|
||||||
|
foreach (var x in GetServices().OfType<IDisposable>())
|
||||||
foreach (var service in _services)
|
|
||||||
{
|
{
|
||||||
if (service is IDisposable disposable)
|
x.Dispose();
|
||||||
{
|
|
||||||
disposable.Dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1,11 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 881c97aa8732ace4796d97874c8f8769
|
guid: 881c97aa8732ace4796d97874c8f8769
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel.Design;
|
using System.ComponentModel.Design;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
#if NET5_0_OR_GREATER
|
#if NET5_0_OR_GREATER
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,44 +12,14 @@ namespace BITKit.Entities
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IEntity
|
public interface IEntity
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// 等待初始化完成,通常用于其他系统需要等待实体初始化完成
|
|
||||||
/// </summary>
|
|
||||||
void WaitForInitializationComplete();
|
|
||||||
int Id { get; }
|
int Id { get; }
|
||||||
CancellationToken CancellationToken { get; }
|
CancellationToken CancellationToken { get; }
|
||||||
bool TryGetComponent<T>(out T component);
|
|
||||||
bool TryGetComponent(Type type, out IEntityComponent component);
|
|
||||||
IEntityComponent[] Components { get; }
|
|
||||||
bool RegisterComponent<T>(T component);
|
|
||||||
IServiceProvider ServiceProvider { get; }
|
IServiceProvider ServiceProvider { get; }
|
||||||
#if NET5_0_OR_GREATER
|
|
||||||
IServiceCollection ServiceCollection { get; }
|
IServiceCollection ServiceCollection { get; }
|
||||||
object[] GetServices();
|
object[] GetServices();
|
||||||
#endif
|
|
||||||
void Inject(object obj);
|
void Inject(object obj);
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 基本实体组件
|
|
||||||
/// </summary>
|
|
||||||
public interface IEntityComponent
|
|
||||||
{
|
|
||||||
IEntity Entity { get; set; }
|
|
||||||
#if NET5_0_OR_GREATER
|
|
||||||
void BuildService(IServiceCollection serviceCollection);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
public interface IEntityBehavior:IEntityComponent
|
|
||||||
{
|
|
||||||
void Initialize(IEntity _entity);
|
|
||||||
void OnAwake();
|
|
||||||
void OnStart();
|
|
||||||
void OnUpdate(float deltaTime);
|
|
||||||
void OnFixedUpdate(float deltaTime);
|
|
||||||
void OnLateUpdate(float deltaTime);
|
|
||||||
void OnDestroyComponent();
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// 基本实体服务
|
/// 基本实体服务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IEntitiesService
|
public interface IEntitiesService
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 6ca7db14bd1dc33459de160d09804e8b
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -8,7 +8,8 @@ namespace BITKit
|
||||||
{
|
{
|
||||||
public static IEnumerable<Func<T>> CastAsFunc<T>(this Func<T> self)
|
public static IEnumerable<Func<T>> CastAsFunc<T>(this Func<T> self)
|
||||||
{
|
{
|
||||||
return self is null ? Array.Empty<Func<T>>() : self?.GetInvocationList().Cast<Func<T>>();
|
var value = self;
|
||||||
|
return value is null? Array.Empty<Func<T>>() : self?.GetInvocationList().Cast<Func<T>>();
|
||||||
}
|
}
|
||||||
public static IEnumerable<Func<T0, T1>> CastAsFunc<T0, T1>(this Func<T0, T1> self)
|
public static IEnumerable<Func<T0, T1>> CastAsFunc<T0, T1>(this Func<T0, T1> self)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
|
@ -186,6 +187,10 @@ namespace BITKit
|
||||||
self.Add(key, value);
|
self.Add(key, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public static TValue Get<TKey,TValue>(this IDictionary<Type,TValue> self)
|
||||||
|
{
|
||||||
|
return self[typeof(TKey)];
|
||||||
|
}
|
||||||
public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> self, TKey key) where TValue : new()
|
public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> self, TKey key) where TValue : new()
|
||||||
{
|
{
|
||||||
lock (self)
|
lock (self)
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 07743e56508d72f4bbfa9a075927d42c
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -31,7 +31,7 @@ namespace BITKit.StateMachine
|
||||||
void OnStateExit(IState old, IState newState);
|
void OnStateExit(IState old, IState newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IStateMachine<T>
|
public interface IStateMachine<T> where T:IState
|
||||||
{
|
{
|
||||||
bool Enabled { get; set; }
|
bool Enabled { get; set; }
|
||||||
T CurrentState { get; set; }
|
T CurrentState { get; set; }
|
||||||
|
@ -53,7 +53,7 @@ namespace BITKit.StateMachine
|
||||||
|
|
||||||
public static class StateMachineUtils
|
public static class StateMachineUtils
|
||||||
{
|
{
|
||||||
public static void Register<T>(IStateMachine<T> stateMachine, T newState) where T : IState
|
public static void Register<T>(this IStateMachine<T> stateMachine, T newState) where T : IState
|
||||||
{
|
{
|
||||||
if (stateMachine.StateDictionary.ContainsKey(newState.GetType()))
|
if (stateMachine.StateDictionary.ContainsKey(newState.GetType()))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,155 +1,161 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace BITKit
|
namespace BITKit
|
||||||
{
|
{
|
||||||
#region 物品枚举
|
#region 物品枚举
|
||||||
|
|
||||||
public enum ItemQuality
|
public enum ItemQuality
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 常见的
|
/// 常见的
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Common,
|
Common,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 罕见的
|
/// 罕见的
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Uncommon,
|
Uncommon,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 稀有的
|
/// 稀有的
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Rare,
|
Rare,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 史诗的
|
/// 史诗的
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Epic,
|
Epic,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 传奇的
|
/// 传奇的
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Legendary,
|
Legendary,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 神话的
|
/// 神话的
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Mythical,
|
Mythical,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 开发者
|
/// 开发者
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Develop,
|
Develop,
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 物品接口
|
#region 物品接口
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 物品属性
|
||||||
|
/// </summary>
|
||||||
|
public interface IScriptableItemProperty
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 基础物品
|
/// 基础物品
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IBasicItem :IPropertable,ICloneable
|
public interface IScriptableItem
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 唯一Id
|
/// 唯一Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
int Id { get; }
|
int Id { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 物品名,一般用于查找物品的主键
|
/// 物品名,一般用于查找物品的主键
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string Name { get; }
|
string Name { get; }
|
||||||
// /// <summary>
|
|
||||||
// /// 可寻址路径,该路径用于查找物品
|
|
||||||
// /// </summary>
|
|
||||||
// string AddressablePath { get; }
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 物品描述
|
/// 物品描述
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string Description { get; }
|
string Description { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最大堆叠数量
|
||||||
|
/// </summary>
|
||||||
|
public int MaxStack { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 物品品质
|
/// 物品品质
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ItemQuality Quality { get; }
|
ItemQuality Quality { get; }
|
||||||
bool CopyItemsFrom(IBasicItem item);
|
|
||||||
|
/// <summary>
|
||||||
|
/// 属性
|
||||||
|
/// </summary>
|
||||||
|
IReadOnlyDictionary<Type, IScriptableItemProperty> Properties { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 价值
|
/// 价值
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
int Value=>10;
|
int Value => 10;
|
||||||
}
|
}
|
||||||
/// <summary>
|
|
||||||
/// 可配置化物品,通常用于配置
|
public interface IRuntimeItem : ICloneable
|
||||||
/// </summary>
|
|
||||||
public interface IAssetableItem: IBasicItem
|
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 运行时Id
|
||||||
|
/// </summary>
|
||||||
|
public int Id { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 配置Id
|
||||||
|
/// </summary>
|
||||||
|
public int ScriptableId { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数量
|
||||||
|
/// </summary>
|
||||||
|
public int Amount { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 运行时属性
|
||||||
|
/// </summary>
|
||||||
|
IDictionary<Type, IScriptableItemProperty> RuntimeProperties { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当运行时属性改变时
|
||||||
|
/// </summary>
|
||||||
|
// ReSharper disable once EventNeverInvoked.Global
|
||||||
|
event Action<IRuntimeItem> OnRuntimePropertiesChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 物品实现
|
#region 物品实现
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 被托管的物品
|
/// 被托管的物品
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class ManagedItem : IBasicItem
|
public record RuntimeItem : IRuntimeItem
|
||||||
{
|
{
|
||||||
#region 字段
|
public int Id { get; set; } = new Random().Next();
|
||||||
public int Id;
|
public int ScriptableId { get; set; }
|
||||||
public string Name;
|
public int Amount { get; set; }
|
||||||
public string AddressablePath { get; set; }
|
|
||||||
public string Description;
|
|
||||||
public ItemQuality Quality;
|
|
||||||
public int Value { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 本地属性
|
|
||||||
/// </summary>
|
|
||||||
private Property property = new();
|
|
||||||
#endregion
|
|
||||||
#region 接口的隐式实现
|
|
||||||
int IBasicItem.Id => Id;
|
|
||||||
string IBasicItem.Name => Name;
|
|
||||||
string IBasicItem.Description => Description;
|
|
||||||
ItemQuality IBasicItem.Quality => Quality;
|
|
||||||
#endregion
|
|
||||||
#region 接口的显式实现
|
|
||||||
public bool Contains<T>() => property.Contains<T>();
|
|
||||||
|
|
||||||
public T GetOrAddProperty<T>(Func<T> addFactory) => property.GetOrAddProperty<T>(addFactory);
|
public IDictionary<Type, IScriptableItemProperty> RuntimeProperties { get; set; } =
|
||||||
|
new Dictionary<Type, IScriptableItemProperty>();
|
||||||
|
|
||||||
public T GetOrCreateProperty<T>() => property.GetOrCreateProperty<T>();
|
public event Action<IRuntimeItem> OnRuntimePropertiesChanged;
|
||||||
|
|
||||||
public object[] GetProperties() => property.GetProperties();
|
object ICloneable.Clone()
|
||||||
|
|
||||||
public bool TryGetProperty<T>(out T value) => property.TryGetProperty<T>(out value);
|
|
||||||
|
|
||||||
public bool TryRemoveProperty<T>() => property.TryRemoveProperty<T>();
|
|
||||||
|
|
||||||
public bool TrySetProperty<T>(T value) => property.TrySetProperty(value);
|
|
||||||
|
|
||||||
public void Read(BinaryReader r)
|
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return new RuntimeItem
|
||||||
}
|
{
|
||||||
|
Id = new Random().Next(),
|
||||||
public void Write(BinaryWriter w)
|
ScriptableId = ScriptableId,
|
||||||
{
|
Amount = Amount,
|
||||||
throw new NotImplementedException();
|
RuntimeProperties = new Dictionary<Type, IScriptableItemProperty>(RuntimeProperties),
|
||||||
}
|
OnRuntimePropertiesChanged = null,
|
||||||
|
};
|
||||||
public bool CopyItemsFrom(IBasicItem item)
|
|
||||||
{
|
|
||||||
Value = item.Value;
|
|
||||||
Id=item.Id;
|
|
||||||
Name = item.Name;
|
|
||||||
//AddressablePath = item.AddressablePath;
|
|
||||||
Description = item.Description;
|
|
||||||
Quality=item.Quality;
|
|
||||||
CopyPropertiesFrom(item);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
public bool ClearProperties()=>property.ClearProperties();
|
|
||||||
public bool CopyPropertiesFrom(IPropertable propertable)
|
|
||||||
{
|
|
||||||
return property.CopyPropertiesFrom(propertable);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public object Clone()
|
|
||||||
{
|
|
||||||
var item = MemberwiseClone() as ManagedItem;
|
|
||||||
item!.Id = Id;
|
|
||||||
return item;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using Microsoft.SqlServer.Server;
|
||||||
|
|
||||||
namespace BITKit
|
namespace BITKit
|
||||||
{
|
{
|
||||||
|
@ -7,89 +8,63 @@ namespace BITKit
|
||||||
/// 支持属性
|
/// 支持属性
|
||||||
/// 支持回调
|
/// 支持回调
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IBasicItemContainer
|
public interface IRuntimeItemContainer:IBinarySerialize
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 物品容器的唯一Id
|
/// 物品容器的唯一Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
int Id { get; }
|
int Id { get; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 尝试获取指定Item
|
|
||||||
/// </summary>
|
|
||||||
bool TryGetItem(Func<IBasicItem, bool> func, out IBasicItem item);
|
|
||||||
/// <summary>
|
|
||||||
/// 获取所有Item的只读副本
|
/// 获取所有Item的只读副本
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IBasicItem[] GetItems();
|
IRuntimeItem[] GetItems();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加物品的接口
|
/// 添加物品的接口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool Add(IBasicItem item);
|
bool Add(IRuntimeItem item);
|
||||||
/// <summary>
|
|
||||||
/// 通过Item本身进行移除
|
|
||||||
/// </summary>
|
|
||||||
bool Remove(IBasicItem item);
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 通过Id移除物品(推荐)
|
/// 通过Id移除物品(推荐)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool Remove(int id);
|
bool Remove(int id);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 通过工厂方法移除物品
|
|
||||||
/// </summary>
|
|
||||||
bool Remove(Func<IBasicItem, bool> removeFactory);
|
|
||||||
/// <summary>
|
|
||||||
/// 通过通过Id丢下物品
|
/// 通过通过Id丢下物品
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool Drop(int Id);
|
bool Drop(int id);
|
||||||
bool DropOrSpawn(IBasicItem item);
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 注册添加物品的工厂方法,
|
/// 注册添加物品的工厂方法,
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event Func<IBasicItem, bool> AddFactory;
|
event Func<IRuntimeItem, bool> AddFactory;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 注册移除物品的工厂方法
|
/// 注册移除物品的工厂方法
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event Func<IBasicItem, bool> RemoveFactory;
|
event Func<IRuntimeItem, bool> RemoveFactory;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 注册丢下物品的工厂方法
|
/// 注册丢下物品的工厂方法
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event Func<IBasicItem, bool> DropFactory;
|
event Func<IRuntimeItem, bool> DropFactory;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 已添加Item的回调
|
/// 已添加Item的回调
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event Action<IBasicItem> OnAdd;
|
event Action<IRuntimeItem> OnAdd;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 已移除Item的回调
|
/// 已移除Item的回调
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event Action<IBasicItem> OnRemove;
|
event Action<IRuntimeItem> OnRemove;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 已设置Item的回调
|
/// 已设置Item的回调
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event Action<IBasicItem> OnSet;
|
event Action<IRuntimeItem> OnSet;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 已丢下Item的回调
|
/// 已丢下Item的回调
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event Action<IBasicItem> OnDrop;
|
event Action<IRuntimeItem> OnDrop;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 已重构Items的回调
|
/// 已重构Items的回调
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event Action<IBasicItemContainer> OnRebuild;
|
event Action<IRuntimeItemContainer> OnRebuild;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否已完成物品交换,例如false就是开始交换物品true就是已完成交换物品,可以处理物品了
|
/// 是否已完成物品交换,例如false就是开始交换物品true就是已完成交换物品,可以处理物品了
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event Action<bool> OnRelease;
|
event Action<bool> OnRelease;
|
||||||
/// <summary>
|
|
||||||
/// 添加挂起句柄
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id"></param>
|
|
||||||
void AddHandle(int id);
|
|
||||||
/// <summary>
|
|
||||||
/// 移除挂起句柄
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id"></param>
|
|
||||||
void RemoveHandle(int id);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,13 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace BITKit
|
|
||||||
{
|
|
||||||
public interface IWorldItemObject
|
|
||||||
{
|
|
||||||
public IBasicItem Item { get; set; }
|
|
||||||
public event Action<IBasicItem> OnSetItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ using System.Numerics;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using BITKit.Net.Examples;
|
using BITKit.Net.Examples;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
|
|
||||||
|
@ -21,6 +22,26 @@ namespace BITKit.Net
|
||||||
{
|
{
|
||||||
public class KcpNetClient:INetClient,INetProvider
|
public class KcpNetClient:INetClient,INetProvider
|
||||||
{
|
{
|
||||||
|
private readonly ILogger<KcpNetClient> _logger;
|
||||||
|
public KcpNetClient(ILogger<KcpNetClient> logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_client = new KcpClient(
|
||||||
|
OnConnectedInternal,
|
||||||
|
OnData,
|
||||||
|
OnDisconnectInternal,
|
||||||
|
OnError,
|
||||||
|
KCPNet.Config
|
||||||
|
);
|
||||||
|
_timer.Elapsed += Tick;
|
||||||
|
_logger.LogInformation("已创建KCP客户端");
|
||||||
|
AddCommandListener<NetClientAllocateIdCommand>(x =>
|
||||||
|
{
|
||||||
|
Id = x.Id;
|
||||||
|
});
|
||||||
|
_isConnected.AddListener(ConnectionCallback);
|
||||||
|
}
|
||||||
|
|
||||||
public event Action OnStartConnect;
|
public event Action OnStartConnect;
|
||||||
public event Action OnConnected;
|
public event Action OnConnected;
|
||||||
public event Action OnDisconnected;
|
public event Action OnDisconnected;
|
||||||
|
@ -29,14 +50,14 @@ namespace BITKit.Net
|
||||||
public bool IsConnecting { get; private set; }
|
public bool IsConnecting { get; private set; }
|
||||||
public double RpcTimeOut { get; set; } = 5;
|
public double RpcTimeOut { get; set; } = 5;
|
||||||
public bool AutoReconnect { get; set; } = true;
|
public bool AutoReconnect { get; set; } = true;
|
||||||
public float2 Traffic { get; set; }
|
public float2 Traffic { get; private set; }
|
||||||
public bool ManualTick { get; set; }
|
public bool ManualTick { get; set; }
|
||||||
|
|
||||||
private readonly IntervalUpdate _reconnectInterval = new(1);
|
private readonly IntervalUpdate _reconnectInterval = new(1);
|
||||||
|
|
||||||
public int Ping { get; private set; }
|
public int Ping { get; private set; }
|
||||||
public int Id { get; private set; } = -1;
|
public int Id { get; private set; } = -1;
|
||||||
private readonly KcpClient client;
|
private readonly KcpClient _client;
|
||||||
|
|
||||||
private readonly ConcurrentQueue<byte[]> _commandQueue = new();
|
private readonly ConcurrentQueue<byte[]> _commandQueue = new();
|
||||||
|
|
||||||
|
@ -50,7 +71,7 @@ namespace BITKit.Net
|
||||||
private readonly GenericEvent _events = new();
|
private readonly GenericEvent _events = new();
|
||||||
|
|
||||||
private readonly ValidHandle _isConnected = new();
|
private readonly ValidHandle _isConnected = new();
|
||||||
|
private bool _userConnected;
|
||||||
private int _index = int.MinValue;
|
private int _index = int.MinValue;
|
||||||
private readonly ConcurrentDictionary<int, object> _p2p = new();
|
private readonly ConcurrentDictionary<int, object> _p2p = new();
|
||||||
private readonly ConcurrentDictionary<string,Func<object,UniTask<object>>> _rpc = new();
|
private readonly ConcurrentDictionary<string,Func<object,UniTask<object>>> _rpc = new();
|
||||||
|
@ -64,23 +85,7 @@ namespace BITKit.Net
|
||||||
private ushort _connectedPort = 27014;
|
private ushort _connectedPort = 27014;
|
||||||
|
|
||||||
private readonly byte[] _heartBeat = new byte[] { (byte)NetCommandType.Heartbeat };
|
private readonly byte[] _heartBeat = new byte[] { (byte)NetCommandType.Heartbeat };
|
||||||
public KcpNetClient()
|
|
||||||
{
|
|
||||||
client = new KcpClient(
|
|
||||||
OnConnectedInternal,
|
|
||||||
OnData,
|
|
||||||
OnDisconnectInternal,
|
|
||||||
OnError,
|
|
||||||
KCPNet.Config
|
|
||||||
);
|
|
||||||
_timer.Elapsed += Tick;
|
|
||||||
BIT4Log.Log<KcpNetClient>("已创建KCP客户端");
|
|
||||||
AddCommandListener<NetClientAllocateIdCommand>(x =>
|
|
||||||
{
|
|
||||||
Id = x.Id;
|
|
||||||
});
|
|
||||||
_isConnected.AddListener(ConnectionCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void ConnectionCallback(bool x)
|
private async void ConnectionCallback(bool x)
|
||||||
{
|
{
|
||||||
|
@ -88,12 +93,12 @@ namespace BITKit.Net
|
||||||
if (x)
|
if (x)
|
||||||
{
|
{
|
||||||
OnConnected?.Invoke();
|
OnConnected?.Invoke();
|
||||||
BIT4Log.Log<KcpNetClient>("连接成功");
|
_logger.LogInformation("连接成功");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OnDisconnected?.Invoke();
|
OnDisconnected?.Invoke();
|
||||||
BIT4Log.Log<KcpNetClient>("连接已断开");
|
_logger.LogInformation("连接已断开");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,9 +109,14 @@ namespace BITKit.Net
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void Disconnect()
|
public async void Disconnect()
|
||||||
|
{
|
||||||
|
_userConnected = false;
|
||||||
|
DisconnectInternal();
|
||||||
|
}
|
||||||
|
private async void DisconnectInternal()
|
||||||
{
|
{
|
||||||
IsConnecting = false;
|
IsConnecting = false;
|
||||||
client.Disconnect();
|
_client.Disconnect();
|
||||||
_isConnected.RemoveElement(this);
|
_isConnected.RemoveElement(this);
|
||||||
_timer.Stop();
|
_timer.Stop();
|
||||||
try
|
try
|
||||||
|
@ -117,6 +127,7 @@ namespace BITKit.Net
|
||||||
catch (OperationCanceledException){}
|
catch (OperationCanceledException){}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string _lastHostName;
|
||||||
public async UniTask<bool> Connect(string address = "127.0.0.1", ushort port = 27014)
|
public async UniTask<bool> Connect(string address = "127.0.0.1", ushort port = 27014)
|
||||||
{
|
{
|
||||||
if (IsConnecting)
|
if (IsConnecting)
|
||||||
|
@ -124,7 +135,7 @@ namespace BITKit.Net
|
||||||
BIT4Log.Warning<KcpNetClient>("正在连接中");
|
BIT4Log.Warning<KcpNetClient>("正在连接中");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
_userConnected = true;
|
||||||
//如果address是域名,解析为Ip
|
//如果address是域名,解析为Ip
|
||||||
if (address.Contains("."))
|
if (address.Contains("."))
|
||||||
{
|
{
|
||||||
|
@ -132,7 +143,11 @@ namespace BITKit.Net
|
||||||
if (ip.Length > 0)
|
if (ip.Length > 0)
|
||||||
{
|
{
|
||||||
address = ip[0].ToString();
|
address = ip[0].ToString();
|
||||||
BIT4Log.Log<KcpNetClient>($"解析域名:{address}");
|
if (_lastHostName != address)
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"解析域名:{address},IP:{ip}");
|
||||||
|
_lastHostName = address;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +158,7 @@ namespace BITKit.Net
|
||||||
|
|
||||||
|
|
||||||
IsConnecting = true;
|
IsConnecting = true;
|
||||||
if (client.connected) return false;
|
if (_client.connected) return false;
|
||||||
await BITApp.SwitchToMainThread();
|
await BITApp.SwitchToMainThread();
|
||||||
OnStartConnect?.Invoke();
|
OnStartConnect?.Invoke();
|
||||||
await UniTask.SwitchToThreadPool();
|
await UniTask.SwitchToThreadPool();
|
||||||
|
@ -151,7 +166,7 @@ namespace BITKit.Net
|
||||||
{
|
{
|
||||||
_lastHeartbeat = DateTime.Now;
|
_lastHeartbeat = DateTime.Now;
|
||||||
|
|
||||||
client.Connect(address, port);
|
_client.Connect(address, port);
|
||||||
|
|
||||||
_timer.Start();
|
_timer.Start();
|
||||||
_interval = TimeSpan.FromMilliseconds(_timer.Interval);
|
_interval = TimeSpan.FromMilliseconds(_timer.Interval);
|
||||||
|
@ -163,13 +178,13 @@ namespace BITKit.Net
|
||||||
|
|
||||||
for (var i = 0; i < 5; i++)
|
for (var i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
client.Send(new[] { (byte)NetCommandType.Heartbeat }, KcpChannel.Reliable);
|
_client.Send(new[] { (byte)NetCommandType.Heartbeat }, KcpChannel.Reliable);
|
||||||
Traffic += new float2(1, 0);
|
Traffic += new float2(1, 0);
|
||||||
client.Tick();
|
_client.Tick();
|
||||||
await Task.Delay(100);
|
await Task.Delay(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client.connected)
|
if (_client.connected)
|
||||||
{
|
{
|
||||||
SendServerMessage(Environment.MachineName);
|
SendServerMessage(Environment.MachineName);
|
||||||
|
|
||||||
|
@ -177,11 +192,11 @@ namespace BITKit.Net
|
||||||
|
|
||||||
_connectedAddress = address;
|
_connectedAddress = address;
|
||||||
_connectedPort = port;
|
_connectedPort = port;
|
||||||
return client.connected;
|
return _client.connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
OnConnectedFailed?.Invoke();
|
OnConnectedFailed?.Invoke();
|
||||||
Disconnect();
|
DisconnectInternal();
|
||||||
|
|
||||||
IsConnecting = false;
|
IsConnecting = false;
|
||||||
return false;
|
return false;
|
||||||
|
@ -220,7 +235,7 @@ namespace BITKit.Net
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case NetCommandType.Message:
|
case NetCommandType.Message:
|
||||||
BIT4Log.Log<KcpNetClient>($"已收到消息:{reader.ReadString()}");
|
_logger.LogInformation($"已收到消息:{reader.ReadString()}");
|
||||||
break;
|
break;
|
||||||
case NetCommandType.AllClientCommand:
|
case NetCommandType.AllClientCommand:
|
||||||
case NetCommandType.Command:
|
case NetCommandType.Command:
|
||||||
|
@ -424,7 +439,7 @@ namespace BITKit.Net
|
||||||
|
|
||||||
if (eventDelegate is null)
|
if (eventDelegate is null)
|
||||||
{
|
{
|
||||||
BIT4Log.Warning<KcpNetClient>($"未找到对应的事件:{rpcName}");
|
//BIT4Log.Warning<KcpNetClient>($"未找到对应的事件:{rpcName}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -443,9 +458,9 @@ namespace BITKit.Net
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BIT4Log.Log<KcpNetClient>($"未知消息类型:{type},字节:{(byte)type}");
|
_logger.LogInformation($"未知消息类型:{type},字节:{(byte)type}");
|
||||||
if (bytes.Array != null)
|
if (bytes.Array != null)
|
||||||
BIT4Log.Log<KcpNetClient>(
|
_logger.LogInformation(
|
||||||
$"已收到:({Id}, {BitConverter.ToString(bytes.Array, bytes.Offset, bytes.Count)} @ {channel})");
|
$"已收到:({Id}, {BitConverter.ToString(bytes.Array, bytes.Offset, bytes.Count)} @ {channel})");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -456,17 +471,17 @@ namespace BITKit.Net
|
||||||
// if (BITApp.SynchronizationContext is not null)
|
// if (BITApp.SynchronizationContext is not null)
|
||||||
// await UniTask.SwitchToSynchronizationContext(BITApp.SynchronizationContext);
|
// await UniTask.SwitchToSynchronizationContext(BITApp.SynchronizationContext);
|
||||||
// OnConnected?.Invoke();
|
// OnConnected?.Invoke();
|
||||||
// BIT4Log.Log<KcpNetClient>("已连接");
|
// _logger.LogInformation("已连接");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnDisconnectInternal()
|
private async void OnDisconnectInternal()
|
||||||
{
|
{
|
||||||
//BIT4Log.Log<KcpNetClient>("连接被断开");
|
// _logger.LogInformation("连接被断开");
|
||||||
Disconnect();
|
DisconnectInternal();
|
||||||
}
|
}
|
||||||
private void OnError(ErrorCode errorCode, string message)
|
private void OnError(ErrorCode errorCode, string message)
|
||||||
{
|
{
|
||||||
BIT4Log.Log<KcpNetClient>($"{client.remoteEndPoint}异常:{errorCode},{message}");
|
_logger.LogInformation($"{_client.remoteEndPoint}异常:{errorCode},{message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ServerCommand<T>(T command = default)
|
public void ServerCommand<T>(T command = default)
|
||||||
|
@ -500,6 +515,10 @@ namespace BITKit.Net
|
||||||
|
|
||||||
public async UniTask<T> GetFromServer<T>(string path = default,params object[] pars)
|
public async UniTask<T> GetFromServer<T>(string path = default,params object[] pars)
|
||||||
{
|
{
|
||||||
|
if (IsConnected is false)
|
||||||
|
{
|
||||||
|
throw new NetOfflineException();
|
||||||
|
}
|
||||||
//await UniTask.SwitchToThreadPool();
|
//await UniTask.SwitchToThreadPool();
|
||||||
var id = _index++;
|
var id = _index++;
|
||||||
var ms = new MemoryStream();
|
var ms = new MemoryStream();
|
||||||
|
@ -528,6 +547,10 @@ namespace BITKit.Net
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
if (IsConnected is false)
|
||||||
|
{
|
||||||
|
throw new NetOfflineException();
|
||||||
|
}
|
||||||
if ((_now - startTime).TotalSeconds > RpcTimeOut)
|
if ((_now - startTime).TotalSeconds > RpcTimeOut)
|
||||||
{
|
{
|
||||||
await BITApp.SwitchToMainThread();
|
await BITApp.SwitchToMainThread();
|
||||||
|
@ -573,24 +596,25 @@ namespace BITKit.Net
|
||||||
foreach (var methodInfo in rpcHandle.GetType().GetMethods())
|
foreach (var methodInfo in rpcHandle.GetType().GetMethods())
|
||||||
{
|
{
|
||||||
var att = methodInfo.GetCustomAttribute<NetRpcAttribute>();
|
var att = methodInfo.GetCustomAttribute<NetRpcAttribute>();
|
||||||
if(att is null)continue;
|
if (att is null) continue;
|
||||||
_rpcMethods.AddOrUpdate(methodInfo.Name, methodInfo, (s, info) => methodInfo);
|
_rpcMethods.AddOrUpdate(methodInfo.Name, methodInfo, (s, info) => methodInfo);
|
||||||
_rpcHandles.AddOrUpdate(methodInfo.Name, rpcHandle, (s, o) => rpcHandle);
|
_rpcHandles.AddOrUpdate(methodInfo.Name, rpcHandle, (s, o) => rpcHandle);
|
||||||
|
|
||||||
reportBuilder.AppendLine($"Add [{methodInfo.Name}] as MethodInfo");
|
reportBuilder.AppendLine($"Add [{methodInfo.Name}] as MethodInfo");
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var eventInfo in rpcHandle.GetType().GetEvents())
|
foreach (var eventInfo in rpcHandle.GetType().GetEvents())
|
||||||
{
|
{
|
||||||
var att = eventInfo.GetCustomAttribute<NetRpcAttribute>();
|
var att = eventInfo.GetCustomAttribute<NetRpcAttribute>();
|
||||||
if(att is null)continue;
|
if (att is null) continue;
|
||||||
|
|
||||||
_rpcEvents.TryAdd(eventInfo.Name, eventInfo);
|
_rpcEvents.TryAdd(eventInfo.Name, eventInfo);
|
||||||
_rpcHandles.TryAdd(eventInfo.Name, rpcHandle);
|
_rpcHandles.TryAdd(eventInfo.Name, rpcHandle);
|
||||||
|
|
||||||
reportBuilder.AppendLine($"Add [{eventInfo.Name}] as EventInfo");
|
reportBuilder.AppendLine($"Add [{eventInfo.Name}] as EventInfo");
|
||||||
}
|
}
|
||||||
|
|
||||||
BIT4Log.Log<KcpNetClient>(reportBuilder);
|
_logger.LogInformation(reportBuilder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddCommandListener<T>(Action<T> handle)
|
public void AddCommandListener<T>(Action<T> handle)
|
||||||
|
@ -621,6 +645,10 @@ namespace BITKit.Net
|
||||||
|
|
||||||
public void SendRT(string rpcName, params object[] pars)
|
public void SendRT(string rpcName, params object[] pars)
|
||||||
{
|
{
|
||||||
|
if (IsConnected is false)
|
||||||
|
{
|
||||||
|
throw new NetOfflineException();
|
||||||
|
}
|
||||||
using var ms = new MemoryStream();
|
using var ms = new MemoryStream();
|
||||||
using var writer = new BinaryWriter(ms);
|
using var writer = new BinaryWriter(ms);
|
||||||
writer.Write((byte)NetCommandType.GetFromServer);
|
writer.Write((byte)NetCommandType.GetFromServer);
|
||||||
|
@ -650,36 +678,36 @@ namespace BITKit.Net
|
||||||
.Write(message)
|
.Write(message)
|
||||||
.Build();
|
.Build();
|
||||||
Traffic+=new float2(bytes.Length,0);
|
Traffic+=new float2(bytes.Length,0);
|
||||||
client.Send(bytes, KcpChannel.Reliable);
|
_client.Send(bytes, KcpChannel.Reliable);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
private readonly IntervalUpdate _pingInterval = new(1);
|
private readonly IntervalUpdate _pingInterval = new(1);
|
||||||
#endif
|
|
||||||
|
#endif
|
||||||
|
|
||||||
public void Tick()
|
public void Tick()
|
||||||
{
|
{
|
||||||
|
_now = DateTime.Now;
|
||||||
|
if(_userConnected is false)return;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_now = DateTime.UtcNow;
|
if (_client.connected)
|
||||||
|
|
||||||
|
|
||||||
if (client.connected)
|
|
||||||
{
|
{
|
||||||
if (DateTime.Now - _lastHeartbeat > TimeSpan.FromSeconds(5))
|
if (DateTime.Now - _lastHeartbeat > TimeSpan.FromSeconds(5))
|
||||||
{
|
{
|
||||||
BIT4Log.Warning<KcpNetClient>("心跳超时,自动断开");
|
BIT4Log.Warning<KcpNetClient>("心跳超时,自动断开");
|
||||||
Disconnect();
|
DisconnectInternal();
|
||||||
_commandQueue.Clear();
|
_commandQueue.Clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while (_commandQueue.TryDequeue(out var bytes))
|
while (_commandQueue.TryDequeue(out var bytes))
|
||||||
{
|
{
|
||||||
Traffic += new float2(bytes.Length, 0);
|
Traffic += new float2(bytes.Length, 0);
|
||||||
client.Send(bytes, KcpChannel.Reliable);
|
_client.Send(bytes, KcpChannel.Reliable);
|
||||||
}
|
}
|
||||||
Traffic+=new float2(1,0);
|
Traffic+=new float2(1,0);
|
||||||
client.Send(_heartBeat, KcpChannel.Unreliable);
|
_client.Send(_heartBeat, KcpChannel.Unreliable);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -696,16 +724,7 @@ namespace BITKit.Net
|
||||||
//BIT4Log.Warning<KcpNetClient>("连接已断开,清空指令队列");
|
//BIT4Log.Warning<KcpNetClient>("连接已断开,清空指令队列");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_client.Tick();
|
||||||
#if UNITY_EDITOR
|
|
||||||
if (_pingInterval.AllowUpdate)
|
|
||||||
{
|
|
||||||
_lastPingTime = DateTime.Now;
|
|
||||||
client.Send(new[] { (byte)NetCommandType.Ping }, KcpChannel.Reliable);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
client.Tick();
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -718,7 +737,7 @@ namespace BITKit.Net
|
||||||
{
|
{
|
||||||
// send client to server
|
// send client to server
|
||||||
Traffic+=new float2(2,0);
|
Traffic+=new float2(2,0);
|
||||||
client.Send(new byte[]{0x01, 0x02}, KcpChannel.Reliable);
|
_client.Send(new byte[]{0x01, 0x02}, KcpChannel.Reliable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -101,7 +101,7 @@ namespace BITKit.Net
|
||||||
BIT4Log.Log<KCPNetServer>($"{Name}:链接{id}超时,已断开");
|
BIT4Log.Log<KCPNetServer>($"{Name}:链接{id}超时,已断开");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server.IsActive() is false || ManualTick) return;
|
if (server.IsActive() is false) return;
|
||||||
|
|
||||||
server.Tick();
|
server.Tick();
|
||||||
|
|
||||||
|
@ -150,9 +150,11 @@ namespace BITKit.Net
|
||||||
_timer.Interval = 1000f / TickRate;
|
_timer.Interval = 1000f / TickRate;
|
||||||
_interval = TimeSpan.FromSeconds(1.0 / TickRate);
|
_interval = TimeSpan.FromSeconds(1.0 / TickRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
OnStartServer?.Invoke();
|
OnStartServer?.Invoke();
|
||||||
server.Start(port);
|
server.Start(port);
|
||||||
_timer.Start();
|
if (ManualTick is false)
|
||||||
|
_timer.Start();
|
||||||
_isStarted = true;
|
_isStarted = true;
|
||||||
BIT4Log.Log<KCPNetServer>($"已启动KCP服务器:{port}");
|
BIT4Log.Log<KCPNetServer>($"已启动KCP服务器:{port}");
|
||||||
}
|
}
|
||||||
|
@ -551,14 +553,14 @@ namespace BITKit.Net
|
||||||
{
|
{
|
||||||
foreach (var methodInfo in rpcHandle.GetType().GetMethods())
|
foreach (var methodInfo in rpcHandle.GetType().GetMethods())
|
||||||
{
|
{
|
||||||
var att = methodInfo.GetCustomAttribute<NetRpcAttribute>();
|
var att = methodInfo.GetCustomAttribute<NetRpcAttribute>(true);
|
||||||
if(att is null)continue;
|
if(att is null)continue;
|
||||||
_rpcMethods.TryAdd(methodInfo.Name, methodInfo);
|
_rpcMethods.TryAdd(methodInfo.Name, methodInfo);
|
||||||
_rpcHandles.TryAdd(methodInfo.Name, rpcHandle);
|
_rpcHandles.TryAdd(methodInfo.Name, rpcHandle);
|
||||||
}
|
}
|
||||||
foreach (var eventInfo in rpcHandle.GetType().GetEvents())
|
foreach (var eventInfo in rpcHandle.GetType().GetEvents())
|
||||||
{
|
{
|
||||||
var att = eventInfo.GetCustomAttribute<NetRpcAttribute>();
|
var att = eventInfo.GetCustomAttribute<NetRpcAttribute>(true);
|
||||||
if(att is null)continue;
|
if(att is null)continue;
|
||||||
|
|
||||||
_rpcEvents.TryAdd(eventInfo.Name, eventInfo);
|
_rpcEvents.TryAdd(eventInfo.Name, eventInfo);
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: a3e65b7e409c5ce40b5ce927156ae2ad
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -147,6 +147,21 @@ namespace BITKit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<T> SelectManyPro<T>(this IEnumerable<T> self, Func<T, IEnumerable<T>> factory)
|
||||||
|
{
|
||||||
|
return Get(self);
|
||||||
|
IEnumerable<T> Get(IEnumerable<T> list)
|
||||||
|
{
|
||||||
|
var newList = new List<T>();
|
||||||
|
foreach (var x in list)
|
||||||
|
{
|
||||||
|
newList.Add(x);
|
||||||
|
newList.AddRange(Get(factory.Invoke(x)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return newList.Distinct();
|
||||||
|
}
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取集合中所有的组合,每个组合中的元素个数为输入集合的元素个数,每个元素只出现一次
|
/// 获取集合中所有的组合,每个组合中的元素个数为输入集合的元素个数,每个元素只出现一次
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -126,7 +126,7 @@ namespace BITKit.Mod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ModService
|
public partial class ModService
|
||||||
{
|
{
|
||||||
public static async UniTask<ModPackage[]> SearchPackages()
|
public static async UniTask<ModPackage[]> SearchPackages()
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BITKit.Mod
|
||||||
|
{
|
||||||
|
public partial class ModService
|
||||||
|
{
|
||||||
|
public static Func<string, UniTask<object>> LoadAssetAsyncFactory;
|
||||||
|
|
||||||
|
public static async UniTask<T> LoadAsset<T>(string location) where T : class
|
||||||
|
{
|
||||||
|
foreach (var func in LoadAssetAsyncFactory.CastAsFunc())
|
||||||
|
{
|
||||||
|
var value = await func.Invoke(location);
|
||||||
|
if (value is T value1)
|
||||||
|
{
|
||||||
|
return value1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception($"Asset not found: {location}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: e0adbb35ce4784342a0ed37ac4a56200
|
guid: c63d2ab8d0ff2304e980bb1e0585c903
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
|
@ -1,5 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using Microsoft.SqlServer.Server;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
@ -7,84 +9,103 @@ using Newtonsoft.Json.Linq;
|
||||||
namespace BITKit
|
namespace BITKit
|
||||||
// ReSharper restore CheckNamespace
|
// ReSharper restore CheckNamespace
|
||||||
{
|
{
|
||||||
public record ContextModel
|
public record ContextModel:IBinarySerialize
|
||||||
|
|
||||||
{
|
{
|
||||||
public static ContextModel Get(object data)
|
public static ContextModel Get(object data)
|
||||||
|
{
|
||||||
|
return new ContextModel()
|
||||||
{
|
{
|
||||||
return new ContextModel()
|
StatusCode = 200,
|
||||||
{
|
Message = "success",
|
||||||
StatusCode = 200,
|
Data = data
|
||||||
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)
|
|
||||||
{
|
|
||||||
BIT4Log.Warning(json);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static implicit operator string(ContextModel self)
|
|
||||||
{
|
|
||||||
return self.ToString();
|
|
||||||
}
|
|
||||||
#if NET5_0_OR_GREATER
|
|
||||||
public static implicit operator HttpContent(ContextModel self)
|
|
||||||
{
|
|
||||||
return new StringContent(self, System.Text.Encoding.UTF8, "application/json");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public override string ToString()
|
public static ContextModel Error(string message)
|
||||||
|
{
|
||||||
|
return new ContextModel()
|
||||||
{
|
{
|
||||||
return JsonConvert.SerializeObject(this);
|
StatusCode = 500,
|
||||||
}
|
Message = message,
|
||||||
|
Data = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
[JsonProperty("status_code")]
|
public static ContextModel GetFromJson(string json)
|
||||||
public int StatusCode=200;
|
{
|
||||||
[JsonProperty("message")]
|
try
|
||||||
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)
|
var result = new ContextModel();
|
||||||
{
|
var jObject = JObject.Parse(json);
|
||||||
case T t:
|
if (jObject.TryGetValue("status_code", out var statusCode))
|
||||||
value = t;
|
result.StatusCode = statusCode.Value<int>();
|
||||||
return true;
|
if (jObject.TryGetValue("message", out var message))
|
||||||
case JToken jToken:
|
result.Message = message.Value<string>();
|
||||||
value = jToken.ToObject<T>();
|
if (jObject.TryGetValue("data", out var data))
|
||||||
return true;
|
result.Data = data;
|
||||||
default:
|
return JsonConvert.DeserializeObject<ContextModel>(json);
|
||||||
value = default;
|
}
|
||||||
return false;
|
catch (Exception)
|
||||||
}
|
{
|
||||||
|
BIT4Log.Warning(json);
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static implicit operator string(ContextModel self)
|
||||||
|
{
|
||||||
|
return self.ToString();
|
||||||
|
}
|
||||||
|
#if NET5_0_OR_GREATER
|
||||||
|
public static implicit operator HttpContent(ContextModel self)
|
||||||
|
{
|
||||||
|
return new StringContent(self, System.Text.Encoding.UTF8, "application/json");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return JsonConvert.SerializeObject(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonProperty("status_code")] public int StatusCode = 200;
|
||||||
|
[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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Read(BinaryReader r)
|
||||||
|
{
|
||||||
|
StatusCode = r.ReadInt32();
|
||||||
|
Message = r.ReadString();
|
||||||
|
Data = r.ReadBoolean() ? BITBinary.Read(r) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(BinaryWriter w)
|
||||||
|
{
|
||||||
|
w.Write(StatusCode);
|
||||||
|
w.Write(Message);
|
||||||
|
w.Write(Data is not null);
|
||||||
|
if (Data is not null)
|
||||||
|
{
|
||||||
|
BITBinary.Write(w, Data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
|
||||||
|
namespace BITKit
|
||||||
|
{
|
||||||
|
public class NetOfflineException : System.Exception
|
||||||
|
{
|
||||||
|
public NetOfflineException() : base("Client is not connected") { }
|
||||||
|
}
|
||||||
|
public class NetAuthorizeException : System.Exception
|
||||||
|
{
|
||||||
|
public NetAuthorizeException() : base("Client is not authorized") { }
|
||||||
|
}
|
||||||
|
public abstract class NetAuthorityException : System.Exception
|
||||||
|
{
|
||||||
|
protected NetAuthorityException(string message =null) : base(string.IsNullOrEmpty(message)?"Authority is not valid":message) { }
|
||||||
|
}
|
||||||
|
public class NetClientOnlyException : NetAuthorityException
|
||||||
|
{
|
||||||
|
public NetClientOnlyException() : base("This method is only available on client") { }
|
||||||
|
}
|
||||||
|
public class NetServerOnlyException : NetAuthorityException
|
||||||
|
{
|
||||||
|
public NetServerOnlyException() : base("This method is only available on server") { }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 618a48f7c780dd148ae1fa0fba95b583
|
guid: d38fad9bff7582b4b8287df7c47a47b7
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
|
@ -18,7 +18,14 @@ namespace BITKit
|
||||||
[AttributeUsage(AttributeTargets.Method|AttributeTargets.Event)]
|
[AttributeUsage(AttributeTargets.Method|AttributeTargets.Event)]
|
||||||
public sealed class NetRpcAttribute : Attribute
|
public sealed class NetRpcAttribute : Attribute
|
||||||
{
|
{
|
||||||
|
public readonly bool AddTypeNamePrefix;
|
||||||
|
public NetRpcAttribute()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public NetRpcAttribute(bool addTypeNamePrefix)
|
||||||
|
{
|
||||||
|
AddTypeNamePrefix = addTypeNamePrefix;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 帮助类
|
/// 帮助类
|
||||||
|
@ -84,7 +91,6 @@ namespace BITKit
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface INetProvider
|
public interface INetProvider
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 向服务端发送指令
|
/// 向服务端发送指令
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -192,6 +198,10 @@ namespace BITKit
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface INetServer
|
public interface INetServer
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 通信接口
|
||||||
|
/// </summary>
|
||||||
|
public INetProvider NetProvider=>this as INetProvider;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 源物体,用于通过代理直接访问
|
/// 源物体,用于通过代理直接访问
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -274,6 +284,10 @@ namespace BITKit
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface INetClient
|
public interface INetClient
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 通讯接口
|
||||||
|
/// </summary>
|
||||||
|
public INetProvider NetProvider=>this as INetProvider;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 源物体,用于通过代理直接访问
|
/// 源物体,用于通过代理直接访问
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -318,85 +332,4 @@ namespace BITKit
|
||||||
/// <param name="message">消息</param>
|
/// <param name="message">消息</param>
|
||||||
void SendServerMessage(string message);
|
void SendServerMessage(string message);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UNITY
|
|
||||||
/// <summary>
|
|
||||||
/// 有关NetProvider的Unity代理
|
|
||||||
/// </summary>
|
|
||||||
[Serializable]
|
|
||||||
public class NetProviderProxy : INetProvider
|
|
||||||
{
|
|
||||||
[SerializeField] private MonoBehaviour monoBehaviour;
|
|
||||||
INetProvider netProvider => monoBehaviour as INetProvider;
|
|
||||||
void INetProvider.ServerCommand<T>(T command) => netProvider.ServerCommand(command);
|
|
||||||
void INetProvider.RpcClientCommand<T>(T command) => netProvider.RpcClientCommand(command);
|
|
||||||
void INetProvider.ClientCommand<T>(int id, T command) => netProvider.ClientCommand(id, command);
|
|
||||||
|
|
||||||
async UniTask<T> INetProvider.GetFromServer<T>(string addressablePath) =>
|
|
||||||
await netProvider.GetFromServer<T>(addressablePath);
|
|
||||||
|
|
||||||
UniTask<T> INetProvider.GetFromClient<T>(int id, string addressablePath) =>
|
|
||||||
netProvider.GetFromClient<T>(id, addressablePath);
|
|
||||||
|
|
||||||
void INetProvider.AddRpcHandle(object rpcHandle) => netProvider.AddRpcHandle(rpcHandle);
|
|
||||||
|
|
||||||
void INetProvider.AddCommandListener<T>(Action<T> handle) => netProvider.AddCommandListener<T>(handle);
|
|
||||||
|
|
||||||
void INetProvider.RemoveCommandListener<T>(Action<T> handle) => netProvider.RemoveCommandListener<T>(handle);
|
|
||||||
|
|
||||||
void INetProvider.SendRT(string rpcName, params object[] pars) => netProvider.SendRT(rpcName, pars);
|
|
||||||
|
|
||||||
void INetProvider.SendTargetRT(int id, string rpcName, params object[] pars) =>
|
|
||||||
netProvider.SendTargetRT(id, rpcName, pars);
|
|
||||||
|
|
||||||
void INetProvider.SendAllRT(string rpcName, params object[] pars) => netProvider.SendAllRT(rpcName, pars);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 有关Unity的NetClient的代理
|
|
||||||
/// </summary>
|
|
||||||
[Serializable]
|
|
||||||
public class GDNetClientProxy : INetClient
|
|
||||||
{
|
|
||||||
[SerializeField] private MonoBehaviour monoBehaviour;
|
|
||||||
private INetClient _netClientImplementation=>monoBehaviour as INetClient;
|
|
||||||
event Action INetClient.OnStartConnect
|
|
||||||
{
|
|
||||||
add => _netClientImplementation.OnStartConnect += value;
|
|
||||||
remove => _netClientImplementation.OnStartConnect -= value;
|
|
||||||
}
|
|
||||||
|
|
||||||
event Action INetClient.OnConnected
|
|
||||||
{
|
|
||||||
add => _netClientImplementation.OnConnected += value;
|
|
||||||
remove => _netClientImplementation.OnConnected -= value;
|
|
||||||
}
|
|
||||||
|
|
||||||
event Action INetClient.OnDisconnected
|
|
||||||
{
|
|
||||||
add => _netClientImplementation.OnDisconnected += value;
|
|
||||||
remove => _netClientImplementation.OnDisconnected -= value;
|
|
||||||
}
|
|
||||||
|
|
||||||
event Action INetClient.OnConnectedFailed
|
|
||||||
{
|
|
||||||
add => _netClientImplementation.OnConnectedFailed += value;
|
|
||||||
remove => _netClientImplementation.OnConnectedFailed -= value;
|
|
||||||
}
|
|
||||||
|
|
||||||
UniTask<bool> INetClient.Connect(string address, ushort port)
|
|
||||||
{
|
|
||||||
return _netClientImplementation.Connect(address, port);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool INetClient.IsConnected => _netClientImplementation.IsConnected;
|
|
||||||
|
|
||||||
int INetClient.Ping => _netClientImplementation.Ping;
|
|
||||||
public int Id => _netClientImplementation.Id;
|
|
||||||
void INetClient.Disconnect()
|
|
||||||
{
|
|
||||||
_netClientImplementation.Disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: bd95732fea121104b8f974d4b29a9325
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: fa022cf4131f15247b756ad81daac733
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: bc8df90017042c340a06728f62ed53af
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: e61132c5a20b1cd429a70da257582959
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: d543b75a249edac42bc53defe955e9fa
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: e517c312e735e1042b911efc79deb1f6
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 2f1e118cfd267c74abc0e9464f5088ea
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: a8711b7cfbb88574d928e3ba11162109
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 3cb533c3705546949815e7583cdfc65b
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,178 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace BITKit
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 属性接口,用于序列化引用
|
|
||||||
/// </summary>
|
|
||||||
public interface IProperty
|
|
||||||
{
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// 属性接口
|
|
||||||
/// GetOrCreate(√)
|
|
||||||
/// GetOrAdd(√)
|
|
||||||
/// TryGet(√)
|
|
||||||
/// TryRemove(√)
|
|
||||||
/// TrySet(√)
|
|
||||||
/// GetProperties(√)
|
|
||||||
/// </summary>
|
|
||||||
public interface IPropertable
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 是否拥有属性
|
|
||||||
/// </summary>
|
|
||||||
bool Contains<T>();
|
|
||||||
/// <summary>
|
|
||||||
/// 获取或创建属性
|
|
||||||
/// </summary>
|
|
||||||
T GetOrCreateProperty<T>();
|
|
||||||
/// <summary>
|
|
||||||
/// 获取或通过工厂方法添加属性
|
|
||||||
/// </summary>
|
|
||||||
T GetOrAddProperty<T>(Func<T> addFactory);
|
|
||||||
/// <summary>
|
|
||||||
/// 尝试获取属性
|
|
||||||
/// </summary>
|
|
||||||
bool TryGetProperty<T>(out T value);
|
|
||||||
/// <summary>
|
|
||||||
/// 尝试移除属性
|
|
||||||
/// </summary>
|
|
||||||
bool TryRemoveProperty<T>();
|
|
||||||
/// <summary>
|
|
||||||
/// 尝试设置属性
|
|
||||||
/// </summary>
|
|
||||||
bool TrySetProperty<T>(T value);
|
|
||||||
/// <summary>
|
|
||||||
/// 获取所有属性
|
|
||||||
/// </summary>
|
|
||||||
object[] GetProperties();
|
|
||||||
/// <summary>
|
|
||||||
/// 清除所有属性
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
bool ClearProperties();
|
|
||||||
/// <summary>
|
|
||||||
/// 从其他对象复制属性
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="propertable"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
bool CopyPropertiesFrom(IPropertable propertable);
|
|
||||||
}
|
|
||||||
public class Property : IPropertable
|
|
||||||
{
|
|
||||||
public Property() { }
|
|
||||||
public Property(IEnumerable<object> factory)
|
|
||||||
{
|
|
||||||
foreach (var x in factory)
|
|
||||||
{
|
|
||||||
properties.Add(x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private readonly List<object> properties=new();
|
|
||||||
public T GetProperty<T>()
|
|
||||||
{
|
|
||||||
return properties.OfType<T>().First();
|
|
||||||
}
|
|
||||||
public void SetProperty<T>(T value)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < properties.Count; i++)
|
|
||||||
{
|
|
||||||
if (properties[i] is T)
|
|
||||||
properties[i] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public bool Contains<T>()
|
|
||||||
{
|
|
||||||
return properties.OfType<T>().FirstOrDefault() is not null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T GetOrCreateProperty<T>()
|
|
||||||
{
|
|
||||||
return GetOrAddProperty(Activator.CreateInstance<T>);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T GetOrAddProperty<T>(Func<T> addFactory)
|
|
||||||
{
|
|
||||||
foreach (var obj in properties)
|
|
||||||
{
|
|
||||||
if (obj is T t) return t;
|
|
||||||
}
|
|
||||||
T x;
|
|
||||||
properties.Add(x = addFactory.Invoke());
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryGetProperty<T>(out T value)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
value = properties.OfType<T>().First();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (InvalidOperationException)
|
|
||||||
{
|
|
||||||
value = default;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public bool TryRemoveProperty<T>()
|
|
||||||
{
|
|
||||||
var removed=false;
|
|
||||||
foreach (var value in properties.OfType<T>().ToArray())
|
|
||||||
{
|
|
||||||
properties.Remove(value);
|
|
||||||
removed = true;
|
|
||||||
}
|
|
||||||
// if(properties.TryGetValue(typeof(T).FullName, out var x))
|
|
||||||
// {
|
|
||||||
// properties.Remove(typeof(T).Name);
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
return removed;
|
|
||||||
}
|
|
||||||
public bool TrySetProperty<T>(T value)
|
|
||||||
{
|
|
||||||
var current = properties.OfType<T>().FirstOrDefault();
|
|
||||||
if (current is not null)
|
|
||||||
{
|
|
||||||
properties.Remove(current);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
properties.Add(value);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public object[] GetProperties() => properties.ToArray();
|
|
||||||
|
|
||||||
public void Read(BinaryReader r)
|
|
||||||
{
|
|
||||||
foreach (var x in properties)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write(BinaryWriter w)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ClearProperties()
|
|
||||||
{
|
|
||||||
properties.Clear();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CopyPropertiesFrom(IPropertable propertable)
|
|
||||||
{
|
|
||||||
ClearProperties();
|
|
||||||
properties.AddRange( propertable.GetProperties());;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 0ad3cecd07fd75744b93174b03537005
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 0a9ce048cccddfd42972d7502f096e77
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,34 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
namespace BITKit
|
|
||||||
{
|
|
||||||
public enum SelectionState
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
Hover,
|
|
||||||
Active,
|
|
||||||
Inactive,
|
|
||||||
Focus,
|
|
||||||
Selected,
|
|
||||||
Enabled,
|
|
||||||
Checked,
|
|
||||||
Root,
|
|
||||||
}
|
|
||||||
public interface ISelectable
|
|
||||||
{
|
|
||||||
#if UNITY_5_3_OR_NEWER
|
|
||||||
UnityEngine.Transform Transform { get; }
|
|
||||||
#endif
|
|
||||||
void SetSelectionState(SelectionState state);
|
|
||||||
event Action OnNone;
|
|
||||||
event Action OnHover;
|
|
||||||
event Action OnActive;
|
|
||||||
event Action OnInactive;
|
|
||||||
event Action OnFocus;
|
|
||||||
event Action OnSelected;
|
|
||||||
event Action OnEnabled;
|
|
||||||
event Action OnChecked;
|
|
||||||
event Action OnRoot;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace BITKit.Selection
|
|
||||||
{
|
|
||||||
public interface ISelector
|
|
||||||
{
|
|
||||||
bool TryGetCurrentSelectable(out ISelectable selectable);
|
|
||||||
event Action<ISelectable> OnNone;
|
|
||||||
event Action<ISelectable> OnHover;
|
|
||||||
event Action<ISelectable> OnActive;
|
|
||||||
event Action<ISelectable> OnInactive;
|
|
||||||
event Action<ISelectable> OnFocus;
|
|
||||||
event Action<ISelectable> OnSelected;
|
|
||||||
event Action<ISelectable> OnEnabled;
|
|
||||||
event Action<ISelectable> OnChecked;
|
|
||||||
event Action<ISelectable> OnRoot;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: e55e58ac133e98749bdeb60064d42ace
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 0710a77f8ae8f894781e9aa63f26d36b
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: bfcd8de179791a8449cfd82153de4999
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 088acda9508faea49be2d9f04eb1308e
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace BITKit
|
namespace BITKit
|
||||||
{
|
{
|
||||||
|
@ -26,6 +27,11 @@ namespace BITKit
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="action"></param>
|
/// <param name="action"></param>
|
||||||
void Remove(Action<float> action);
|
void Remove(Action<float> action);
|
||||||
|
/// <summary>
|
||||||
|
/// 手动调用循环
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="delta"></param>
|
||||||
|
void ManualTick(float delta);
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 主线程循环
|
/// 主线程循环
|
||||||
|
@ -35,4 +41,40 @@ namespace BITKit
|
||||||
/// 线程池循环
|
/// 线程池循环
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IThreadTicker : ITicker { }
|
public interface IThreadTicker : ITicker { }
|
||||||
|
|
||||||
|
|
||||||
|
#if UNITY_5_3_OR_NEWER
|
||||||
|
/// <summary>
|
||||||
|
/// 最后执行的循环,通常用于旋转、位移等
|
||||||
|
/// </summary>
|
||||||
|
public interface IAfterTicker : ITicker{}
|
||||||
|
/// <summary>
|
||||||
|
/// Unity专用固定循环
|
||||||
|
/// </summary>
|
||||||
|
public interface IFixedTicker : ITicker{}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
public class Ticker : ITicker
|
||||||
|
{
|
||||||
|
private readonly Queue<Action> _queue = new();
|
||||||
|
private event Action<float> TickEvents;
|
||||||
|
public ulong TickCount { get; private set; }
|
||||||
|
public void Add(Action action)
|
||||||
|
{
|
||||||
|
_queue.Enqueue(action);
|
||||||
|
}
|
||||||
|
public void Add(Action<float> action)=>TickEvents += action;
|
||||||
|
public void Remove(Action<float> action)=>TickEvents -= action;
|
||||||
|
|
||||||
|
public void ManualTick(float delta)
|
||||||
|
{
|
||||||
|
TickCount++;
|
||||||
|
while (_queue.TryDequeue(out var action))
|
||||||
|
{
|
||||||
|
action.Invoke();
|
||||||
|
}
|
||||||
|
TickEvents?.Invoke(delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
using System;
|
||||||
|
using BITKit;
|
||||||
|
using Timer = System.Timers.Timer;
|
||||||
|
|
||||||
|
namespace BITKit
|
||||||
|
{
|
||||||
|
public class TimerTicker:ITicker
|
||||||
|
{
|
||||||
|
public TimerTicker()
|
||||||
|
{
|
||||||
|
_timer = new Timer();
|
||||||
|
_timer.Elapsed += (sender, args) =>
|
||||||
|
{
|
||||||
|
OnTick();
|
||||||
|
if (_timer.Enabled && _timer.AutoReset is false)
|
||||||
|
{
|
||||||
|
_timer.Start();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public int TickRate { get; set; }
|
||||||
|
public ulong TickCount { get; private set; }
|
||||||
|
private readonly Timer _timer;
|
||||||
|
private float _deltaTime;
|
||||||
|
private event Action<float> Tick;
|
||||||
|
public void Add(Action action)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(Action<float> action)
|
||||||
|
{
|
||||||
|
Tick += action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Remove(Action<float> action)
|
||||||
|
{
|
||||||
|
Tick -= action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ManualTick(float delta)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
_deltaTime = 1f / TickRate;
|
||||||
|
_timer.Interval = TimeSpan.FromSeconds(_deltaTime).TotalMilliseconds;
|
||||||
|
_timer.Enabled = true;
|
||||||
|
}
|
||||||
|
private void OnTick()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TickCount++;
|
||||||
|
Tick?.Invoke(_deltaTime);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
BIT4Log.LogException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
_timer.Enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: eb2d5a09faa2e9a41858ff98770b423c
|
guid: e07078010581a9b4481480587c1f6c64
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: e42b9df1bf3976e4e87a36eeaf8e1fb7
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -19,10 +19,6 @@ namespace BITKit.UX
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool IsWindow { get; }
|
bool IsWindow { get; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 该面板是否有效,用于检查该面板是否已经被销毁
|
|
||||||
/// </summary>
|
|
||||||
//bool IsValid { get; }
|
|
||||||
/// <summary>
|
|
||||||
/// 该面板的索引(入口,Key)
|
/// 该面板的索引(入口,Key)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string Index { get; }
|
string Index { get; }
|
||||||
|
@ -38,77 +34,15 @@ namespace BITKit.UX
|
||||||
/// 事件回调,当面板被打开时触发
|
/// 事件回调,当面板被打开时触发
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event Action OnEntry;
|
event Action OnEntry;
|
||||||
|
event Func<UniTask> OnEntryAsync;
|
||||||
|
event Action OnEntryCompleted;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 事件回调,当面板被关闭时触发
|
/// 事件回调,当面板被关闭时触发
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event Action OnExit;
|
event Action OnExit;
|
||||||
|
|
||||||
void OnUpdate(float deltaTime);
|
event Func<UniTask> OnExitAsync;
|
||||||
}
|
event Action OnExitCompleted;
|
||||||
public abstract class UXPanelImplement:IUXPanel
|
void OnTick(float deltaTime);
|
||||||
{
|
|
||||||
protected abstract IUXPanel service { get; }
|
|
||||||
private IUXPanel _iuxPanelImplementation => service;
|
|
||||||
public bool IsWindow=>_iuxPanelImplementation.IsWindow;
|
|
||||||
//public bool IsValid => _iuxPanelImplementation.IsValid;
|
|
||||||
|
|
||||||
public string Index => _iuxPanelImplementation.Index;
|
|
||||||
|
|
||||||
public bool AllowCursor => _iuxPanelImplementation.AllowCursor;
|
|
||||||
|
|
||||||
public bool AllowInput => _iuxPanelImplementation.AllowInput;
|
|
||||||
|
|
||||||
public bool IsEntered
|
|
||||||
{
|
|
||||||
get => service.IsEntered;
|
|
||||||
set => service.IsEntered = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Entry()
|
|
||||||
{
|
|
||||||
_iuxPanelImplementation.Entry();
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniTask EntryAsync()
|
|
||||||
{
|
|
||||||
return service.EntryAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Entered()
|
|
||||||
{
|
|
||||||
service.Entered();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Exit()
|
|
||||||
{
|
|
||||||
_iuxPanelImplementation.Exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniTask ExitAsync()
|
|
||||||
{
|
|
||||||
return service.ExitAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Exited()
|
|
||||||
{
|
|
||||||
service.Exited();
|
|
||||||
}
|
|
||||||
|
|
||||||
public event Action OnEntry
|
|
||||||
{
|
|
||||||
add => _iuxPanelImplementation.OnEntry += value;
|
|
||||||
remove => _iuxPanelImplementation.OnEntry -= value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public event Action OnExit
|
|
||||||
{
|
|
||||||
add => _iuxPanelImplementation.OnExit += value;
|
|
||||||
remove => _iuxPanelImplementation.OnExit -= value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnUpdate(float deltaTime)
|
|
||||||
{
|
|
||||||
service.OnUpdate(deltaTime);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,19 @@
|
||||||
|
using System;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
|
||||||
namespace BITKit.UX
|
namespace BITKit.UX
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 基本UX服务(GUI管理器),主要通过加载叠加面板实现
|
/// 基本UX服务(GUI管理器),主要通过加载叠加面板实现
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IUXService
|
public interface IUXService:IDisposable
|
||||||
{
|
{
|
||||||
|
object Root { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
UniTask InitializeAsync();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 注册面板,加入注册队列
|
/// 注册面板,加入注册队列
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -8,7 +8,11 @@ namespace BITKit.UX
|
||||||
{
|
{
|
||||||
string Message { get; set; }
|
string Message { get; set; }
|
||||||
object Container { get; }
|
object Container { get; }
|
||||||
public void SetMessage(string message)=>Message=message;
|
public IUXWaitingHandle SetMessage(string message)
|
||||||
|
{
|
||||||
|
Message=message;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public interface IUXWaiting
|
public interface IUXWaiting
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 429ce01eb2ea7ac4b99ea7adc32c2c71
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 9c82261b9903a8c42a7e217940015c26
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 87bc33909c0bd1c49987c7095fb608c2
|
guid: 6a9ecef037d512f40886666749c60d48
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
|
@ -1,12 +1,10 @@
|
||||||
{
|
{
|
||||||
"name": "BITKit.MotionMatching",
|
"name": "BITKit.WorldNode",
|
||||||
"rootNamespace": "",
|
"rootNamespace": "",
|
||||||
"references": [
|
"references": [
|
||||||
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
|
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
|
||||||
"GUID:d525ad6bd40672747bde77962f1c401e",
|
|
||||||
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
|
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
|
||||||
"GUID:e34a5702dd353724aa315fb8011f08c3",
|
"GUID:d8b63aba1907145bea998dd612889d6b"
|
||||||
"GUID:296866320aab85a42a0403bf684bac59"
|
|
||||||
],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 9f93c330bf016d047a49b0c29307ef42
|
guid: d750d221812bb1d48baff92e6ef73e28
|
||||||
AssemblyDefinitionImporter:
|
AssemblyDefinitionImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
|
@ -0,0 +1,19 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace BITKit.WorldNode
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 世界节点
|
||||||
|
/// </summary>
|
||||||
|
public interface IWorldNode
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public object WorldObject { get; set; }
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 119f6a0b25fc0cc47b6f950cd9902aba
|
guid: 051c8f58c08cb14449b4da1aca114caf
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
|
@ -0,0 +1,41 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace BITKit.WorldNode
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 世界节点服务,所有动态世界节点通过此接口注册
|
||||||
|
/// </summary>
|
||||||
|
public interface IWorldNodeService
|
||||||
|
{
|
||||||
|
public IReadOnlyDictionary<int, IWorldNode> WorldNodes { get; }
|
||||||
|
public void RegisterNode(IWorldNode node);
|
||||||
|
public event Action<IWorldNode> OnNodeRegistered;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 世界节点默认实现
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
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();
|
||||||
|
public void RegisterNode(IWorldNode node)
|
||||||
|
{
|
||||||
|
OnNodeRegistered?.Invoke(node);
|
||||||
|
WorldNodes.TryAdd(node.Id, node);
|
||||||
|
}
|
||||||
|
event Action<IWorldNode> IWorldNodeService.OnNodeRegistered
|
||||||
|
{
|
||||||
|
add=>OnNodeRegistered+=value;
|
||||||
|
remove=>OnNodeRegistered-=value;
|
||||||
|
}
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
WorldNodes.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ca82e09109a03de47b638f35b49b59e5
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,53 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
#if UNITY_5_3_OR_NEWER
|
||||||
|
using UnityEngine;
|
||||||
|
#endif
|
||||||
|
namespace BITKit.WorldNode
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public struct WorldInfoNode : IWorldNode
|
||||||
|
{
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
#if UNITY_5_3_OR_NEWER
|
||||||
|
[SerializeReference,SubclassSelector]
|
||||||
|
#endif
|
||||||
|
private IReference name;
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
#if UNITY_5_3_OR_NEWER
|
||||||
|
[SerializeReference,SubclassSelector]
|
||||||
|
#endif
|
||||||
|
private IReference description;
|
||||||
|
public int Id { get; set; }
|
||||||
|
public object WorldObject { get; set; }
|
||||||
|
public string Name => name?.Value;
|
||||||
|
public string Description => description?.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class WorldInfoNodeService : IDisposable
|
||||||
|
{
|
||||||
|
public IReadOnlyDictionary<int, WorldInfoNode> WorldInfoNodes => _infoNodes;
|
||||||
|
private readonly IWorldNodeService _worldNodeService;
|
||||||
|
private readonly ConcurrentDictionary<int, WorldInfoNode> _infoNodes = new();
|
||||||
|
|
||||||
|
public WorldInfoNodeService(IWorldNodeService worldNodeService)
|
||||||
|
{
|
||||||
|
_worldNodeService = worldNodeService;
|
||||||
|
|
||||||
|
_worldNodeService.OnNodeRegistered += OnNodeRegistered;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnNodeRegistered(IWorldNode obj)
|
||||||
|
{
|
||||||
|
if (obj is not WorldInfoNode infoNode) return;
|
||||||
|
_infoNodes.TryAdd(obj.Id, infoNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_infoNodes.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 132a27b99db1e664692937ec23f40676
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,18 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace BITKit.WorldNode
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public struct WorldInfoPlayerStart:IWorldNode
|
||||||
|
{
|
||||||
|
public static WorldInfoPlayerStart Current { get; set; }
|
||||||
|
public int Id { get; set; }
|
||||||
|
public object WorldObject { get; set; }
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
Current = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bb1616e9308157b43b675b2830b6da23
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,26 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Unity.Mathematics;
|
||||||
|
#if UNITY_5_3_OR_NEWER
|
||||||
|
using UnityEngine;
|
||||||
|
#endif
|
||||||
|
namespace BITKit.WorldNode
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public struct WorldPortalNode:IWorldNode
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 目标地图名称,为空则保留该地图
|
||||||
|
/// </summary>
|
||||||
|
#if UNITY_5_3_OR_NEWER
|
||||||
|
[SerializeReference,SubclassSelector]
|
||||||
|
#endif
|
||||||
|
public IReference MapName;
|
||||||
|
public float3 Position;
|
||||||
|
public float3 EulerAngle;
|
||||||
|
public int Id { get; set; }
|
||||||
|
public object WorldObject { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: cd869f7557b7c4f4a889a1103ce044d3
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: f6f2e220c849a4440877e3b2ce108d13
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
Before Width: | Height: | Size: 307 B After Width: | Height: | Size: 307 B |
Before Width: | Height: | Size: 583 B After Width: | Height: | Size: 583 B |
Before Width: | Height: | Size: 187 B After Width: | Height: | Size: 187 B |
Before Width: | Height: | Size: 208 B After Width: | Height: | Size: 208 B |
Before Width: | Height: | Size: 111 B After Width: | Height: | Size: 111 B |
Before Width: | Height: | Size: 128 B After Width: | Height: | Size: 128 B |
Before Width: | Height: | Size: 197 B After Width: | Height: | Size: 197 B |
Before Width: | Height: | Size: 201 B After Width: | Height: | Size: 201 B |
Before Width: | Height: | Size: 145 B After Width: | Height: | Size: 145 B |
Before Width: | Height: | Size: 150 B After Width: | Height: | Size: 150 B |
Before Width: | Height: | Size: 151 B After Width: | Height: | Size: 151 B |