using System;
using System.Collections.Generic;
using System.Linq;
using Mirror;
namespace PrefsGUI.Sync
{
///
/// Spawnデータの分割対応したダミーのSyncObject
///
/// 受信した分割Spawnデータとその間のDeltaデータを保存し、Spawnデータが全て揃った段階でまとめて本来のSyncObjectに反映する
///
public class DividedSpawnDataReceiverSyncObject : SyncObject, IDisposable
{
public readonly SyncObject baseSyncObject;
private readonly List> _spawnDataList = new();
private readonly List> _deltaDataList = new();
public DividedSpawnDataReceiverSyncObject(SyncObject baseSyncObject) => this.baseSyncObject = baseSyncObject;
#region override SyncObject
public override void ClearChanges()
{
}
public override void OnSerializeAll(NetworkWriter writer)
{
}
public override void OnSerializeDelta(NetworkWriter writer)
{
}
public override void OnDeserializeAll(NetworkReader reader)
{
}
public override void OnDeserializeDelta(NetworkReader reader)
{
// readerを進めるために一旦SyncObjectのOnDeserializeDeltaを呼ぶ
// ここで適用された値は私用せずApplyStockDataで改めて適用する
var startPosition = reader.Position;
baseSyncObject.OnDeserializeDelta(reader);
var size = reader.Position - startPosition;
reader.Position = startPosition;
var bytes = reader.ReadBytesSegment(size);
AddDeltaData(bytes);
}
public override void Reset()
{
}
#endregion
public void AddDividedSpawnData(ArraySegment bytesVolatile)
{
// このbytesVolatileはNetworkReaderの参照なのでいずれ上書きされるっぽい
// コピーして保存する
var bytes = ArraySegmentPooled.Get(bytesVolatile.Count);
bytesVolatile.CopyTo(bytes);
_spawnDataList.Add(bytes);
}
private void AddDeltaData(ArraySegment bytesVolatile)
{
// このbytesVolatileはNetworkReaderの参照なのでいずれ上書きされるはず
// コピーして保存する
var bytes = ArraySegmentPooled.Get(bytesVolatile.Count);
bytesVolatile.CopyTo(bytes);
_deltaDataList.Add(bytes);
}
public void ApplyStockData()
{
baseSyncObject.Reset();
ApplySpawnData();
ApplyDeltaData();
}
private void ApplySpawnData()
{
var size = _spawnDataList.Sum(x => x.ArraySegment.Count);
using var totalBytes = ArraySegmentPooled.Get(size);
var position = 0;
foreach (var arraySegmentPooled in _spawnDataList)
{
var arraySegment = arraySegmentPooled.ArraySegment;
arraySegment.CopyTo(totalBytes.ArraySegment.Slice(position, arraySegment.Count));
position += arraySegment.Count;
arraySegmentPooled.Dispose();
}
_spawnDataList.Clear();
using var reader = NetworkReaderPool.Get(totalBytes);
baseSyncObject.OnDeserializeAll(reader);
}
private void ApplyDeltaData()
{
foreach (var deltaData in _deltaDataList)
{
using var reader = NetworkReaderPool.Get(deltaData);
baseSyncObject.OnDeserializeDelta(reader);
deltaData.Dispose();
}
_deltaDataList.Clear();
}
public void Dispose()
{
foreach (var arraySegmentPooled in _spawnDataList)
{
arraySegmentPooled.Dispose();
}
_spawnDataList.Clear();
foreach (var arraySegmentPooled in _deltaDataList)
{
arraySegmentPooled.Dispose();
}
_deltaDataList.Clear();
}
}
}