This commit is contained in:
PC-20230316NUNE\Administrator
2024-08-31 21:05:29 +08:00
parent d67032e1de
commit 77b305be7a
53 changed files with 316 additions and 118 deletions

View File

@@ -11,9 +11,9 @@ namespace JNGame.Sync.State.Tile.Entity
public class JNTileContext<T> : JNContext<T> where T : JNTileEntity, new()
{
private JNSSTileServerService SyncTile => base.Sync as JNSSTileServerService;
private JNSSTileServerService SyncTile => Sync as JNSSTileServerService;
public override void OnSyncUpdate()
public override void OnSyncUpdate(int dt)
{
foreach (var entity in base.GetEntities())
{
@@ -21,6 +21,10 @@ namespace JNGame.Sync.State.Tile.Entity
//生命周期
bool isContains = SyncTile.IsContains(entity.Position);
bool isHost = entity.IsHost;
//从服务器 如果数据不是自己创建的则自己永远没有权限
if (SyncTile.IsSlave && !(entity.IsSelfCreate)) isContains = false;
entity.IsHost = isContains;
//区块进入生命周期
@@ -37,28 +41,36 @@ namespace JNGame.Sync.State.Tile.Entity
//判断实体是否在所属区块 在则 更新
if (entity.IsHost)
{
entity.OnSyncUpdate();
entity.OnSyncUpdate(dt);
}
}
}
public override T CreateEntity()
{
var entity = NewEntity();
BindInitialize(entity);
entity.IsHost = true;
entity.IsSelfCreate = true;
BindComponent(entity);
BindLifeCycle(entity);
return entity;
}
public T TileSyncCreate(ulong id)
{
//判断是否有这个Id实体
foreach (var data in GetEntities())
if (Entities.ContainsKey(id))
{
if (data.Id == id)
{
Debug.Log("重复Id实体创建");
return null;
}
Debug.Log("重复Id实体创建");
return null;
}
var entity = NewEntity();
entity.OnInit(this,id);
entity.IsHost = false;
entity.IsSelfCreate = false;
BindComponent(entity);
BindLifeCycle(entity);
return entity;

View File

@@ -43,13 +43,42 @@ namespace JNGame.Sync.State.Tile.Entity
/// </summary>
public bool IsHost { get; set; } = false;
/// <summary>
/// 是否自己服务器创建
/// </summary>
public bool IsSelfCreate { get; set; } = false;
/// <summary>
/// 是否将数据同步到从服务器
/// </summary>
public bool IsSyncSlave { get; set; } = false;
/// <summary>
/// 是否将数据同步到主服务器
/// 是否将数据同步到主服务器 (目前没有这个场景 压根想不到这个场景使用所以遗弃)
/// 其中一个场景就是 主服务器的玩家要攻击从服务器的实体
/// 这个场景是不可能遇到的 因为 违背的设计
/// 1. 从服务器是用来解决主服务器实体多 导致同步流量高 而出现的解决方案
/// 如果将从服务器的实体同步到主服务器那么就违背了设计思路 导致主服务器流量增加
/// 2. 这种场景直接主服务器创建这个实体就可以了 没必要 从 从服务器里创建在同步给主服务器 多此一举
///
/// 衍生问题 : 多人大乱斗的场景怎么办
/// 1. 主从服务器的模式并不能解决这个场景 主从服务器解决的场景有两种:
/// 1.主从服务器适用的场景是所有人攻击主服务器的某个实体 比如世界 Boss
/// 2.可以作为独立服务器存在 比如一个区块人满了 就创建一个独立的服务器
/// 让后面的人加入到新的服务器中 比如逆水寒右上角选择分场景 这时候的
/// 从服务器是不会和主服务器有任何交集的
/// 2. 如果要解决多人大乱斗的场景 怎么解决 ?
/// 1.解决这个问题的首先 要知道问题所在 问题的所在也是玩家多了之后同步
/// 的实体就会很多 怎么解决?
/// 2.这时候要引出另一种架构 主服务器 - [list]数据层服务器 - [list]玩家
/// 通过中间的数据层服务器去给玩家发送状态从而解决主服务器流量压力
/// 3.主服务器每次更新状态时候 将状态分别发送给 所有数据层服务器 有玩家
/// 加入就给玩家分配其中一个数据层服务器 通过这个数据层服务器 去同步
/// 数据
/// 4.当然 上面的是解决主服务压力 如果场景很多实体 会出现同步实体过多
/// 导致客户端接受到的状态数据非常多 从而客户端也有流量压力 所以这时候
/// 数据层服务器要增加一个功能 通过玩家位置 发送附近的状态数据 和 过滤
/// 指定实体来解决客户端流量压力 (这种优化点适用任何的状态同步)
/// </summary>
public bool IsSyncMaster { get; set; } = false;

View File

@@ -7,6 +7,13 @@ namespace JNGame.Sync.Frame.Entity.Component.Components
{
public class JNTransformComponent : JNComponent
{
public LVector3 Position = new();
public bool IsRange(LVector3 target,LFloat len)
{
return LVector3.Distance(Position, target) <= len;
}
}
}

View File

@@ -24,7 +24,7 @@ namespace JNGame.Sync.Entity.Component
//生命周期
public virtual void OnSyncStart(){}
public virtual void OnSyncUpdate(){}
public virtual void OnSyncUpdate(int dt){}
public virtual void OnSyncDestroy(){}
}
}

