mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-14 16:51:28 +00:00
[+] 接入ET8服务端
[+] 接入ET8服务端
This commit is contained in:
9
Assets/GameScripts/DotNet/Model/Share/ConstFiberId.cs
Normal file
9
Assets/GameScripts/DotNet/Model/Share/ConstFiberId.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace ET
|
||||
{
|
||||
public static class ConstFiberId
|
||||
{
|
||||
public const int Main = -1;
|
||||
public const int NetClient = -2;
|
||||
public const int DB = -3;
|
||||
}
|
||||
}
|
11
Assets/GameScripts/DotNet/Model/Share/ConstFiberId.cs.meta
Normal file
11
Assets/GameScripts/DotNet/Model/Share/ConstFiberId.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a5e2228e988db544687281f0ff80f009
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/GameScripts/DotNet/Model/Share/Demo.meta
Normal file
8
Assets/GameScripts/DotNet/Model/Share/Demo.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cef1faf005614e1498e553b563fae673
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
38
Assets/GameScripts/DotNet/Model/Share/Demo/EventType.cs
Normal file
38
Assets/GameScripts/DotNet/Model/Share/Demo/EventType.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
namespace ET
|
||||
{
|
||||
namespace EventType
|
||||
{
|
||||
public struct SceneChangeStart
|
||||
{
|
||||
}
|
||||
|
||||
public struct SceneChangeFinish
|
||||
{
|
||||
}
|
||||
|
||||
public struct AfterCreateClientScene
|
||||
{
|
||||
}
|
||||
|
||||
public struct AfterCreateCurrentScene
|
||||
{
|
||||
}
|
||||
|
||||
public struct AppStartInitFinish
|
||||
{
|
||||
}
|
||||
|
||||
public struct LoginFinish
|
||||
{
|
||||
}
|
||||
|
||||
public struct EnterMapFinish
|
||||
{
|
||||
}
|
||||
|
||||
public struct AfterUnitCreate
|
||||
{
|
||||
public Unit Unit;
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/GameScripts/DotNet/Model/Share/Demo/EventType.cs.meta
Normal file
11
Assets/GameScripts/DotNet/Model/Share/Demo/EventType.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3bd7b14de3c7c874d9f2b5411204ddb1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
58
Assets/GameScripts/DotNet/Model/Share/Entry.cs
Normal file
58
Assets/GameScripts/DotNet/Model/Share/Entry.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using System.IO;
|
||||
using MemoryPack;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
namespace EventType
|
||||
{
|
||||
public struct EntryEvent1
|
||||
{
|
||||
}
|
||||
|
||||
public struct EntryEvent2
|
||||
{
|
||||
}
|
||||
|
||||
public struct EntryEvent3
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public static class Entry
|
||||
{
|
||||
public static void Init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void Start()
|
||||
{
|
||||
StartAsync().Coroutine();
|
||||
}
|
||||
|
||||
private static async ETTask StartAsync()
|
||||
{
|
||||
WinPeriod.Init();
|
||||
|
||||
MongoHelper.RegisterStruct<LSInput>();
|
||||
MongoHelper.Register();
|
||||
|
||||
World.Instance.AddSingleton<OpcodeType>();
|
||||
World.Instance.AddSingleton<IdValueGenerater>();
|
||||
World.Instance.AddSingleton<ObjectPool>();
|
||||
World.Instance.AddSingleton<ActorMessageQueue>();
|
||||
World.Instance.AddSingleton<EntitySystemSingleton>();
|
||||
World.Instance.AddSingleton<LSEntitySystemSingleton>();
|
||||
World.Instance.AddSingleton<MessageDispatcherComponent>();
|
||||
World.Instance.AddSingleton<NumericWatcherComponent>();
|
||||
World.Instance.AddSingleton<AIDispatcherComponent>();
|
||||
World.Instance.AddSingleton<ActorMessageDispatcherComponent>();
|
||||
World.Instance.AddSingleton<NetServices>();
|
||||
World.Instance.AddSingleton<NavmeshComponent>();
|
||||
|
||||
World.Instance.AddSingleton<FiberManager>();
|
||||
|
||||
await FiberManager.Instance.Create(SchedulerType.Main, ConstFiberId.Main, 0, SceneType.Main, "");
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/GameScripts/DotNet/Model/Share/Entry.cs.meta
Normal file
11
Assets/GameScripts/DotNet/Model/Share/Entry.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 28ee985a41787a24a8ea3bf87277e7e3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/GameScripts/DotNet/Model/Share/LockStep.meta
Normal file
8
Assets/GameScripts/DotNet/Model/Share/LockStep.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e8c5c383e6c7b48d9ba137530d2e924b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,34 @@
|
||||
namespace ET
|
||||
{
|
||||
public class FixedTimeCounter
|
||||
{
|
||||
private long startTime;
|
||||
private int startFrame;
|
||||
public int Interval { get; private set; }
|
||||
|
||||
public FixedTimeCounter(long startTime, int startFrame, int interval)
|
||||
{
|
||||
this.startTime = startTime;
|
||||
this.startFrame = startFrame;
|
||||
this.Interval = interval;
|
||||
}
|
||||
|
||||
public void ChangeInterval(int interval, int frame)
|
||||
{
|
||||
this.startTime += (frame - this.startFrame) * this.Interval;
|
||||
this.startFrame = frame;
|
||||
this.Interval = interval;
|
||||
}
|
||||
|
||||
public long FrameTime(int frame)
|
||||
{
|
||||
return this.startTime + (frame - this.startFrame) * this.Interval;
|
||||
}
|
||||
|
||||
public void Reset(long time, int frame)
|
||||
{
|
||||
this.startTime = time;
|
||||
this.startFrame = frame;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a78339a190b64d92ba482cd00b239f52
|
||||
timeCreated: 1682422635
|
@@ -0,0 +1,94 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
public class FrameBuffer
|
||||
{
|
||||
public int MaxFrame { get; private set; }
|
||||
private readonly List<OneFrameInputs> frameInputs;
|
||||
private readonly List<MemoryBuffer> snapshots;
|
||||
private readonly List<long> hashs;
|
||||
|
||||
public FrameBuffer(int frame = 0, int capacity = LSConstValue.FrameCountPerSecond * 60)
|
||||
{
|
||||
this.MaxFrame = frame + LSConstValue.FrameCountPerSecond * 30;
|
||||
this.frameInputs = new List<OneFrameInputs>(capacity);
|
||||
this.snapshots = new List<MemoryBuffer>(capacity);
|
||||
this.hashs = new List<long>(capacity);
|
||||
|
||||
for (int i = 0; i < this.snapshots.Capacity; ++i)
|
||||
{
|
||||
this.hashs.Add(0);
|
||||
this.frameInputs.Add(new OneFrameInputs());
|
||||
MemoryBuffer memoryBuffer = new(10240);
|
||||
memoryBuffer.SetLength(0);
|
||||
memoryBuffer.Seek(0, SeekOrigin.Begin);
|
||||
this.snapshots.Add(memoryBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetHash(int frame, long hash)
|
||||
{
|
||||
EnsureFrame(frame);
|
||||
this.hashs[frame % this.frameInputs.Capacity] = hash;
|
||||
}
|
||||
|
||||
public long GetHash(int frame)
|
||||
{
|
||||
EnsureFrame(frame);
|
||||
return this.hashs[frame % this.frameInputs.Capacity];
|
||||
}
|
||||
|
||||
public bool CheckFrame(int frame)
|
||||
{
|
||||
if (frame < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (frame > this.MaxFrame)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void EnsureFrame(int frame)
|
||||
{
|
||||
if (!CheckFrame(frame))
|
||||
{
|
||||
throw new Exception($"frame out: {frame}, maxframe: {this.MaxFrame}");
|
||||
}
|
||||
}
|
||||
|
||||
public OneFrameInputs FrameInputs(int frame)
|
||||
{
|
||||
EnsureFrame(frame);
|
||||
OneFrameInputs oneFrameInputs = this.frameInputs[frame % this.frameInputs.Capacity];
|
||||
return oneFrameInputs;
|
||||
}
|
||||
|
||||
public void MoveForward(int frame)
|
||||
{
|
||||
if (this.MaxFrame - frame > LSConstValue.FrameCountPerSecond) // 至少留出1秒的空间
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
++this.MaxFrame;
|
||||
|
||||
OneFrameInputs oneFrameInputs = this.FrameInputs(this.MaxFrame);
|
||||
oneFrameInputs.Inputs.Clear();
|
||||
}
|
||||
|
||||
public MemoryBuffer Snapshot(int frame)
|
||||
{
|
||||
EnsureFrame(frame);
|
||||
MemoryBuffer memoryBuffer = this.snapshots[frame % this.snapshots.Capacity];
|
||||
return memoryBuffer;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 248572437c2f47728e0191da78943fe5
|
||||
timeCreated: 1681719619
|
@@ -0,0 +1,7 @@
|
||||
namespace ET
|
||||
{
|
||||
public interface IActorRoom: IActorMessage
|
||||
{
|
||||
long PlayerId { get; set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 88154111be2b445c295e7208376f428b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
public interface ILSRollback
|
||||
{
|
||||
}
|
||||
|
||||
public interface ILSRollbackSystem: ISystemType
|
||||
{
|
||||
void Run(Entity o);
|
||||
}
|
||||
|
||||
[LSEntitySystem]
|
||||
public abstract class LSRollbackSystem<T> : ILSRollbackSystem where T: Entity, ILSRollback
|
||||
{
|
||||
void ILSRollbackSystem.Run(Entity o)
|
||||
{
|
||||
this.LSRollback((T)o);
|
||||
}
|
||||
|
||||
Type ISystemType.Type()
|
||||
{
|
||||
return typeof(T);
|
||||
}
|
||||
|
||||
Type ISystemType.SystemType()
|
||||
{
|
||||
return typeof(ILSRollbackSystem);
|
||||
}
|
||||
|
||||
int ISystemType.GetInstanceQueueIndex()
|
||||
{
|
||||
return InstanceQueueIndex.None;
|
||||
}
|
||||
|
||||
protected abstract void LSRollback(T self);
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 27067471cd1c7d045bb855b9f4f4c9b4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
public interface ILSUpdate
|
||||
{
|
||||
}
|
||||
|
||||
public interface ILSUpdateSystem: ISystemType
|
||||
{
|
||||
void Run(LSEntity o);
|
||||
}
|
||||
|
||||
[LSEntitySystem]
|
||||
public abstract class LSUpdateSystem<T> : ILSUpdateSystem where T: LSEntity, ILSUpdate
|
||||
{
|
||||
void ILSUpdateSystem.Run(LSEntity o)
|
||||
{
|
||||
this.LSUpdate((T)o);
|
||||
}
|
||||
|
||||
Type ISystemType.Type()
|
||||
{
|
||||
return typeof(T);
|
||||
}
|
||||
|
||||
Type ISystemType.SystemType()
|
||||
{
|
||||
return typeof(ILSUpdateSystem);
|
||||
}
|
||||
|
||||
int ISystemType.GetInstanceQueueIndex()
|
||||
{
|
||||
return LSQueneUpdateIndex.LSUpdate;
|
||||
}
|
||||
|
||||
protected abstract void LSUpdate(T self);
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2dc2986d4ec384cad9cf41a6eef3f6eb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,10 @@
|
||||
namespace ET
|
||||
{
|
||||
public static class LSConstValue
|
||||
{
|
||||
public const int MatchCount = 1;
|
||||
public const int UpdateInterval = 50;
|
||||
public const int FrameCountPerSecond = 1000 / UpdateInterval;
|
||||
public const int SaveLSWorldFrameCount = 60 * FrameCountPerSecond;
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f1af7fd8703b4dc3a521ef52d538d168
|
||||
timeCreated: 1681819811
|
72
Assets/GameScripts/DotNet/Model/Share/LockStep/LSEntity.cs
Normal file
72
Assets/GameScripts/DotNet/Model/Share/LockStep/LSEntity.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
public interface IRegisterLSEntitySystem
|
||||
{
|
||||
void RegisterSystem(LSEntity entity);
|
||||
}
|
||||
|
||||
[EnableMethod]
|
||||
public class LSEntity: Entity
|
||||
{
|
||||
public new K AddComponent<K>(bool isFromPool = false) where K : LSEntity, IAwake, new()
|
||||
{
|
||||
return this.AddComponentWithId<K>(this.GetId(), isFromPool);
|
||||
}
|
||||
|
||||
public new K AddComponent<K, P1>(P1 p1, bool isFromPool = false) where K : LSEntity, IAwake<P1>, new()
|
||||
{
|
||||
return this.AddComponentWithId<K, P1>(this.GetId(), p1, isFromPool);
|
||||
}
|
||||
|
||||
public new K AddComponent<K, P1, P2>(P1 p1, P2 p2, bool isFromPool = false) where K : LSEntity, IAwake<P1, P2>, new()
|
||||
{
|
||||
return this.AddComponentWithId<K, P1, P2>(this.GetId(), p1, p2, isFromPool);
|
||||
}
|
||||
|
||||
public new K AddComponent<K, P1, P2, P3>(P1 p1, P2 p2, P3 p3, bool isFromPool = false) where K : LSEntity, IAwake<P1, P2, P3>, new()
|
||||
{
|
||||
return this.AddComponentWithId<K, P1, P2, P3>(this.GetId(), p1, p2, p3, isFromPool);
|
||||
}
|
||||
|
||||
[EnableAccessEntiyChild]
|
||||
public new T AddChild<T>(bool isFromPool = false) where T : LSEntity, IAwake
|
||||
{
|
||||
return this.AddChildWithId<T>(this.GetId(), isFromPool);
|
||||
}
|
||||
|
||||
[EnableAccessEntiyChild]
|
||||
public new T AddChild<T, A>(A a, bool isFromPool = false) where T : LSEntity, IAwake<A>
|
||||
{
|
||||
return this.AddChildWithId<T, A>(this.GetId(), a, isFromPool);
|
||||
}
|
||||
|
||||
[EnableAccessEntiyChild]
|
||||
public new T AddChild<T, A, B>(A a, B b, bool isFromPool = false) where T : LSEntity, IAwake<A, B>
|
||||
{
|
||||
return this.AddChildWithId<T, A, B>(this.GetId(), a, b, isFromPool);
|
||||
}
|
||||
|
||||
[EnableAccessEntiyChild]
|
||||
public new T AddChild<T, A, B, C>(A a, B b, C c, bool isFromPool = false) where T : LSEntity, IAwake<A, B, C>
|
||||
{
|
||||
return this.AddChildWithId<T, A, B, C>(this.GetId(), a, b, c, isFromPool);
|
||||
}
|
||||
|
||||
protected override void RegisterSystem()
|
||||
{
|
||||
IRegisterLSEntitySystem iRegisterLsEntitySystem = (IRegisterLSEntitySystem)this.IScene;
|
||||
TypeSystems.OneTypeSystems oneTypeSystems = LSEntitySystemSingleton.Instance.GetOneTypeSystems(this.GetType());
|
||||
if (oneTypeSystems == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (oneTypeSystems.QueueFlag[LSQueneUpdateIndex.LSUpdate])
|
||||
{
|
||||
iRegisterLsEntitySystem.RegisterSystem(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3c56b3bb10000446c8e48f82b6969093
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||
public class LSEntitySystemAttribute: BaseAttribute
|
||||
{
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 83785c2329d8c4847b6fab0468c7f4d4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,107 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
[UniqueId(-1, 1)]
|
||||
public static class LSQueneUpdateIndex
|
||||
{
|
||||
public const int None = -1;
|
||||
public const int LSUpdate = 0;
|
||||
public const int Max = 1;
|
||||
}
|
||||
|
||||
public class LSEntitySystemSingleton: SingletonLock<LSEntitySystemSingleton>, ISingletonAwake
|
||||
{
|
||||
public TypeSystems TypeSystems { get; private set; }
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
this.TypeSystems = new(LSQueneUpdateIndex.Max);
|
||||
foreach (Type type in EventSystem.Instance.GetTypes(typeof (LSEntitySystemAttribute)))
|
||||
{
|
||||
object obj = Activator.CreateInstance(type);
|
||||
|
||||
if (obj is not ISystemType iSystemType)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
TypeSystems.OneTypeSystems oneTypeSystems = this.TypeSystems.GetOrCreateOneTypeSystems(iSystemType.Type());
|
||||
oneTypeSystems.Map.Add(iSystemType.SystemType(), obj);
|
||||
int index = iSystemType.GetInstanceQueueIndex();
|
||||
if (index > LSQueneUpdateIndex.None && index < LSQueneUpdateIndex.Max)
|
||||
{
|
||||
oneTypeSystems.QueueFlag[index] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
World.Instance.AddSingleton<LSEntitySystemSingleton>(true);
|
||||
}
|
||||
|
||||
public TypeSystems.OneTypeSystems GetOneTypeSystems(Type type)
|
||||
{
|
||||
return this.TypeSystems.GetOneTypeSystems(type);
|
||||
}
|
||||
|
||||
public void LSRollback(Entity entity)
|
||||
{
|
||||
if (entity is not ILSRollback)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<object> iLSRollbackSystems = this.TypeSystems.GetSystems(entity.GetType(), typeof (ILSRollbackSystem));
|
||||
if (iLSRollbackSystems == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (ILSRollbackSystem iLSRollbackSystem in iLSRollbackSystems)
|
||||
{
|
||||
if (iLSRollbackSystem == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
iLSRollbackSystem.Run(entity);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void LSUpdate(LSEntity entity)
|
||||
{
|
||||
if (entity is not ILSUpdate)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<object> iLSUpdateSystems = TypeSystems.GetSystems(entity.GetType(), typeof (ILSUpdateSystem));
|
||||
if (iLSUpdateSystems == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (ILSUpdateSystem iLSUpdateSystem in iLSUpdateSystems)
|
||||
{
|
||||
try
|
||||
{
|
||||
iLSUpdateSystem.Run(entity);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d43f6155cef5380498803ee6c4e00d63
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
50
Assets/GameScripts/DotNet/Model/Share/LockStep/LSInput.cs
Normal file
50
Assets/GameScripts/DotNet/Model/Share/LockStep/LSInput.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using MemoryPack;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
[MemoryPackable]
|
||||
public partial struct LSInput
|
||||
{
|
||||
[MemoryPackOrder(0)]
|
||||
public TrueSync.TSVector2 V;
|
||||
|
||||
[MemoryPackOrder(1)]
|
||||
public int Button;
|
||||
|
||||
public bool Equals(LSInput other)
|
||||
{
|
||||
return this.V == other.V && this.Button == other.Button;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is LSInput other && Equals(other);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(this.V, this.Button);
|
||||
}
|
||||
|
||||
public static bool operator==(LSInput a, LSInput b)
|
||||
{
|
||||
if (a.V != b.V)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a.Button != b.Button)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool operator !=(LSInput a, LSInput b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f2411352b8bd84ed8bf43aa625cf3d44
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
namespace ET
|
||||
{
|
||||
[ComponentOf(typeof(LSUnit))]
|
||||
public class LSInputComponent: LSEntity, ILSUpdate, IAwake, ISerializeToEntity
|
||||
{
|
||||
public LSInput LSInput { get; set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e0df77bdfbbb4a5fa2e9de116dabaaa2
|
||||
timeCreated: 1682051388
|
29
Assets/GameScripts/DotNet/Model/Share/LockStep/LSUnit.cs
Normal file
29
Assets/GameScripts/DotNet/Model/Share/LockStep/LSUnit.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using TrueSync;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
[ChildOf(typeof(LSUnitComponent))]
|
||||
public class LSUnit: LSEntity, IAwake, ISerializeToEntity
|
||||
{
|
||||
public TSVector Position
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[BsonIgnore]
|
||||
public TSVector Forward
|
||||
{
|
||||
get => this.Rotation * TSVector.forward;
|
||||
set => this.Rotation = TSQuaternion.LookRotation(value, TSVector.up);
|
||||
}
|
||||
|
||||
public TSQuaternion Rotation
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c62694a15545f4b599f146f8a44e417c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,7 @@
|
||||
namespace ET
|
||||
{
|
||||
[ComponentOf(typeof(LSWorld))]
|
||||
public class LSUnitComponent: LSEntity, IAwake, ISerializeToEntity
|
||||
{
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a9b77ec7663d54ec88ba2a0297314aef
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
46
Assets/GameScripts/DotNet/Model/Share/LockStep/LSUpdater.cs
Normal file
46
Assets/GameScripts/DotNet/Model/Share/LockStep/LSUpdater.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
public class LSUpdater
|
||||
{
|
||||
private List<long> updateIds = new();
|
||||
private List<long> newUpdateIds = new();
|
||||
|
||||
private readonly Dictionary<long, EntityRef<LSEntity>> lsEntities = new();
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (this.newUpdateIds.Count > 0)
|
||||
{
|
||||
foreach (long id in this.newUpdateIds)
|
||||
{
|
||||
this.updateIds.Add(id);
|
||||
}
|
||||
this.updateIds.Sort();
|
||||
this.newUpdateIds.Clear();
|
||||
}
|
||||
|
||||
foreach (long id in this.updateIds)
|
||||
{
|
||||
LSEntity entity = lsEntities[id];
|
||||
if (entity == null)
|
||||
{
|
||||
this.lsEntities.Remove(id);
|
||||
continue;
|
||||
}
|
||||
this.newUpdateIds.Add(id);
|
||||
LSEntitySystemSingleton.Instance.LSUpdate(entity);
|
||||
}
|
||||
this.updateIds.Clear();
|
||||
ObjectHelper.Swap(ref this.updateIds, ref this.newUpdateIds);
|
||||
}
|
||||
|
||||
public void Add(LSEntity entity)
|
||||
{
|
||||
this.newUpdateIds.Add(entity.Id);
|
||||
this.lsEntities.Add(entity.Id, entity);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 654b3240c49c34319877c2dc7da81a5a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
75
Assets/GameScripts/DotNet/Model/Share/LockStep/LSWorld.cs
Normal file
75
Assets/GameScripts/DotNet/Model/Share/LockStep/LSWorld.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TrueSync;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
public static class LSWorldSystem
|
||||
{
|
||||
public static LSWorld LSWorld(this LSEntity entity)
|
||||
{
|
||||
return entity.IScene as LSWorld;
|
||||
}
|
||||
|
||||
public static long GetId(this LSEntity entity)
|
||||
{
|
||||
return entity.LSWorld().GetId();
|
||||
}
|
||||
|
||||
public static TSRandom GetRandom(this LSEntity entity)
|
||||
{
|
||||
return entity.LSWorld().Random;
|
||||
}
|
||||
}
|
||||
|
||||
[EnableMethod]
|
||||
[ChildOf]
|
||||
[ComponentOf]
|
||||
public class LSWorld: LSEntity, IAwake, IScene, IRegisterLSEntitySystem
|
||||
{
|
||||
public LSWorld()
|
||||
{
|
||||
}
|
||||
|
||||
public LSWorld(SceneType sceneType)
|
||||
{
|
||||
this.Id = this.GetId();
|
||||
|
||||
this.SceneType = sceneType;
|
||||
|
||||
Log.Info($"LSScene create: {this.Id} {this.InstanceId}");
|
||||
}
|
||||
|
||||
private readonly LSUpdater updater = new();
|
||||
|
||||
[BsonIgnore]
|
||||
public Fiber Fiber { get; set; }
|
||||
|
||||
[BsonElement]
|
||||
private long idGenerator;
|
||||
|
||||
public long GetId()
|
||||
{
|
||||
return ++this.idGenerator;
|
||||
}
|
||||
|
||||
public TSRandom Random { get; set; }
|
||||
|
||||
[BsonIgnore]
|
||||
public SceneType SceneType { get; set; }
|
||||
|
||||
public int Frame { get; set; }
|
||||
|
||||
public void Update()
|
||||
{
|
||||
this.updater.Update();
|
||||
++this.Frame;
|
||||
}
|
||||
|
||||
public void RegisterSystem(LSEntity entity)
|
||||
{
|
||||
this.updater.Add(entity);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 55f4993cd749b4da984b60fc8d0720a2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
public partial class OneFrameInputs
|
||||
{
|
||||
protected bool Equals(OneFrameInputs other)
|
||||
{
|
||||
return Equals(this.Inputs, other.Inputs);
|
||||
}
|
||||
|
||||
public void CopyTo(OneFrameInputs to)
|
||||
{
|
||||
to.Inputs.Clear();
|
||||
foreach (var kv in this.Inputs)
|
||||
{
|
||||
to.Inputs.Add(kv.Key, kv.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ReferenceEquals(this, obj))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (obj.GetType() != this.GetType())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Equals((OneFrameInputs) obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(this.Inputs);
|
||||
}
|
||||
|
||||
public OneFrameInputs()
|
||||
{
|
||||
this.Inputs = new Dictionary<long, LSInput>(LSConstValue.MatchCount);
|
||||
}
|
||||
|
||||
public static bool operator==(OneFrameInputs a, OneFrameInputs b)
|
||||
{
|
||||
if (a is null || b is null)
|
||||
{
|
||||
if (a is null && b is null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a.Inputs.Count != b.Inputs.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var kv in a.Inputs)
|
||||
{
|
||||
if (!b.Inputs.TryGetValue(kv.Key, out LSInput inputInfo))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (kv.Value != inputInfo)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool operator !=(OneFrameInputs a, OneFrameInputs b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Room2C_Start
|
||||
{
|
||||
public Room2C_Start()
|
||||
{
|
||||
this.UnitInfo = new List<LockStepUnitInfo>(LSConstValue.MatchCount);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cc7d50658d3c844c8b32167be54851c4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
18
Assets/GameScripts/DotNet/Model/Share/LockStep/Replay.cs
Normal file
18
Assets/GameScripts/DotNet/Model/Share/LockStep/Replay.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System.Collections.Generic;
|
||||
using MemoryPack;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
[MemoryPackable]
|
||||
public partial class Replay
|
||||
{
|
||||
[MemoryPackOrder(1)]
|
||||
public List<LockStepUnitInfo> UnitInfos;
|
||||
|
||||
[MemoryPackOrder(2)]
|
||||
public List<OneFrameInputs> FrameInputs = new();
|
||||
|
||||
[MemoryPackOrder(3)]
|
||||
public List<byte[]> Snapshots = new();
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 83a7335c9271d4f848460aedf23c1b70
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
53
Assets/GameScripts/DotNet/Model/Share/LockStep/Room.cs
Normal file
53
Assets/GameScripts/DotNet/Model/Share/LockStep/Room.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
[ChildOf]
|
||||
[ComponentOf]
|
||||
public class Room: Entity, IScene, IAwake, IUpdate
|
||||
{
|
||||
public Fiber Fiber { get; set; }
|
||||
public SceneType SceneType { get; set; } = SceneType.Room;
|
||||
public string Name { get; set; }
|
||||
|
||||
public long StartTime { get; set; }
|
||||
|
||||
// 帧缓存
|
||||
public FrameBuffer FrameBuffer { get; set; }
|
||||
|
||||
// 计算fixedTime,fixedTime在客户端是动态调整的,会做时间膨胀缩放
|
||||
public FixedTimeCounter FixedTimeCounter { get; set; }
|
||||
|
||||
// 玩家id列表
|
||||
public List<long> PlayerIds { get; } = new(LSConstValue.MatchCount);
|
||||
|
||||
// 预测帧
|
||||
public int PredictionFrame { get; set; } = -1;
|
||||
|
||||
// 权威帧
|
||||
public int AuthorityFrame { get; set; } = -1;
|
||||
|
||||
// 存档
|
||||
public Replay Replay { get; set; } = new();
|
||||
|
||||
private EntityRef<LSWorld> lsWorld;
|
||||
|
||||
// LSWorld做成child,可以有多个lsWorld,比如守望先锋有两个
|
||||
public LSWorld LSWorld
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.lsWorld;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.AddChild(value);
|
||||
this.lsWorld = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReplay { get; set; }
|
||||
|
||||
public int SpeedMultiply { get; set; }
|
||||
}
|
||||
}
|
11
Assets/GameScripts/DotNet/Model/Share/LockStep/Room.cs.meta
Normal file
11
Assets/GameScripts/DotNet/Model/Share/LockStep/Room.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 51fde8d44ce33433b9523076002f8831
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/GameScripts/DotNet/Model/Share/Module.meta
Normal file
8
Assets/GameScripts/DotNet/Model/Share/Module.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ad8d604046d19e40a023fa31ed2265f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/GameScripts/DotNet/Model/Share/Module/AI.meta
Normal file
8
Assets/GameScripts/DotNet/Model/Share/Module/AI.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 17314ef2e141d8f4e8b75777cec648ce
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
public class AIHandlerAttribute: BaseAttribute
|
||||
{
|
||||
}
|
||||
|
||||
[AIHandler]
|
||||
public abstract class AAIHandler
|
||||
{
|
||||
// 检查是否满足条件
|
||||
public abstract int Check(AIComponent aiComponent, AIConfig aiConfig);
|
||||
|
||||
// 协程编写必须可以取消
|
||||
public abstract ETTask Execute(AIComponent aiComponent, AIConfig aiConfig, ETCancellationToken cancellationToken);
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3e43892262fb7af4b95b158fa391da91
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,15 @@
|
||||
namespace ET
|
||||
{
|
||||
// 客户端挂在ClientScene上,服务端挂在Unit上
|
||||
[ComponentOf(typeof(Scene))]
|
||||
public class AIComponent: Entity, IAwake<int>, IDestroy
|
||||
{
|
||||
public int AIConfigId;
|
||||
|
||||
public ETCancellationToken CancellationToken;
|
||||
|
||||
public long Timer;
|
||||
|
||||
public int Current;
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b13f63f82f588d4382b1e8cb779425e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
33
Assets/GameScripts/DotNet/Model/Share/Module/AI/AIConfig.cs
Normal file
33
Assets/GameScripts/DotNet/Model/Share/Module/AI/AIConfig.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
public partial class AIConfigCategory
|
||||
{
|
||||
[BsonIgnore]
|
||||
public Dictionary<int, SortedDictionary<int, AIConfig>> AIConfigs = new Dictionary<int, SortedDictionary<int, AIConfig>>();
|
||||
|
||||
public SortedDictionary<int, AIConfig> GetAI(int aiConfigId)
|
||||
{
|
||||
return this.AIConfigs[aiConfigId];
|
||||
}
|
||||
|
||||
public override void EndInit()
|
||||
{
|
||||
foreach (var kv in this.GetAll())
|
||||
{
|
||||
SortedDictionary<int, AIConfig> aiNodeConfig;
|
||||
if (!this.AIConfigs.TryGetValue(kv.Value.AIConfigId, out aiNodeConfig))
|
||||
{
|
||||
aiNodeConfig = new SortedDictionary<int, AIConfig>();
|
||||
this.AIConfigs.Add(kv.Value.AIConfigId, aiNodeConfig);
|
||||
}
|
||||
|
||||
aiNodeConfig.Add(kv.Key, kv.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f733a3428ecb9224d8917bd0aed54a0b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
public class AIDispatcherComponent: SingletonLock<AIDispatcherComponent>, ISingletonAwake
|
||||
{
|
||||
private readonly Dictionary<string, AAIHandler> aiHandlers = new();
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
var types = EventSystem.Instance.GetTypes(typeof (AIHandlerAttribute));
|
||||
foreach (Type type in types)
|
||||
{
|
||||
AAIHandler aaiHandler = Activator.CreateInstance(type) as AAIHandler;
|
||||
if (aaiHandler == null)
|
||||
{
|
||||
Log.Error($"robot ai is not AAIHandler: {type.Name}");
|
||||
continue;
|
||||
}
|
||||
this.aiHandlers.Add(type.Name, aaiHandler);
|
||||
}
|
||||
}
|
||||
|
||||
public AAIHandler Get(string key)
|
||||
{
|
||||
this.aiHandlers.TryGetValue(key, out var aaiHandler);
|
||||
return aaiHandler;
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
World.Instance.AddSingleton<AIDispatcherComponent>(true);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70505ae07c0ed05469c46867370eae98
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aac5f3c9c8081e643874db9704c945a4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
public static class ConsoleMode
|
||||
{
|
||||
public const string ReloadDll = "R";
|
||||
public const string ReloadConfig = "C";
|
||||
public const string ShowMemory = "M";
|
||||
public const string Repl = "Repl";
|
||||
public const string Debugger = "Debugger";
|
||||
public const string CreateRobot = "CreateRobot";
|
||||
public const string Robot = "Robot";
|
||||
}
|
||||
|
||||
[ComponentOf(typeof(Scene))]
|
||||
public class ConsoleComponent: Entity, IAwake
|
||||
{
|
||||
public CancellationTokenSource CancellationTokenSource;
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 22534ff56546c094d904521502f2103f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
public class ConsoleDispatcher: SingletonLock<ConsoleDispatcher>, ISingletonAwake
|
||||
{
|
||||
private readonly Dictionary<string, IConsoleHandler> handlers = new();
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
World.Instance.AddSingleton<ConsoleDispatcher>(true);
|
||||
}
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
HashSet<Type> types = EventSystem.Instance.GetTypes(typeof (ConsoleHandlerAttribute));
|
||||
|
||||
foreach (Type type in types)
|
||||
{
|
||||
object[] attrs = type.GetCustomAttributes(typeof(ConsoleHandlerAttribute), false);
|
||||
if (attrs.Length == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ConsoleHandlerAttribute consoleHandlerAttribute = (ConsoleHandlerAttribute)attrs[0];
|
||||
|
||||
object obj = Activator.CreateInstance(type);
|
||||
|
||||
IConsoleHandler iConsoleHandler = obj as IConsoleHandler;
|
||||
if (iConsoleHandler == null)
|
||||
{
|
||||
throw new Exception($"ConsoleHandler handler not inherit IConsoleHandler class: {obj.GetType().FullName}");
|
||||
}
|
||||
this.handlers.Add(consoleHandlerAttribute.Mode, iConsoleHandler);
|
||||
}
|
||||
}
|
||||
|
||||
public IConsoleHandler Get(string key)
|
||||
{
|
||||
return this.handlers[key];
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7cf505646a7016d40817dc8783f37ed1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,12 @@
|
||||
namespace ET
|
||||
{
|
||||
public class ConsoleHandlerAttribute: BaseAttribute
|
||||
{
|
||||
public string Mode { get; }
|
||||
|
||||
public ConsoleHandlerAttribute(string mode)
|
||||
{
|
||||
this.Mode = mode;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08c605182de1040469a4239c965f2694
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,7 @@
|
||||
namespace ET
|
||||
{
|
||||
public interface IConsoleHandler
|
||||
{
|
||||
ETTask Run(Fiber fiber, ModeContex contex, string content);
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0498d217572ef624cb2f066e11f028a9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,27 @@
|
||||
namespace ET
|
||||
{
|
||||
[EntitySystemOf(typeof(ModeContex))]
|
||||
[FriendOf(typeof(ModeContex))]
|
||||
public static partial class ModeContexSystem
|
||||
{
|
||||
[EntitySystem]
|
||||
private static void Awake(this ModeContex self)
|
||||
{
|
||||
self.Mode = "";
|
||||
}
|
||||
|
||||
[EntitySystem]
|
||||
private static void Destroy(this ModeContex self)
|
||||
{
|
||||
self.Mode = "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[ComponentOf(typeof(ConsoleComponent))]
|
||||
public class ModeContex: Entity, IAwake, IDestroy
|
||||
{
|
||||
public string Mode = "";
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 519865a57fe078d4b8b5989813e8c4ec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08e7592e24d7de848a57c94e2a27a999
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,17 @@
|
||||
namespace ET
|
||||
{
|
||||
public static partial class ErrorCode
|
||||
{
|
||||
public const int ERR_Success = 0;
|
||||
|
||||
// 1-11004 是SocketError请看SocketError定义
|
||||
//-----------------------------------
|
||||
// 100000-109999是Core层的错误
|
||||
|
||||
// 110000以下的错误请看ErrorCore.cs
|
||||
|
||||
// 这里配置逻辑层的错误码
|
||||
// 110000 - 200000是抛异常的错误
|
||||
// 200001以上不抛异常
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c926ebadd533a344d9b622ba3398dd9a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
public interface IMHandler
|
||||
{
|
||||
void Handle(Session session, object message);
|
||||
Type GetMessageType();
|
||||
|
||||
Type GetResponseType();
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5d9d71d94c994b64daecdede5f1a889c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,100 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
public class MessageDispatcherInfo
|
||||
{
|
||||
public SceneType SceneType { get; }
|
||||
public IMHandler IMHandler { get; }
|
||||
|
||||
public MessageDispatcherInfo(SceneType sceneType, IMHandler imHandler)
|
||||
{
|
||||
this.SceneType = sceneType;
|
||||
this.IMHandler = imHandler;
|
||||
}
|
||||
}
|
||||
|
||||
public class MessageDispatcherComponent: SingletonLock<MessageDispatcherComponent>, ISingletonAwake
|
||||
{
|
||||
private readonly Dictionary<ushort, List<MessageDispatcherInfo>> handlers = new();
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
HashSet<Type> types = EventSystem.Instance.GetTypes(typeof (MessageHandlerAttribute));
|
||||
|
||||
foreach (Type type in types)
|
||||
{
|
||||
IMHandler iMHandler = Activator.CreateInstance(type) as IMHandler;
|
||||
if (iMHandler == null)
|
||||
{
|
||||
Log.Error($"message handle {type.Name} 需要继承 IMHandler");
|
||||
continue;
|
||||
}
|
||||
|
||||
object[] attrs = type.GetCustomAttributes(typeof(MessageHandlerAttribute), true);
|
||||
|
||||
foreach (object attr in attrs)
|
||||
{
|
||||
MessageHandlerAttribute messageHandlerAttribute = attr as MessageHandlerAttribute;
|
||||
|
||||
Type messageType = iMHandler.GetMessageType();
|
||||
|
||||
ushort opcode = OpcodeType.Instance.GetOpcode(messageType);
|
||||
if (opcode == 0)
|
||||
{
|
||||
Log.Error($"消息opcode为0: {messageType.Name}");
|
||||
continue;
|
||||
}
|
||||
|
||||
MessageDispatcherInfo messageDispatcherInfo = new (messageHandlerAttribute.SceneType, iMHandler);
|
||||
this.RegisterHandler(opcode, messageDispatcherInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
World.Instance.AddSingleton<MessageDispatcherComponent>(true);
|
||||
}
|
||||
|
||||
private void RegisterHandler(ushort opcode, MessageDispatcherInfo handler)
|
||||
{
|
||||
if (!this.handlers.ContainsKey(opcode))
|
||||
{
|
||||
this.handlers.Add(opcode, new List<MessageDispatcherInfo>());
|
||||
}
|
||||
|
||||
this.handlers[opcode].Add(handler);
|
||||
}
|
||||
|
||||
public void Handle(Session session, object message)
|
||||
{
|
||||
List<MessageDispatcherInfo> actions;
|
||||
ushort opcode = OpcodeType.Instance.GetOpcode(message.GetType());
|
||||
if (!this.handlers.TryGetValue(opcode, out actions))
|
||||
{
|
||||
Log.Error($"消息没有处理: {opcode} {message}");
|
||||
return;
|
||||
}
|
||||
|
||||
SceneType sceneType = session.IScene.SceneType;
|
||||
foreach (MessageDispatcherInfo ev in actions)
|
||||
{
|
||||
if (!ev.SceneType.HasSameFlag(sceneType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ev.IMHandler.Handle(session, message);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ede21855857ffe4aae0f5d80047cc80
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
public abstract class MessageHandler<Message>: IMHandler where Message : class
|
||||
{
|
||||
protected abstract ETTask Run(Session session, Message message);
|
||||
|
||||
public void Handle(Session session, object msg)
|
||||
{
|
||||
Message message = msg as Message;
|
||||
if (message == null)
|
||||
{
|
||||
Log.Error($"消息类型转换错误: {msg.GetType().FullName} to {typeof (Message).Name}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (session.IsDisposed)
|
||||
{
|
||||
Log.Error($"session disconnect {msg}");
|
||||
return;
|
||||
}
|
||||
|
||||
this.Run(session, message).Coroutine();
|
||||
}
|
||||
|
||||
public Type GetMessageType()
|
||||
{
|
||||
return typeof (Message);
|
||||
}
|
||||
|
||||
public Type GetResponseType()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4c40ee71fc1a2f144bf4d2ff2cf7c65d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
public class MessageHandlerAttribute: BaseAttribute
|
||||
{
|
||||
public SceneType SceneType { get; }
|
||||
|
||||
public MessageHandlerAttribute(SceneType sceneType)
|
||||
{
|
||||
this.SceneType = sceneType;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61a55441f76423340b0da6e5c2af7c66
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
185
Assets/GameScripts/DotNet/Model/Share/Module/Message/Session.cs
Normal file
185
Assets/GameScripts/DotNet/Model/Share/Module/Message/Session.cs
Normal file
@@ -0,0 +1,185 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
public readonly struct RpcInfo
|
||||
{
|
||||
public readonly IRequest Request;
|
||||
public readonly ETTask<IResponse> Tcs;
|
||||
|
||||
public RpcInfo(IRequest request)
|
||||
{
|
||||
this.Request = request;
|
||||
this.Tcs = ETTask<IResponse>.Create(true);
|
||||
}
|
||||
}
|
||||
|
||||
[EntitySystemOf(typeof(Session))]
|
||||
[FriendOf(typeof(Session))]
|
||||
public static partial class SessionSystem
|
||||
{
|
||||
[EntitySystem]
|
||||
private static void Awake(this Session self, AService aService)
|
||||
{
|
||||
self.AService = aService;
|
||||
long timeNow = self.Fiber().TimeInfo.ClientNow();
|
||||
self.LastRecvTime = timeNow;
|
||||
self.LastSendTime = timeNow;
|
||||
|
||||
self.requestCallbacks.Clear();
|
||||
|
||||
Log.Info($"session create: zone: {self.Zone()} id: {self.Id} {timeNow} ");
|
||||
}
|
||||
|
||||
[EntitySystem]
|
||||
private static void Destroy(this Session self)
|
||||
{
|
||||
self.AService.Remove(self.Id, self.Error);
|
||||
|
||||
foreach (RpcInfo responseCallback in self.requestCallbacks.Values.ToArray())
|
||||
{
|
||||
responseCallback.Tcs.SetException(new RpcException(self.Error, $"session dispose: {self.Id} {self.RemoteAddress}"));
|
||||
}
|
||||
|
||||
Log.Info($"session dispose: {self.RemoteAddress} id: {self.Id} ErrorCode: {self.Error}, please see ErrorCode.cs! {self.Fiber().TimeInfo.ClientNow()}");
|
||||
|
||||
self.requestCallbacks.Clear();
|
||||
}
|
||||
|
||||
public static void OnResponse(this Session self, IResponse response)
|
||||
{
|
||||
if (!self.requestCallbacks.Remove(response.RpcId, out var action))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ErrorCore.IsRpcNeedThrowException(response.Error))
|
||||
{
|
||||
action.Tcs.SetException(new Exception($"Rpc error, request: {action.Request} response: {response}"));
|
||||
return;
|
||||
}
|
||||
action.Tcs.SetResult(response);
|
||||
}
|
||||
|
||||
public static async ETTask<IResponse> Call(this Session self, IRequest request, ETCancellationToken cancellationToken)
|
||||
{
|
||||
int rpcId = ++Session.RpcId;
|
||||
RpcInfo rpcInfo = new RpcInfo(request);
|
||||
self.requestCallbacks[rpcId] = rpcInfo;
|
||||
request.RpcId = rpcId;
|
||||
|
||||
self.Send(request);
|
||||
|
||||
void CancelAction()
|
||||
{
|
||||
if (!self.requestCallbacks.TryGetValue(rpcId, out RpcInfo action))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self.requestCallbacks.Remove(rpcId);
|
||||
Type responseType = OpcodeType.Instance.GetResponseType(action.Request.GetType());
|
||||
IResponse response = (IResponse) Activator.CreateInstance(responseType);
|
||||
response.Error = ErrorCore.ERR_Cancel;
|
||||
action.Tcs.SetResult(response);
|
||||
}
|
||||
|
||||
IResponse ret;
|
||||
try
|
||||
{
|
||||
cancellationToken?.Add(CancelAction);
|
||||
ret = await rpcInfo.Tcs;
|
||||
}
|
||||
finally
|
||||
{
|
||||
cancellationToken?.Remove(CancelAction);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static async ETTask<IResponse> Call(this Session self, IRequest request, int time = 0)
|
||||
{
|
||||
int rpcId = ++Session.RpcId;
|
||||
RpcInfo rpcInfo = new(request);
|
||||
self.requestCallbacks[rpcId] = rpcInfo;
|
||||
request.RpcId = rpcId;
|
||||
self.Send(request);
|
||||
|
||||
if (time > 0)
|
||||
{
|
||||
async ETTask Timeout()
|
||||
{
|
||||
await self.Fiber().TimerComponent.WaitAsync(time);
|
||||
if (!self.requestCallbacks.TryGetValue(rpcId, out RpcInfo action))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self.requestCallbacks.Remove(rpcId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
action.Tcs.SetException(new Exception($"session call timeout: {request} {time}"));
|
||||
}
|
||||
|
||||
Timeout().Coroutine();
|
||||
}
|
||||
|
||||
return await rpcInfo.Tcs;
|
||||
}
|
||||
|
||||
public static void Send(this Session self, IMessage message)
|
||||
{
|
||||
self.Send(default, message);
|
||||
}
|
||||
|
||||
public static void Send(this Session self, ActorId actorId, IMessage message)
|
||||
{
|
||||
self.LastSendTime = self.Fiber().TimeInfo.ClientNow();
|
||||
Log.Debug(message.ToString());
|
||||
self.AService.Send(self.Id, actorId, message as MessageObject);
|
||||
}
|
||||
}
|
||||
|
||||
[ChildOf]
|
||||
public sealed class Session: Entity, IAwake<AService>, IDestroy
|
||||
{
|
||||
public AService AService { get; set; }
|
||||
|
||||
public static int RpcId
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public readonly Dictionary<int, RpcInfo> requestCallbacks = new();
|
||||
|
||||
public long LastRecvTime
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public long LastSendTime
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public int Error
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public IPEndPoint RemoteAddress
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f666df5ed1cec4d40bd2986c28507634
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,9 @@
|
||||
namespace ET
|
||||
{
|
||||
// 刚accept的session只持续5秒,必须通过验证,否则断开
|
||||
[ComponentOf(typeof(Session))]
|
||||
public class SessionAcceptTimeoutComponent: Entity, IAwake, IDestroy
|
||||
{
|
||||
public long Timer;
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37f2d187ca934374393b7b32d87b91f3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
namespace ET
|
||||
{
|
||||
[ComponentOf(typeof(Session))]
|
||||
public class SessionIdleCheckerComponent: Entity, IAwake, IDestroy
|
||||
{
|
||||
public long RepeatedTimer;
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d309c1ef46c0eb4bb58c14b6716c032
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/GameScripts/DotNet/Model/Share/Module/Move.meta
Normal file
8
Assets/GameScripts/DotNet/Model/Share/Module/Move.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 26fd94c36353aad4591969119ce93bb4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,83 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
[ComponentOf(typeof(Unit))]
|
||||
public class MoveComponent: Entity, IAwake, IDestroy
|
||||
{
|
||||
public float3 PreTarget
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Targets[this.N - 1];
|
||||
}
|
||||
}
|
||||
|
||||
public float3 NextTarget
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Targets[this.N];
|
||||
}
|
||||
}
|
||||
|
||||
// 开启移动协程的时间
|
||||
public long BeginTime;
|
||||
|
||||
// 每个点的开始时间
|
||||
public long StartTime { get; set; }
|
||||
|
||||
// 开启移动协程的Unit的位置
|
||||
public float3 StartPos;
|
||||
|
||||
public float3 RealPos
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Targets[0];
|
||||
}
|
||||
}
|
||||
|
||||
private long needTime;
|
||||
|
||||
public long NeedTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.needTime;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.needTime = value;
|
||||
}
|
||||
}
|
||||
|
||||
public long MoveTimer;
|
||||
|
||||
public float Speed; // m/s
|
||||
|
||||
public ETTask<bool> tcs;
|
||||
|
||||
public List<float3> Targets = new List<float3>();
|
||||
|
||||
public float3 FinalTarget
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Targets[this.Targets.Count - 1];
|
||||
}
|
||||
}
|
||||
|
||||
public int N;
|
||||
|
||||
public int TurnTime;
|
||||
|
||||
public bool IsTurnHorizontal;
|
||||
|
||||
public quaternion From;
|
||||
|
||||
public quaternion To;
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 91e6974c200f3e9468684362d1489433
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,15 @@
|
||||
namespace ET
|
||||
{
|
||||
namespace EventType
|
||||
{
|
||||
public struct MoveStart
|
||||
{
|
||||
public Unit Unit;
|
||||
}
|
||||
|
||||
public struct MoveStop
|
||||
{
|
||||
public Unit Unit;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0abfe3cf9ea0c8d41a0afe2920c080bb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d6a99783c189d543ac801a2d36b362b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,7 @@
|
||||
namespace ET
|
||||
{
|
||||
public interface INumericWatcher
|
||||
{
|
||||
void Run(Unit unit, EventType.NumbericChange args);
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d25ba9800f0a922459d8287d76d224d7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,121 @@
|
||||
using System.Collections.Generic;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using MongoDB.Bson.Serialization.Options;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
[FriendOf(typeof (NumericComponent))]
|
||||
public static class NumericComponentSystem
|
||||
{
|
||||
public static float GetAsFloat(this NumericComponent self, int numericType)
|
||||
{
|
||||
return (float)self.GetByKey(numericType) / 10000;
|
||||
}
|
||||
|
||||
public static int GetAsInt(this NumericComponent self, int numericType)
|
||||
{
|
||||
return (int)self.GetByKey(numericType);
|
||||
}
|
||||
|
||||
public static long GetAsLong(this NumericComponent self, int numericType)
|
||||
{
|
||||
return self.GetByKey(numericType);
|
||||
}
|
||||
|
||||
public static void Set(this NumericComponent self, int nt, float value)
|
||||
{
|
||||
self[nt] = (long)(value * 10000);
|
||||
}
|
||||
|
||||
public static void Set(this NumericComponent self, int nt, int value)
|
||||
{
|
||||
self[nt] = value;
|
||||
}
|
||||
|
||||
public static void Set(this NumericComponent self, int nt, long value)
|
||||
{
|
||||
self[nt] = value;
|
||||
}
|
||||
|
||||
public static void SetNoEvent(this NumericComponent self, int numericType, long value)
|
||||
{
|
||||
self.Insert(numericType, value, false);
|
||||
}
|
||||
|
||||
public static void Insert(this NumericComponent self, int numericType, long value, bool isPublicEvent = true)
|
||||
{
|
||||
long oldValue = self.GetByKey(numericType);
|
||||
if (oldValue == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self.NumericDic[numericType] = value;
|
||||
|
||||
if (numericType >= NumericType.Max)
|
||||
{
|
||||
self.Update(numericType, isPublicEvent);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isPublicEvent)
|
||||
{
|
||||
EventSystem.Instance.Publish(self.Scene(),
|
||||
new EventType.NumbericChange() { Unit = self.GetParent<Unit>(), New = value, Old = oldValue, NumericType = numericType });
|
||||
}
|
||||
}
|
||||
|
||||
public static long GetByKey(this NumericComponent self, int key)
|
||||
{
|
||||
long value = 0;
|
||||
self.NumericDic.TryGetValue(key, out value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public static void Update(this NumericComponent self, int numericType, bool isPublicEvent)
|
||||
{
|
||||
int final = (int)numericType / 10;
|
||||
int bas = final * 10 + 1;
|
||||
int add = final * 10 + 2;
|
||||
int pct = final * 10 + 3;
|
||||
int finalAdd = final * 10 + 4;
|
||||
int finalPct = final * 10 + 5;
|
||||
|
||||
// 一个数值可能会多种情况影响,比如速度,加个buff可能增加速度绝对值100,也有些buff增加10%速度,所以一个值可以由5个值进行控制其最终结果
|
||||
// final = (((base + add) * (100 + pct) / 100) + finalAdd) * (100 + finalPct) / 100;
|
||||
long result = (long)(((self.GetByKey(bas) + self.GetByKey(add)) * (100 + self.GetAsFloat(pct)) / 100f + self.GetByKey(finalAdd)) *
|
||||
(100 + self.GetAsFloat(finalPct)) / 100f);
|
||||
self.Insert(final, result, isPublicEvent);
|
||||
}
|
||||
}
|
||||
|
||||
namespace EventType
|
||||
{
|
||||
public struct NumbericChange
|
||||
{
|
||||
public Unit Unit;
|
||||
public int NumericType;
|
||||
public long Old;
|
||||
public long New;
|
||||
}
|
||||
}
|
||||
|
||||
[ComponentOf(typeof (Unit))]
|
||||
public class NumericComponent: Entity, IAwake, ITransfer
|
||||
{
|
||||
[BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]
|
||||
public Dictionary<int, long> NumericDic = new Dictionary<int, long>();
|
||||
|
||||
public long this[int numericType]
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetByKey(numericType);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.Insert(numericType, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 701bdb74115713a4bb6486a4bbc832ce
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,32 @@
|
||||
namespace ET
|
||||
{
|
||||
// 这个可弄个配置表生成
|
||||
public static class NumericType
|
||||
{
|
||||
public const int Max = 10000;
|
||||
|
||||
public const int Speed = 1000;
|
||||
public const int SpeedBase = Speed * 10 + 1;
|
||||
public const int SpeedAdd = Speed * 10 + 2;
|
||||
public const int SpeedPct = Speed * 10 + 3;
|
||||
public const int SpeedFinalAdd = Speed * 10 + 4;
|
||||
public const int SpeedFinalPct = Speed * 10 + 5;
|
||||
|
||||
public const int Hp = 1001;
|
||||
public const int HpBase = Hp * 10 + 1;
|
||||
|
||||
public const int MaxHp = 1002;
|
||||
public const int MaxHpBase = MaxHp * 10 + 1;
|
||||
public const int MaxHpAdd = MaxHp * 10 + 2;
|
||||
public const int MaxHpPct = MaxHp * 10 + 3;
|
||||
public const int MaxHpFinalAdd = MaxHp * 10 + 4;
|
||||
public const int MaxHpFinalPct = MaxHp * 10 + 5;
|
||||
|
||||
public const int AOI = 1003;
|
||||
public const int AOIBase = AOI * 10 + 1;
|
||||
public const int AOIAdd = AOI * 10 + 2;
|
||||
public const int AOIPct = AOI * 10 + 3;
|
||||
public const int AOIFinalAdd = AOI * 10 + 4;
|
||||
public const int AOIFinalPct = AOI * 10 + 5;
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e48d074e33972034bad7ee8ba643edf5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class NumericWatcherAttribute : BaseAttribute
|
||||
{
|
||||
public SceneType SceneType { get; }
|
||||
|
||||
public int NumericType { get; }
|
||||
|
||||
public NumericWatcherAttribute(SceneType sceneType, int type)
|
||||
{
|
||||
this.SceneType = sceneType;
|
||||
this.NumericType = type;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96e98292e4df6684abad49fc0887b963
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
public class NumericWatcherInfo
|
||||
{
|
||||
public SceneType SceneType { get; }
|
||||
public INumericWatcher INumericWatcher { get; }
|
||||
|
||||
public NumericWatcherInfo(SceneType sceneType, INumericWatcher numericWatcher)
|
||||
{
|
||||
this.SceneType = sceneType;
|
||||
this.INumericWatcher = numericWatcher;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 监视数值变化组件,分发监听
|
||||
/// </summary>
|
||||
public class NumericWatcherComponent : SingletonLock<NumericWatcherComponent>, ISingletonAwake
|
||||
{
|
||||
private readonly Dictionary<int, List<NumericWatcherInfo>> allWatchers = new();
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
HashSet<Type> types = EventSystem.Instance.GetTypes(typeof(NumericWatcherAttribute));
|
||||
foreach (Type type in types)
|
||||
{
|
||||
object[] attrs = type.GetCustomAttributes(typeof(NumericWatcherAttribute), false);
|
||||
|
||||
foreach (object attr in attrs)
|
||||
{
|
||||
NumericWatcherAttribute numericWatcherAttribute = (NumericWatcherAttribute)attr;
|
||||
INumericWatcher obj = (INumericWatcher)Activator.CreateInstance(type);
|
||||
NumericWatcherInfo numericWatcherInfo = new(numericWatcherAttribute.SceneType, obj);
|
||||
if (!this.allWatchers.ContainsKey(numericWatcherAttribute.NumericType))
|
||||
{
|
||||
this.allWatchers.Add(numericWatcherAttribute.NumericType, new List<NumericWatcherInfo>());
|
||||
}
|
||||
this.allWatchers[numericWatcherAttribute.NumericType].Add(numericWatcherInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
World.Instance.AddSingleton<NumericWatcherComponent>(true);
|
||||
}
|
||||
|
||||
public void Run(Unit unit, EventType.NumbericChange args)
|
||||
{
|
||||
List<NumericWatcherInfo> list;
|
||||
if (!this.allWatchers.TryGetValue(args.NumericType, out list))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SceneType unitDomainSceneType = unit.IScene.SceneType;
|
||||
foreach (NumericWatcherInfo numericWatcher in list)
|
||||
{
|
||||
if (!numericWatcher.SceneType.HasSameFlag(unitDomainSceneType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
numericWatcher.INumericWatcher.Run(unit, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 86c4a86a98102464b8bbe1bd9da800e5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 972155bb07920b648bbeecab259ed50b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,163 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
public static class WaitTypeError
|
||||
{
|
||||
public const int Success = 0;
|
||||
public const int Destroy = 1;
|
||||
public const int Cancel = 2;
|
||||
public const int Timeout = 3;
|
||||
}
|
||||
|
||||
public interface IWaitType
|
||||
{
|
||||
int Error
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
[EntitySystemOf(typeof(ObjectWait))]
|
||||
[FriendOf(typeof(ObjectWait))]
|
||||
public static partial class ObjectWaitSystem
|
||||
{
|
||||
[EntitySystem]
|
||||
private static void Awake(this ObjectWait self)
|
||||
{
|
||||
self.tcss.Clear();
|
||||
}
|
||||
|
||||
[EntitySystem]
|
||||
private static void Destroy(this ObjectWait self)
|
||||
{
|
||||
foreach (object v in self.tcss.Values.ToArray())
|
||||
{
|
||||
((IDestroyRun) v).SetResult();
|
||||
}
|
||||
}
|
||||
|
||||
private interface IDestroyRun
|
||||
{
|
||||
void SetResult();
|
||||
}
|
||||
|
||||
private class ResultCallback<K>: IDestroyRun where K : struct, IWaitType
|
||||
{
|
||||
private ETTask<K> tcs;
|
||||
|
||||
public ResultCallback()
|
||||
{
|
||||
this.tcs = ETTask<K>.Create(true);
|
||||
}
|
||||
|
||||
public bool IsDisposed
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.tcs == null;
|
||||
}
|
||||
}
|
||||
|
||||
public ETTask<K> Task => this.tcs;
|
||||
|
||||
public void SetResult(K k)
|
||||
{
|
||||
var t = tcs;
|
||||
this.tcs = null;
|
||||
t.SetResult(k);
|
||||
}
|
||||
|
||||
public void SetResult()
|
||||
{
|
||||
var t = tcs;
|
||||
this.tcs = null;
|
||||
t.SetResult(new K() { Error = WaitTypeError.Destroy });
|
||||
}
|
||||
}
|
||||
|
||||
public static async ETTask<T> Wait<T>(this ObjectWait self, ETCancellationToken cancellationToken = null) where T : struct, IWaitType
|
||||
{
|
||||
ResultCallback<T> tcs = new ResultCallback<T>();
|
||||
Type type = typeof (T);
|
||||
self.tcss.Add(type, tcs);
|
||||
|
||||
void CancelAction()
|
||||
{
|
||||
self.Notify(new T() { Error = WaitTypeError.Cancel });
|
||||
}
|
||||
|
||||
T ret;
|
||||
try
|
||||
{
|
||||
cancellationToken?.Add(CancelAction);
|
||||
ret = await tcs.Task;
|
||||
}
|
||||
finally
|
||||
{
|
||||
cancellationToken?.Remove(CancelAction);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static async ETTask<T> Wait<T>(this ObjectWait self, int timeout, ETCancellationToken cancellationToken = null) where T : struct, IWaitType
|
||||
{
|
||||
ResultCallback<T> tcs = new ResultCallback<T>();
|
||||
async ETTask WaitTimeout()
|
||||
{
|
||||
await self.Fiber().TimerComponent.WaitAsync(timeout, cancellationToken);
|
||||
if (cancellationToken.IsCancel())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (tcs.IsDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
self.Notify(new T() { Error = WaitTypeError.Timeout });
|
||||
}
|
||||
|
||||
WaitTimeout().Coroutine();
|
||||
|
||||
self.tcss.Add(typeof (T), tcs);
|
||||
|
||||
void CancelAction()
|
||||
{
|
||||
self.Notify(new T() { Error = WaitTypeError.Cancel });
|
||||
}
|
||||
|
||||
T ret;
|
||||
try
|
||||
{
|
||||
cancellationToken?.Add(CancelAction);
|
||||
ret = await tcs.Task;
|
||||
}
|
||||
finally
|
||||
{
|
||||
cancellationToken?.Remove(CancelAction);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void Notify<T>(this ObjectWait self, T obj) where T : struct, IWaitType
|
||||
{
|
||||
Type type = typeof (T);
|
||||
if (!self.tcss.TryGetValue(type, out object tcs))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self.tcss.Remove(type);
|
||||
((ResultCallback<T>) tcs).SetResult(obj);
|
||||
}
|
||||
}
|
||||
|
||||
[ComponentOf]
|
||||
public class ObjectWait: Entity, IAwake, IDestroy
|
||||
{
|
||||
public Dictionary<Type, object> tcss = new Dictionary<Type, object>();
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user