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