This commit is contained in:
CortexCore
2024-03-31 23:31:00 +08:00
parent e179d2eb53
commit b7b89ee71a
641 changed files with 31286 additions and 22134 deletions

View File

@@ -0,0 +1,21 @@
{
"name": "BITKit.Entities.Net",
"rootNamespace": "",
"references": [
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
"GUID:709caf8d7fb6ef24bbba0ab9962a3ad0",
"GUID:d525ad6bd40672747bde77962f1c401e",
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
"GUID:9354affc93e0f3e4a904785e7d4c0f59",
"GUID:c56f2ae4d67b9b947a600c84225206a2"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: c27e9384ceefce34796410b6135e54a5
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,172 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Timers;
using BITKit.Entities.Player;
using UnityEngine;
namespace BITKit.Entities
{
[Serializable]
public struct EntitiesNetSyncCommand
{
public byte[] Data;
}
[Serializable]
public struct EntitiesNetSyncBatchCommand
{
public int Length;
public ulong[] Ids;
public ulong[] AddressablePaths;
public EntitiesNetSyncCommand[] Commands;
}
public class EntitiesNetService : MonoBehaviour
{
[Header(Constant.Header.Services)]
[SerializeReference, SubclassSelector] private ITicker ticker;
[SerializeReference, SubclassSelector] private IEntitiesService entitiesService;
[SerializeReference, SubclassSelector] private IPlayerService playerService;
[SerializeReference, SubclassSelector]private INetClient client;
[SerializeReference, SubclassSelector]private INetServer server;
private INetProvider clientNetProvider => client.Source as INetProvider;
private INetProvider serverNetProvider => server.Source as INetProvider;
[Inject]
private IEntityBinaryHeader _playerHeader;
[Inject] private IAddressable _playerAddressable;
[Inject]
private IEntity _playerEntity;
private readonly ConcurrentQueue<EntitiesNetSyncBatchCommand> _batchCommands = new();
private readonly ConcurrentQueue<EntitiesNetSyncCommand> _syncCommands = new();
private void Start()
{
ticker.Add(Tick);
clientNetProvider.AddCommandListener<EntitiesNetSyncBatchCommand>(_batchCommands.Enqueue);
serverNetProvider.AddCommandListener<EntitiesNetSyncCommand>(_syncCommands.Enqueue);
playerService.OnPlayerInitialized+=OnPlayerInitialized;
playerService.OnPlayerDisposed += OnPlayerDisposed;
destroyCancellationToken.Register(() =>
{
ticker.Remove(Tick);
playerService.OnPlayerInitialized-=OnPlayerInitialized;
});
}
private void OnPlayerDisposed(Entity obj)
{
_playerHeader = null;
_playerAddressable = null;
_playerEntity = null;
}
private void OnPlayerInitialized(Entity obj)
{
obj.Inject(this);
}
private void OnSyncCommand(EntitiesNetSyncCommand obj)
{
using var ms = new MemoryStream(obj.Data);
using var reader = new BinaryReader(ms);
var id = reader.ReadUInt64();
var path = reader.ReadUInt64();
entitiesService.GetOrAdd(id, x => AddEntity(id, path)).TryGetComponent<IEntityBinaryHeader>(out var header);
header.Deserialize(reader);
}
private void OnBatchCommand(EntitiesNetSyncBatchCommand obj)
{
for (var i = 0; i < obj.Length; i++)
{
var id = obj.Ids[i];
var path = obj.AddressablePaths[i];
var command = obj.Commands[i];
var entity = entitiesService.GetOrAdd(id,x=>AddEntity(id,path));
entity.TryGetComponent<IEntityBinaryHeader>(out var header);
using var ms = new MemoryStream(command.Data);
using var reader = new BinaryReader(ms);
header.Deserialize(reader);
}
}
private static IEntity AddEntity(ulong id,ulong addressableId)
{
var entity = AddressableHelper.Get<GameObject>(addressableId);
var instance = Instantiate(entity).GetComponent<Entity>();
instance.Id = id;
instance.WaitForInitializationComplete();
return instance;
}
private void Tick(float deltaTime)
{
while (_batchCommands.TryDequeue(out var command))
{
OnBatchCommand(command);
}
while (_syncCommands.TryDequeue(out var command))
{
OnSyncCommand(command);
}
if (client.IsConnected is false && server.IsRunningServer is false) return;
using var memoryStream = new MemoryStream();
if (client.IsConnected && _playerEntity as Entity && _playerHeader != null)
{
using var writer = new BinaryWriter(memoryStream);
writer.Write(_playerEntity.Id);
writer.Write(_playerAddressable.AddressableId);
_playerHeader.Serialize(writer);
var command = new EntitiesNetSyncCommand
{
Data = memoryStream.ToArray()
};
clientNetProvider.ServerCommand(command);
}
else if (server.IsRunningServer)
{
using var writer = new BinaryWriter(memoryStream);
var headers = entitiesService.QueryComponents<IEntity, IEntityBinaryHeader, IAddressable>();
var batchCommand = new EntitiesNetSyncBatchCommand()
{
Length = headers.Length,
Ids = new ulong[headers.Length],
AddressablePaths = new ulong[headers.Length],
Commands = new EntitiesNetSyncCommand[headers.Length]
};
var count = -1;
foreach (var (entity, header, addressable) in headers)
{
count++;
using var ms = new MemoryStream();
using var entityWriter = new BinaryWriter(ms);
header.Serialize(entityWriter);
entityWriter.Flush();
batchCommand.Ids[count] = entity.Id;
batchCommand.AddressablePaths[count] = addressable.AddressableId;
batchCommand.Commands[count] = new EntitiesNetSyncCommand { Data = ms.ToArray() };
}
serverNetProvider.AllClientCommand(batchCommand);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: eac64f495178d7844bf83d3b03736ea1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,32 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace BITKit.Entities
{
public sealed class EntityNetConfig : EntityBehavior
{
[SerializeField] private bool serverOnly;
[SerializeReference,SubclassSelector] private INetClient netClient;
[SerializeReference,SubclassSelector] private INetServer netServer;
[SerializeReference,SubclassSelector] private ITicker ticker;
public override void OnStart()
{
base.OnStart();
ticker?.Add(OnTick);
}
private void OnDestroy()
{
ticker?.Remove(OnTick);
}
private void OnTick(float deltaTime)
{
if (netClient.IsConnected && serverOnly)
{
Destroy(gameObject);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 58fae32cecb66cc42925dedf4fde21bd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: