2024-08-31 15:35:12 +08:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using AppGame.Sync;
|
2024-08-17 14:27:18 +08:00
|
|
|
|
using DotRecast.Core.Collections;
|
2024-08-22 20:37:39 +08:00
|
|
|
|
using JNGame.Math;
|
2024-08-17 14:27:18 +08:00
|
|
|
|
using JNGame.Sync.Entity;
|
|
|
|
|
using JNGame.Sync.Frame.Entity.Components;
|
|
|
|
|
using JNGame.Sync.State.Tile;
|
|
|
|
|
using JNGame.Sync.State.Tile.Entity;
|
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
|
|
|
|
|
{
|
|
|
|
|
|
2024-08-22 20:37:39 +08:00
|
|
|
|
public interface ISTileDataSystem
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 清除指定区域数据
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void ClearTileData(int index);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取有权限的全部字节
|
|
|
|
|
/// </summary>
|
2024-08-31 15:35:12 +08:00
|
|
|
|
public Dictionary<ulong, byte[]> GetHostDataBytes(Func<JNTileEntity,bool> filter = null);
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取有权限的全部字节 (过滤条件 : 需同步从服务器)
|
|
|
|
|
/// </summary>
|
|
|
|
|
public Dictionary<ulong, byte[]> GetHostDataBytesFilterSlave(Func<JNTileEntity,bool> filter = null);
|
2024-08-22 20:37:39 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取指定区块的全部字节
|
|
|
|
|
/// </summary>
|
2024-08-31 15:35:12 +08:00
|
|
|
|
public Dictionary<ulong, byte[]> GetTileDataBytes(int index,Func<JNTileEntity,bool> filter = null);
|
2024-08-22 20:37:39 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-17 14:27:18 +08:00
|
|
|
|
public abstract class ISTileData : ISStateData
|
|
|
|
|
{
|
2024-08-31 15:35:12 +08:00
|
|
|
|
|
2024-08-22 20:37:39 +08:00
|
|
|
|
public JNTileEntity Entity;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2024-08-31 15:35:12 +08:00
|
|
|
|
/// 绑定实体到数据
|
2024-08-22 20:37:39 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="entity"></param>
|
2024-08-31 15:35:12 +08:00
|
|
|
|
public virtual void BindEntity(JNTileEntity entity)
|
2024-08-22 20:37:39 +08:00
|
|
|
|
{
|
|
|
|
|
Entity = entity;
|
2024-08-31 15:35:12 +08:00
|
|
|
|
Id = entity.Id;
|
2024-08-22 20:37:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取数据位置(用于区块清除)
|
|
|
|
|
/// </summary>
|
|
|
|
|
public abstract LVector3 GetDataPosition();
|
|
|
|
|
|
2024-08-17 14:27:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 支持区块的数据类
|
|
|
|
|
/// </summary>
|
2024-08-22 20:37:39 +08:00
|
|
|
|
public abstract class STileDataSystem<T,E> : SStateDataSystem<T>,ISTileDataSystem where T : ISTileData,new() where E : JNTileEntity, new()
|
2024-08-17 14:27:18 +08:00
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
public abstract JNTileContext<E> NodeContext { get; }
|
2024-08-31 15:35:12 +08:00
|
|
|
|
|
|
|
|
|
public JNSSTileServerService TileSync => Sync as JNSSTileServerService;
|
|
|
|
|
public bool IsMaster => TileSync is not null && TileSync.IsMaster;
|
|
|
|
|
public bool IsSlave => TileSync is not null && TileSync.IsSlave;
|
2024-08-22 20:37:39 +08:00
|
|
|
|
|
2024-08-17 14:27:18 +08:00
|
|
|
|
|
|
|
|
|
protected STileDataSystem(SStateDataEnum type) : base(type)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-31 21:05:29 +08:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-23 10:48:19 +08:00
|
|
|
|
public override void OnUByteUpdate(Dictionary<ulong, byte[]> bytes)
|
2024-08-17 14:27:18 +08:00
|
|
|
|
{
|
|
|
|
|
base.OnUByteUpdate(bytes);
|
|
|
|
|
if (isServer)
|
|
|
|
|
{
|
|
|
|
|
OnDataSyncContext();
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-08-31 15:35:12 +08:00
|
|
|
|
|
|
|
|
|
public override void OnSendUBytes(Dictionary<ulong, byte[]> bytes)
|
|
|
|
|
{
|
|
|
|
|
Dictionary<ulong, byte[]> all = bytes;
|
|
|
|
|
Dictionary<ulong, byte[]> master = new Dictionary<ulong, byte[]>();
|
|
|
|
|
Dictionary<ulong, byte[]> slave = new Dictionary<ulong, byte[]>();
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
}
|
2024-08-17 14:27:18 +08:00
|
|
|
|
|
2024-08-31 15:35:12 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 发送玩家数据
|
|
|
|
|
/// </summary>
|
|
|
|
|
public abstract void OnSendAllData(Dictionary<ulong, byte[]> bytes);
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 发送主服务器数据
|
|
|
|
|
/// </summary>
|
|
|
|
|
public virtual void OnSendMasterData(Dictionary<ulong, byte[]> bytes){}
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 发送从服务器数据
|
|
|
|
|
/// </summary>
|
|
|
|
|
public virtual void OnSendSlaveData(Dictionary<ulong, byte[]> bytes){}
|
|
|
|
|
|
2024-08-17 14:27:18 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 将数据Data同步到Context
|
|
|
|
|
/// </summary>
|
|
|
|
|
protected virtual void OnDataSyncContext()
|
|
|
|
|
{
|
|
|
|
|
|
2024-08-23 10:48:19 +08:00
|
|
|
|
Dictionary<ulong, T> lIsTileData;
|
2024-08-22 20:37:39 +08:00
|
|
|
|
|
|
|
|
|
lock (Data)
|
|
|
|
|
{
|
2024-08-23 10:48:19 +08:00
|
|
|
|
lIsTileData = new Dictionary<ulong, T>(Data);
|
2024-08-22 20:37:39 +08:00
|
|
|
|
}
|
2024-08-17 14:27:18 +08:00
|
|
|
|
|
|
|
|
|
NodeContext.GetEntities().ForEach(child =>
|
|
|
|
|
{
|
|
|
|
|
//如果有则删除
|
|
|
|
|
if (lIsTileData.Remove(child.Id,out var data))
|
|
|
|
|
{
|
2024-08-21 16:18:52 +08:00
|
|
|
|
//同步不属于自己的实体
|
|
|
|
|
if (!child.IsHost)
|
|
|
|
|
{
|
|
|
|
|
//并且同步属性到实体中
|
|
|
|
|
child.TileSyncData(data);
|
|
|
|
|
}
|
2024-08-17 14:27:18 +08:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
//将数据同步到实体中
|
|
|
|
|
foreach (var keyValue in lIsTileData)
|
|
|
|
|
{
|
|
|
|
|
var entity = NodeContext.TileSyncCreate(keyValue.Key);
|
2024-08-31 21:05:29 +08:00
|
|
|
|
|
|
|
|
|
//如果当前是从服务器则同步的实体都是 从 主服务器 同步给 从服务器
|
|
|
|
|
if (IsSlave) entity.IsSyncSlave = true;
|
2024-08-22 20:37:39 +08:00
|
|
|
|
entity?.TileSyncData(keyValue.Value);
|
|
|
|
|
//将实体绑定到数据中
|
|
|
|
|
keyValue.Value.BindEntity(entity);
|
2024-08-17 14:27:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//只更新有权限的实体
|
|
|
|
|
public override void Update(T data)
|
|
|
|
|
{
|
2024-08-31 15:35:12 +08:00
|
|
|
|
var entity = NodeContext.Query(data.Id);
|
2024-08-31 21:05:29 +08:00
|
|
|
|
if (IsMaster)
|
|
|
|
|
{
|
|
|
|
|
if (entity is null || !entity.IsHost) return;
|
|
|
|
|
}
|
2024-08-17 14:27:18 +08:00
|
|
|
|
base.Update(data);
|
|
|
|
|
}
|
|
|
|
|
public override void Add(T data)
|
|
|
|
|
{
|
2024-08-31 15:35:12 +08:00
|
|
|
|
var entity = NodeContext.Query(data.Id);
|
2024-08-31 21:05:29 +08:00
|
|
|
|
if (IsMaster)
|
|
|
|
|
{
|
|
|
|
|
if (entity is null || !entity.IsHost) return;
|
|
|
|
|
}
|
2024-08-17 14:27:18 +08:00
|
|
|
|
base.Add(data);
|
|
|
|
|
}
|
2024-08-22 20:37:39 +08:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 判断数据是否在区块内
|
|
|
|
|
/// </summary>
|
|
|
|
|
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
|
2024-08-23 10:48:19 +08:00
|
|
|
|
var ids = new List<ulong>();
|
2024-08-22 20:37:39 +08:00
|
|
|
|
|
|
|
|
|
Data.ForEach(child =>
|
|
|
|
|
{
|
|
|
|
|
if (IsTileInside(index,child.Value)) ids.Add(child.Key);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
//删除数据和实体
|
|
|
|
|
ids.ForEach(child =>
|
|
|
|
|
{
|
|
|
|
|
//销毁实体
|
|
|
|
|
Data[child].Entity?.Destroy();
|
|
|
|
|
//销毁数据
|
|
|
|
|
Data.Remove(child);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-31 15:35:12 +08:00
|
|
|
|
public Dictionary<ulong, byte[]> GetHostDataBytesFilterSlave(Func<JNTileEntity,bool> filter = null)
|
2024-08-22 20:37:39 +08:00
|
|
|
|
{
|
|
|
|
|
|
2024-08-31 15:35:12 +08:00
|
|
|
|
if (filter is null) filter = entity => true;
|
|
|
|
|
return GetHostDataBytes(entity => entity.IsSyncSlave && filter(entity) );
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Dictionary<ulong, byte[]> GetHostDataBytes(Func<JNTileEntity,bool> filter = null)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (filter is null) filter = entity => true;
|
|
|
|
|
|
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 =>
|
|
|
|
|
{
|
2024-08-31 15:35:12 +08:00
|
|
|
|
var entity = NodeContext.Query(child.Key);
|
|
|
|
|
if (entity is not null && entity.IsHost && filter(entity))
|
2024-08-22 20:37:39 +08:00
|
|
|
|
{
|
|
|
|
|
data[child.Key] = child.Value.GetByte();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return data;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-31 15:35:12 +08:00
|
|
|
|
public Dictionary<ulong, byte[]> GetTileDataBytes(int index,Func<JNTileEntity,bool> filter = null)
|
2024-08-22 20:37:39 +08:00
|
|
|
|
{
|
|
|
|
|
|
2024-08-31 15:35:12 +08:00
|
|
|
|
if (filter is null) filter = entity => true;
|
|
|
|
|
|
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 =>
|
|
|
|
|
{
|
2024-08-31 15:35:12 +08:00
|
|
|
|
var entity = NodeContext.Query(child.Key);
|
|
|
|
|
if (IsTileInside(index,child.Value) && filter(entity))
|
2024-08-22 20:37:39 +08:00
|
|
|
|
{
|
|
|
|
|
data[child.Key] = child.Value.GetByte();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return data;
|
|
|
|
|
|
|
|
|
|
}
|
2024-08-17 14:27:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|