using System.Collections.Generic; using DotRecast.Core.Collections; using UnityEngine; using NotImplementedException = System.NotImplementedException; namespace JNGame.Sync.System.Data { public enum SStateDataEnum { Server, Client, ServerClient, } public abstract class ISStateData : ISData { /// /// 返回Byte数组 /// /// public abstract byte[] GetByte(); /// /// 返回差值Byte /// /// /// public abstract byte[] GetByteDifference(ISData diffValue = null); /// /// 更新字节 /// /// public abstract void UByte(byte[] bytes); } public interface ISStateDataSystem { //网络Id (用于确定网络通讯时找到这个数据系统) public int NetID { get; } /// /// 插入字节 /// public void OnInsertUBytes(Dictionary bytes); /// /// 获取全部字节 /// public Dictionary GetDataBytes(); } /// /// 状态同步的数据系统 (支持网络数据) /// 注意:帧同步也可以使用不过不建议 因为会有额外开销 除非你的游戏 经常在帧同步或者状态同步之间切换 /// public abstract class SStateDataSystem : SDataSystem,ISStateDataSystem where T : ISStateData,new() { public abstract int NetID { get; } //网络通讯的更新字节数据 protected Dictionary UBytes = new(); public SStateDataEnum Type; public bool isServer => Type is SStateDataEnum.ServerClient or SStateDataEnum.Server; public bool isClient => Type is SStateDataEnum.ServerClient or SStateDataEnum.Client; //待插入的数据 protected Queue> WaitUBytes = new (); protected SStateDataSystem(SStateDataEnum type) { Type = type; } public override void OnSyncUpdate(int dt) { 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 (!(latest.ContainsKey(child.Key))) Delete(child.Key); }); if (UBytes.Count > 0) { OnUByteUpdate(UBytes); OnSendUBytes(UBytes); UBytes.Clear(); } } } /// /// 发送字节数据 /// /// /// 是否清空UBytes public abstract void OnSendUBytes(Dictionary bytes); /// /// 插入字节 /// /// public void OnInsertUBytes(Dictionary bytes) { if (bytes is not null) { WaitUBytes.Enqueue(bytes); } else { Debug.Log("有数据是空"); } } /// /// 获取全部字节 /// public Dictionary GetDataBytes() { var data = new Dictionary(); lock (Data) { Data.ForEach(child => { data[child.Key] = child.Value.GetByte(); }); } return data; } /// /// 将UByte提交更新 /// public virtual void OnUByteUpdate(Dictionary bytes) { if (bytes is null) return; lock (Data) { foreach (var info in bytes) { if (SDByteOperate.IsDelete(info.Value)) { Data.Remove(info.Key); } else { if (Data.TryGetValue(info.Key, out var value)) { value.UByte(info.Value); } else { Data[info.Key] = NewObject(info.Key,info.Value); } } } } } /// /// Byte解析新对象 /// /// /// /// public T NewObject(ulong id,byte[] bytes) { var data = new T(); data.Id = id; data.UByte(bytes); return data; } /// /// 刷新数据 /// public virtual void Update(T data) { if (Data.TryGetValue(data.Id, out var value)) { var diff = value.GetByteDifference(data); if (diff.Length > 0) { UBytes[data.Id] = diff; } } else { UBytes[data.Id] = data.GetByte(); } } /// /// 添加数据 /// public virtual void Add(T data) { UBytes[data.Id] = data.GetByte(); } /// /// 删除数据 /// public virtual void Delete(ulong id) { UBytes[id] = SDByteOperate.DELETE; } } }