1
This commit is contained in:
21
Src/Unity/Scripts/Entity/Net/BITKit.Entities.Net.asmdef
Normal file
21
Src/Unity/Scripts/Entity/Net/BITKit.Entities.Net.asmdef
Normal 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
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c27e9384ceefce34796410b6135e54a5
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
172
Src/Unity/Scripts/Entity/Net/EntitiesNetService.cs
Normal file
172
Src/Unity/Scripts/Entity/Net/EntitiesNetService.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Src/Unity/Scripts/Entity/Net/EntitiesNetService.cs.meta
Normal file
11
Src/Unity/Scripts/Entity/Net/EntitiesNetService.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eac64f495178d7844bf83d3b03736ea1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
32
Src/Unity/Scripts/Entity/Net/EntityNetConfig.cs
Normal file
32
Src/Unity/Scripts/Entity/Net/EntityNetConfig.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
11
Src/Unity/Scripts/Entity/Net/EntityNetConfig.cs.meta
Normal file
11
Src/Unity/Scripts/Entity/Net/EntityNetConfig.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 58fae32cecb66cc42925dedf4fde21bd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user