using System.Collections.Generic;
using DotRecast.Core.Collections;
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 SStateDataSystem(SStateDataEnum type)
{
Type = type;
}
public override void OnSyncUpdate()
{
//服务器: 发送最近数据
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)
{
OnInsertUBytes(UBytes);
OnSendUBytes(UBytes);
UBytes.Clear();
}
}
}
///
/// 发送字节数据
///
///
/// 是否清空UBytes
public abstract void OnSendUBytes(Dictionary bytes);
///
/// 插入字节
///
///
public void OnInsertUBytes(Dictionary bytes)
{
//提交数据更新
OnUByteUpdate(bytes);
}
///
/// 获取全部字节
///
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)
{
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;
}
}
}