[+] 接入ET8服务端

[+] 接入ET8服务端
This commit is contained in:
ALEXTANG
2023-07-13 12:23:48 +08:00
parent e0be062006
commit 336d4b2eb9
1316 changed files with 130657 additions and 626 deletions

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a78339a190b64d92ba482cd00b239f52
timeCreated: 1682422635

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 248572437c2f47728e0191da78943fe5
timeCreated: 1681719619

View File

@@ -0,0 +1,7 @@
namespace ET
{
public interface IActorRoom: IActorMessage
{
long PlayerId { get; set; }
}
}

View File

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

View File

@@ -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);
}
}

View File

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

View File

@@ -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);
}
}

View File

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

View File

@@ -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;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f1af7fd8703b4dc3a521ef52d538d168
timeCreated: 1681819811

View 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);
}
}
}
}

View File

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

View File

@@ -0,0 +1,9 @@
using System;
namespace ET
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class LSEntitySystemAttribute: BaseAttribute
{
}
}

View File

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

View File

@@ -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);
}
}
}
}
}

View File

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

View 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);
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
namespace ET
{
[ComponentOf(typeof(LSUnit))]
public class LSInputComponent: LSEntity, ILSUpdate, IAwake, ISerializeToEntity
{
public LSInput LSInput { get; set; }
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e0df77bdfbbb4a5fa2e9de116dabaaa2
timeCreated: 1682051388

View 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;
}
}
}

View File

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

View File

@@ -0,0 +1,7 @@
namespace ET
{
[ComponentOf(typeof(LSWorld))]
public class LSUnitComponent: LSEntity, IAwake, ISerializeToEntity
{
}
}

View File

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

View 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);
}
}
}

View File

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

View 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);
}
}
}

View File

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

View File

@@ -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);
}
}
}

View File

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

View 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();
}
}

View File

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

View 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; }
// 计算fixedTimefixedTime在客户端是动态调整的会做时间膨胀缩放
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; }
}
}

View File

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