提交Unity 联机Pro

This commit is contained in:
PC-20230316NUNE\Administrator
2024-08-17 14:27:18 +08:00
parent f00193b000
commit 894100ae37
7448 changed files with 854473 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a35faa1bd10344b8bbd360443c77d455
timeCreated: 1721722812

View File

@@ -0,0 +1,16 @@
namespace JNGame.Sync.System.Data
{
/// <summary>
/// 帧同步的数据系统 (不支持网络数据)
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class SFrameDataSystem<T> : SDataSystem<T> where T : ISData,new()
{
public override void OnSyncUpdate()
{
Data = GetLatest();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6607845a00924069953887b35ecfa68a
timeCreated: 1721722862

View File

@@ -0,0 +1,201 @@
using System.Collections.Generic;
using DotRecast.Core.Collections;
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; }
public void OnInsertUBytes(Dictionary<long, byte[]> bytes);
}
/// <summary>
/// 状态同步的数据系统 (支持网络数据)
/// 注意:帧同步也可以使用不过不建议 因为会有额外开销 除非你的游戏 经常在帧同步或者状态同步之间切换
/// </summary>
public abstract class SStateDataSystem<T> : SDataSystem<T>,ISStateDataSystem where T : ISStateData,new()
{
public abstract int NetID { get; }
//网络通讯的更新字节数据
protected Dictionary<long, byte[]> 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();
}
}
}
/// <summary>
/// 发送字节数据
/// </summary>
/// <param name="bytes"></param>
/// <returns>是否清空UBytes</returns>
public abstract void OnSendUBytes(Dictionary<long, byte[]> bytes);
/// <summary>
/// 插入字节
/// </summary>
/// <returns></returns>
public void OnInsertUBytes(Dictionary<long, byte[]> bytes)
{
//提交数据更新
OnUByteUpdate(bytes);
}
/// <summary>
/// 将UByte提交更新
/// </summary>
public virtual void OnUByteUpdate(Dictionary<long, byte[]> bytes)
{
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);
}
}
}
}
/// <summary>
/// Byte解析新对象
/// </summary>
/// <param name="id"></param>
/// <param name="bytes"></param>
/// <returns></returns>
public T NewObject(long id,byte[] bytes)
{
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>
public virtual void Delete(long id)
{
UBytes[id] = SDByteOperate.DELETE;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f86e0dbea9824eceb7de44e113c3f29b
timeCreated: 1721722979

View File

@@ -0,0 +1,77 @@
using System.Collections.Generic;
using DotRecast.Core.Collections;
using JNGame.Sync.Entity;
using JNGame.Sync.Frame.Entity.Components;
using JNGame.Sync.State.Tile;
using JNGame.Sync.State.Tile.Entity;
namespace JNGame.Sync.System.Data
{
public abstract class ISTileData : ISStateData
{
public abstract bool IsHost { get; }
}
/// <summary>
/// 支持区块的数据类
/// </summary>
public abstract class STileDataSystem<T,E> : SStateDataSystem<T> 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<long, byte[]> bytes)
{
base.OnUByteUpdate(bytes);
if (isServer)
{
OnDataSyncContext();
}
}
/// <summary>
/// 将数据Data同步到Context
/// </summary>
protected virtual void OnDataSyncContext()
{
var lIsTileData = new Dictionary<long, T>(Data);
NodeContext.GetEntities().ForEach(child =>
{
//如果有则删除
if (lIsTileData.Remove(child.Id,out var data))
{
//并且同步属性到实体中
child.TileSyncData(data);
}
});
//将数据同步到实体中
foreach (var keyValue in lIsTileData)
{
var entity = NodeContext.TileSyncCreate(keyValue.Key);
entity.TileSyncData(keyValue.Value);
}
}
//只更新有权限的实体
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);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 64294f09974c48ca82724ebb3e1a3338
timeCreated: 1722477295

View File

@@ -0,0 +1,187 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Google.Protobuf;
using JNGame.Util.Types;
using Newtonsoft.Json;
namespace JNGame.Sync.System.View
{
/// <summary>
/// Json的输入类
/// </summary>
public class JNInputJson : JNInputBase
{
public byte[] Encoder()
{
return Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(this));
}
public virtual object Decoder(byte[] bytes)
{
return JsonConvert.DeserializeObject(Encoding.UTF8.GetString(bytes),this.GetType());
}
}
public interface JNInputBase
{
/// <summary>
/// 编码
/// </summary>
/// <returns></returns>
public byte[] Encoder();
/// <summary>
/// 解码
/// </summary>
public object Decoder(byte[] bytes);
}
public abstract class JNInputSystem : SLogicSystem
{
protected abstract KeyValue<Type, int> TClass { get; }
protected Dictionary<Type, JNInputBase> TNewClass = new ();
protected readonly Dictionary<int, JNInputBase> Inputs = new ();
protected readonly Dictionary<int, Dictionary<int,JNInputBase>> SInputs = new ();
protected Dictionary<int,JNFrameInput> frame = new();
/// <summary>
/// 移入数据
/// </summary>
public void Enqueue(JNFrameInput input)
{
frame[input.NId] = input;
}
protected JNInputSystem()
{
OnInit();
OnApply();
}
protected virtual void OnInit(){}
/// <summary>
/// 应用
/// </summary>
protected virtual void OnApply()
{
TNewClass.Clear();
foreach (var key in TClass.Keys)
{
TNewClass.Add(key,Activator.CreateInstance(key) as JNInputBase);
}
}
public override void OnSyncUpdate()
{
base.OnSyncUpdate();
UpdateSInputs();
}
/// <summary>
/// 获取同步输入(逻辑中获取 不可修改)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public JNInputBase SInput<T>(int clientId) where T : JNInputBase, new()
{
var key = TClass.Key2Value(typeof(T));
if (SInputs.TryGetValue(key, out var inputs))
{
inputs.TryGetValue(clientId,out var input);
return input;
}
return null;
}
public Dictionary<int,JNInputBase> SInput<T>() where T : JNInputBase, new()
{
var key = TClass.Key2Value(typeof(T));
if (SInputs.TryGetValue(key, out var inputs))
{
return inputs;
}
return new();
}
public JNInputBase SInputOne<T>() where T : JNInputBase, new()
{
var key = TClass.Key2Value(typeof(T));
if (SInputs.TryGetValue(key, out var inputs))
{
if (inputs.Count > 0)
{
return inputs.Values.First();
}
return null;
}
return null;
}
/// <summary>
/// 获取输入 (禁止在逻辑中获取 只允许在UI层调用)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public T Input<T>() where T : JNInputBase,new()
{
if (!(Inputs.TryGetValue(TClass.Key2Value(typeof(T)),out var input)))
{
Inputs[TClass.Key2Value(typeof(T))] = input = new T();
}
return (T)input;
}
/// <summary>
/// 移出输入
/// </summary>
/// <returns></returns>
public JNFrameInputs Dequeue()
{
JNFrameInputs inputs = new JNFrameInputs();
foreach (var key in Inputs.Keys)
{
var input = new JNFrameInput();
var info = Inputs[key];
input.NId = key;
input.Input = ByteString.CopyFrom(info.Encoder());
inputs.Inputs.Add(input);
}
Inputs.Clear();
return inputs;
}
/// <summary>
/// 移入输入
/// </summary>
public void UpdateSInputs()
{
SInputs.Clear();
//解析输入
foreach (var kInput in frame)
{
var input = kInput.Value;
var tClass = TClass.Value2Key(input.NId);
if (!(SInputs.TryGetValue(input.NId,out var inputs)))
{
SInputs.Add(input.NId, inputs = new Dictionary<int, JNInputBase>());
}
inputs.Add(input.ClientId,TNewClass[tClass].Decoder(input.Input.ToByteArray()) as JNInputBase);
}
frame.Clear();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a6c14ce606094eecbc415faab78bb5ad
timeCreated: 1721635056

View File

@@ -0,0 +1,56 @@
using System;
using JNGame.Math;
using JNGame.Sync.System;
using Plugins.JNGame.Util;
namespace JNGame.Sync.Frame.Service
{
/// <summary>
/// 随机数
/// </summary>
public class JNRandomSystem : SLogicSystem
{
//随机数
private Func<LFloat,LFloat,LFloat> nRandomFloat;
private Func<int,int,int> nRandomInt;
//Id
private long _id = 0;
public JNRandomSystem(int seed)
{
nRandomFloat = RandomUtil.SyncRandomFloat(seed);
nRandomInt = RandomUtil.SyncRandomInt(seed);
}
public LFloat Float()
{
return Float(0,1);
}
public LFloat Float(LFloat min,LFloat max)
{
return nRandomFloat(min,max);
}
public int Int(int max,int min)
{
return nRandomInt(max,min);
}
public long NextId()
{
return ++_id;
}
public void SetIdValue(long id)
{
if (_id < id)
{
_id = id;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 30a8e21f1e344fb59f39047129fce186
timeCreated: 1721187856

View File

@@ -0,0 +1,16 @@
using Entitas;
using JNGame.Sync.Entity;
using NotImplementedException = System.NotImplementedException;
namespace JNGame.Sync.System
{
/// <summary>
/// 同步 - 基础系统
/// </summary>
public class SBaseSystem : JNBaseSystem
{
public JNContexts Contexts;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 12633ea43bb44b6ba2e88bafd0a6bb6e
timeCreated: 1721009209

View File

@@ -0,0 +1,89 @@
using System.Collections.Generic;
using System.Linq;
using DotRecast.Core.Collections;
using JNGame.Sync.Frame.Service;
using NotImplementedException = System.NotImplementedException;
namespace JNGame.Sync.System
{
public class SDByteOperate
{
public static readonly byte[] DELETE = { 0 }; //删除
public static bool IsDelete(byte[] value)
{
return value.Length == 1 && value[0] == DELETE[0];
}
}
/// <summary>
/// 数据接口
/// </summary>
public abstract class ISData : IJNSyncId
{
/// <summary>
/// 数据唯一Id
/// </summary>
public long Id { get; set; }
/// <summary>
/// 判断是否一样
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public abstract bool IsEquals(ISData data);
}
public abstract class SDataSystemBase : SBaseSystem,IJNSyncCycle
{
public abstract void OnSyncStart();
public abstract void OnSyncUpdate();
public virtual void OnSyncDestroy()
{ }
}
/// <summary>
/// 状态系统 - 数据层
/// </summary>
public abstract class SDataSystem<T> : SDataSystemBase where T : ISData,new()
{
//数据Id
public long Id { get; private set; }
public JNRandomSystem Random => GetSystem<JNRandomSystem>();
//数据集
public Dictionary<long, T> Data = new();
public virtual T[] Datas {
get
{
lock (Data)
{
return Data.Values.ToArray();
}
}
}
public override void OnSyncStart()
{
//设置数据唯一Id
Id = Random.NextId();
}
/// <summary>
/// 返回最新数据 (收集最新的ISData数据 正常来讲只有服务端会运行)
/// </summary>
public virtual Dictionary<long, T> GetLatest()
{
return new ();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4cc5c86befd84d0a98fbfe2c3ccf1073
timeCreated: 1721039079

View File

@@ -0,0 +1,33 @@
using JNGame.Sync.Frame.Service;
using NotImplementedException = System.NotImplementedException;
namespace JNGame.Sync.System
{
/// <summary>
/// 帧同步 - 逻辑系统
/// </summary>
public class SLogicSystem : SBaseSystem,IJNSyncCycle,IJNSyncId
{
private long _id;
public long Id => _id;
public virtual void OnSyncStart()
{
JNRandomSystem random;
if (this is JNRandomSystem) random = (JNRandomSystem)this;
else random = GetSystem<JNRandomSystem>();
_id = random.NextId();
}
public virtual void OnSyncUpdate()
{
}
public void OnSyncDestroy(){}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 479b71cc642641aeb965e980ee3580e5
timeCreated: 1721187888

View File

@@ -0,0 +1,22 @@
using Entitas;
using NotImplementedException = System.NotImplementedException;
namespace JNGame.Sync.System
{
/// <summary>
/// 帧同步 - 视图系统
/// </summary>
public class SViewSystem : SBaseSystem,IJNSyncCycle,IExecuteSystem
{
public virtual void Execute(){}
public virtual void OnSyncStart()
{
}
public virtual void OnSyncUpdate()
{
}
public virtual void OnSyncDestroy()
{
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7c655f765f124661b81d5be2c7555206
timeCreated: 1721008791

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ae13387f055c48969fe5a2229582c832
timeCreated: 1721635230