View File

@@ -88,7 +88,7 @@ namespace JNGame.Sync.Frame.Entity
return entity;
}
public sealed override T CreateEntity()
public override T CreateEntity()
{
var entity = NewEntity();
BindInitialize(entity);
@@ -100,14 +100,14 @@ namespace JNGame.Sync.Frame.Entity
//帧同步 生命周期
public virtual void OnSyncStart(){}
public virtual void OnSyncUpdate()
public virtual void OnSyncUpdate(int dt)
{
//给实体推帧
foreach (var entity in GetEntities())
{
if (entity.isEnabled)
{
entity.OnSyncUpdate();
entity.OnSyncUpdate(dt);
}
}
}

View File

@@ -23,7 +23,7 @@ namespace JNGame.Sync.Entity
{
for (var i = 0; i < allContexts.Length; i++)
{
(allContexts[i] as IJNContext)?.OnSyncUpdate();
(allContexts[i] as IJNContext)?.OnSyncUpdate(Sync.DeltaTime);
}
}

View File

@@ -136,12 +136,12 @@ namespace JNGame.Sync.Entity
//生命周期
public virtual void OnSyncStart(){}
public virtual void OnSyncUpdate()
public virtual void OnSyncUpdate(int dt)
{
//给组件推帧
foreach (var component in GetComponents())
{
(component as JNComponent)?.OnSyncUpdate();
(component as JNComponent)?.OnSyncUpdate(dt);
}
}

View File

@@ -14,7 +14,7 @@
/// <summary>
/// 实体每帧刷新
/// </summary>
public void OnSyncUpdate();
public void OnSyncUpdate(int dt);
/// <summary>
/// 实体销毁

View File

@@ -116,13 +116,13 @@ namespace JNGame.Sync.Frame
if (syncSystemInfos[i].isActive){
var time = DateTime.Now.Ticks;
_syncSystems[i].OnSyncUpdate();
_syncSystems[i].OnSyncUpdate(DeltaTime);
double time1 = (DateTime.Now.Ticks - time) / 10000f;
syncSystemInfos[i].AddSyncUpdateDuration(time1);
}
#else
_syncSystems[i].OnSyncUpdate();
_syncSystems[i].OnSyncUpdate(DeltaTime);
#endif
}

View File

