mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-06-26 03:14:47 +00:00
219 lines
5.7 KiB
C#
219 lines
5.7 KiB
C#
using System.Collections.Generic;
|
|
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
|
|
{
|
|
|
|
/// <summary>
|
|
/// 清除指定区域数据
|
|
/// </summary>
|
|
public void ClearTileData(int index);
|
|
|
|
/// <summary>
|
|
/// 获取有权限的全部字节
|
|
/// </summary>
|
|
public Dictionary<ulong, byte[]> GetHostDataBytes();
|
|
|
|
|
|
/// <summary>
|
|
/// 获取指定区块的全部字节
|
|
/// </summary>
|
|
public Dictionary<ulong, byte[]> GetTileDataBytes(int index);
|
|
|
|
|
|
|
|
}
|
|
|
|
public abstract class ISTileData : ISStateData
|
|
{
|
|
public abstract bool IsHost { get; }
|
|
public JNTileEntity Entity;
|
|
|
|
/// <summary>
|
|
/// 绑定实体到数据 (销毁数据时顺带销毁实体)
|
|
/// </summary>
|
|
/// <param name="entity"></param>
|
|
public void BindEntity(JNTileEntity entity)
|
|
{
|
|
Entity = entity;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取数据位置(用于区块清除)
|
|
/// </summary>
|
|
public abstract LVector3 GetDataPosition();
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// 支持区块的数据类
|
|
/// </summary>
|
|
public abstract class STileDataSystem<T,E> : SStateDataSystem<T>,ISTileDataSystem where T : ISTileData,new() where E : JNTileEntity, new()
|
|
{
|
|
|
|
public abstract JNTileContext<E> NodeContext { get; }
|
|
|
|
|
|
|
|
protected STileDataSystem(SStateDataEnum type) : base(type)
|
|
{
|
|
}
|
|
|
|
public override void OnUByteUpdate(Dictionary<ulong, byte[]> bytes)
|
|
{
|
|
base.OnUByteUpdate(bytes);
|
|
if (isServer)
|
|
{
|
|
OnDataSyncContext();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 将数据Data同步到Context
|
|
/// </summary>
|
|
protected virtual void OnDataSyncContext()
|
|
{
|
|
|
|
Dictionary<ulong, T> lIsTileData;
|
|
|
|
lock (Data)
|
|
{
|
|
lIsTileData = new Dictionary<ulong, T>(Data);
|
|
}
|
|
|
|
NodeContext.GetEntities().ForEach(child =>
|
|
{
|
|
//如果有则删除
|
|
if (lIsTileData.Remove(child.Id,out var data))
|
|
{
|
|
//同步不属于自己的实体
|
|
if (!child.IsHost)
|
|
{
|
|
//并且同步属性到实体中
|
|
child.TileSyncData(data);
|
|
}
|
|
}
|
|
});
|
|
|
|
//将数据同步到实体中
|
|
foreach (var keyValue in lIsTileData)
|
|
{
|
|
var entity = NodeContext.TileSyncCreate(keyValue.Key);
|
|
entity?.TileSyncData(keyValue.Value);
|
|
//将实体绑定到数据中
|
|
keyValue.Value.BindEntity(entity);
|
|
}
|
|
|
|
}
|
|
|
|
//只更新有权限的实体
|
|
public override void Update(T data)
|
|
{
|
|
if (!data.IsHost) return;
|
|
base.Update(data);
|
|
}
|
|
public override void Add(T data)
|
|
{
|
|
if (!data.IsHost) return;
|
|
base.Add(data);
|
|
}
|
|
|
|
/// <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
|
|
var ids = new List<ulong>();
|
|
|
|
Data.ForEach(child =>
|
|
{
|
|
if (IsTileInside(index,child.Value)) ids.Add(child.Key);
|
|
});
|
|
|
|
//删除数据和实体
|
|
ids.ForEach(child =>
|
|
{
|
|
//销毁实体
|
|
Data[child].Entity?.Destroy();
|
|
//销毁数据
|
|
Data.Remove(child);
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
public Dictionary<ulong, byte[]> GetHostDataBytes()
|
|
{
|
|
|
|
var data = new Dictionary<ulong, byte[]>();
|
|
|
|
lock (Data)
|
|
{
|
|
Data.ForEach(child =>
|
|
{
|
|
if (child.Value.IsHost)
|
|
{
|
|
data[child.Key] = child.Value.GetByte();
|
|
}
|
|
});
|
|
}
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
public Dictionary<ulong, byte[]> GetTileDataBytes(int index)
|
|
{
|
|
|
|
var data = new Dictionary<ulong, byte[]>();
|
|
|
|
lock (Data)
|
|
{
|
|
Data.ForEach(child =>
|
|
{
|
|
if (IsTileInside(index,child.Value))
|
|
{
|
|
data[child.Key] = child.Value.GetByte();
|
|
}
|
|
});
|
|
}
|
|
|
|
return data;
|
|
|
|
}
|
|
}
|
|
|
|
} |