using System; using System.Collections.Concurrent; using System.Collections.Generic; using AppGame.Sync; using DotRecast.Core.Collections; using JNGame.Math; using JNGame.Sync.Entity; using JNGame.Sync.Frame.Entity.Components; using JNGame.Sync.State.Tile; using JNGame.Sync.State.Tile.Entity; using NotImplementedException = System.NotImplementedException; namespace JNGame.Sync.System.Data { public interface ISTileDataSystem { /// /// 清除指定区域数据 /// public void ClearTileData(int index); /// /// 获取有权限的全部字节 /// public Dictionary GetHostDataBytes(Func filter = null); /// /// 获取有权限的全部字节 (过滤条件 : 需同步从服务器) /// public Dictionary GetHostDataBytesFilterSlave(Func filter = null); /// /// 获取指定区块的全部字节 /// public Dictionary GetTileDataBytes(int index,Func filter = null); } public abstract class ISTileData : ISStateData { public JNTileEntity Entity; //是否需要主动推送一次[一般用在从服务器获得主服务器消息后主动给客户端推送] 为什么不会自动推送因为这个实体自己没有权限 public bool IsActiveSyncOnce = false; /// /// 绑定实体到数据 /// /// public virtual void BindEntity(JNTileEntity entity) { Entity = entity; Id = entity.Id; } /// /// 获取数据位置(用于区块清除) /// public abstract LVector3 GetDataPosition(); } /// /// 支持区块的数据类 /// public abstract class STileDataSystem : SStateDataSystem,ISTileDataSystem where T : ISTileData,new() where E : JNTileEntity, new() { public abstract JNTileContext NodeContext { get; } public JNSSTileServerService TileSync => Sync as JNSSTileServerService; public bool IsMaster => TileSync is not null && TileSync.IsMaster; public bool IsSlave => TileSync is not null && TileSync.IsSlave; protected STileDataSystem(SStateDataEnum type) : base(type) { } public override ConcurrentDictionary GetLatest() { var nodes = new ConcurrentDictionary(); 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[child.Id] = entity; }); return nodes; } public override void OnUByteUpdate(Dictionary bytes) { base.OnUByteUpdate(bytes); if (isServer) { OnDataSyncContext(); } } public override void OnSyncUpdate(int dt) { //如果不是Tile系统直接调用base if (Sync is not JNSSTileServerService) { base.OnSyncUpdate(dt); return; } while (WaitUBytes.Count > 0) { OnUByteUpdate(WaitUBytes.Dequeue()); } //服务器: 发送最近数据 if (isServer) { var latest = GetLatest(); latest.Keys.ForEach(key => { if (Data.ContainsKey(key)) { //更新数据 Update(latest[key]); } else { //如果之前没有则添加 Add(latest[key]); } }); Data.ForEach(child => { //没有则删除 if (NodeContext.Query(child.Key) is null) { Delete(child.Key); return; } //主动更新 if (child.Value.IsActiveSyncOnce) { child.Value.IsActiveSyncOnce = false; UBytes[child.Key] = child.Value.GetByte(); } }); if (UBytes.Count > 0) { OnUByteUpdate(UBytes); OnSendUBytes(UBytes); UBytes.Clear(); } } } public override void OnSendUBytes(Dictionary bytes) { Dictionary all = bytes; Dictionary master = new Dictionary(); Dictionary slave = new Dictionary(); all.ForEach(keyValue => { var entity = NodeContext.Query(keyValue.Key); //给从服务器发送数据 if (IsMaster && entity is not null && entity.IsSyncSlave) { slave[keyValue.Key] = keyValue.Value; } }); OnSendAllData(all); OnSendMasterData(master); OnSendSlaveData(slave); } /// /// 发送玩家数据 /// public abstract void OnSendAllData(Dictionary bytes); /// /// 发送主服务器数据 /// public virtual void OnSendMasterData(Dictionary bytes){} /// /// 发送从服务器数据 /// public virtual void OnSendSlaveData(Dictionary bytes){} /// /// 将数据Data同步到Context /// protected virtual void OnDataSyncContext() { Dictionary lIsTileData = new Dictionary(Data); NodeContext.GetEntities().ForEach(child => { //如果有则删除 if (lIsTileData.Remove(child.Id,out var data)) { //同步不属于自己的实体 if (!child.IsHost) { //并且同步属性到实体中 child.TileSyncData(data); //如果是从服务器则主动推送数据 if (IsSlave) data.IsActiveSyncOnce = true; } } }); //将数据同步到实体中 foreach (var keyValue in lIsTileData) { var entity = NodeContext.TileSyncCreate(keyValue.Key); if (entity is null) continue; if (IsSlave) { //如果当前是从服务器则同步的实体都是 从 主服务器 同步给 从服务器 entity.IsSyncSlave = true; //如果是从服务器则主动推送数据 if (IsSlave) keyValue.Value.IsActiveSyncOnce = true; } entity?.TileSyncData(keyValue.Value); entity?.HostUpdate(); //将实体绑定到数据中 keyValue.Value.BindEntity(entity); } } //只更新有权限的实体 public override void Update(T data) { var entity = NodeContext.Query(data.Id); 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 (IsMaster) { if (entity is null || !entity.IsHost) return; } base.Add(data); } /// /// 判断数据是否在区块内 /// public bool IsTileInside(int tileId,T data) { var index = -1; if (Sync is JNSSTileClientService clientService) { index = clientService.GetTileIndex(data.GetDataPosition()); } if (Sync is JNSSTileServerService serverService) { index = serverService.GetTileIndex(data.GetDataPosition()); } return index == tileId; } public void ClearTileData(int index) { lock (Data) { //需要删除的数据Id var ids = new List(); Data.ForEach(child => { if (IsTileInside(index,child.Value)) ids.Add(child.Key); }); //删除数据和实体 ids.ForEach(child => { //销毁实体 Data[child].Entity?.Destroy(); //销毁数据 Data.Remove(child,out var remove); }); } } public Dictionary GetHostDataBytesFilterSlave(Func filter = null) { if (filter is null) filter = entity => true; return GetHostDataBytes(entity => entity.IsSyncSlave && filter(entity) ); } public Dictionary GetHostDataBytes(Func filter = null) { if (filter is null) filter = entity => true; var data = new Dictionary(); lock (Data) { Data.ForEach(child => { var entity = NodeContext.Query(child.Key); if (entity is not null && entity.IsHost && filter(entity)) { data[child.Key] = child.Value.GetByte(); } }); } return data; } public Dictionary GetTileDataBytes(int index,Func filter = null) { if (filter is null) filter = entity => true; var data = new Dictionary(); lock (Data) { Data.ForEach(child => { var entity = NodeContext.Query(child.Key); if (IsTileInside(index,child.Value) && filter(entity)) { data[child.Key] = child.Value.GetByte(); } }); } return data; } } }