@@ -7,7 +7,7 @@
public abstract class SFrameDataSystem<T> : SDataSystem<T> where T : ISData,new()
{
public override void OnSyncUpdate()
public override void OnSyncUpdate(int dt)
{
Data = GetLatest();
}

View File

@@ -70,6 +70,9 @@ namespace JNGame.Sync.System.Data
public bool isServer => Type is SStateDataEnum.ServerClient or SStateDataEnum.Server;
public bool isClient => Type is SStateDataEnum.ServerClient or SStateDataEnum.Client;
//待插入的数据
private Queue<Dictionary<ulong, byte[]>> WaitUBytes = new ();
protected SStateDataSystem(SStateDataEnum type)
{
@@ -77,8 +80,12 @@ namespace JNGame.Sync.System.Data
}
public override void OnSyncUpdate()
public override void OnSyncUpdate(int dt)
{
while (WaitUBytes.Count > 0)
{
OnUByteUpdate(WaitUBytes.Dequeue());
}
//服务器: 发送最近数据
if (isServer)
@@ -125,8 +132,7 @@ namespace JNGame.Sync.System.Data
/// <returns></returns>
public void OnInsertUBytes(Dictionary<ulong, byte[]> bytes)
{
//提交数据更新
OnUByteUpdate(bytes);
WaitUBytes.Enqueue(bytes);
}
/// <summary>

View File

@@ -78,6 +78,26 @@ namespace JNGame.Sync.System.Data
{
}
public override Dictionary<ulong, T> GetLatest()
{
var nodes = new Dictionary<ulong, T>();
E[] entities = null;
if (IsMaster)
{
entities = NodeContext.GetHostEntities();
}else if (IsSlave)
{
entities = NodeContext.GetEntities();
}
entities.ForEach(child =>
{
var entity = new T();
entity.BindEntity(child);
nodes.Add(child.Id,entity);
});
return nodes;
}
public override void OnUByteUpdate(Dictionary<ulong, byte[]> bytes)
{
base.OnUByteUpdate(bytes);
@@ -153,6 +173,9 @@ namespace JNGame.Sync.System.Data
foreach (var keyValue in lIsTileData)
{
var entity = NodeContext.TileSyncCreate(keyValue.Key);
//如果当前是从服务器则同步的实体都是 从 主服务器 同步给 从服务器
if (IsSlave) entity.IsSyncSlave = true;
entity?.TileSyncData(keyValue.Value);
//将实体绑定到数据中
keyValue.Value.BindEntity(entity);
@@ -164,13 +187,19 @@ namespace JNGame.Sync.System.Data
public override void Update(T data)
{
var entity = NodeContext.Query(data.Id);
if (entity is null || !entity.IsHost) return;
if (IsMaster)
{
if (entity is null || !entity.IsHost) return;
}
base.Update(data);
}
public override void Add(T data)
{
var entity = NodeContext.Query(data.Id);
if (entity is null || !entity.IsHost) return;
if (IsMaster)
{
if (entity is null || !entity.IsHost) return;
}
base.Add(data);
}

View File

@@ -79,9 +79,9 @@ namespace JNGame.Sync.System.View
}
}
public override void OnSyncUpdate()
public override void OnSyncUpdate(int dt)
{
base.OnSyncUpdate();
base.OnSyncUpdate(dt);
UpdateSInputs();
}

View File

@@ -41,7 +41,7 @@ namespace JNGame.Sync.System
{
public abstract void OnSyncStart();
public abstract void OnSyncUpdate();
public abstract void OnSyncUpdate(int dt);
public virtual void OnSyncDestroy()
{ }

View File

@@ -23,7 +23,7 @@ namespace JNGame.Sync.System
}
public virtual void OnSyncUpdate()
public virtual void OnSyncUpdate(int dt)
{
}

View File

@@ -12,7 +12,7 @@ namespace JNGame.Sync.System
public virtual void OnSyncStart()
{
}
public virtual void OnSyncUpdate()
public virtual void OnSyncUpdate(int dt)
{
}
public virtual void OnSyncDestroy()