Created
June 22, 2023 11:43
-
-
Save Daxten/5c479c14240aaf33eafd87a51c52b993 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Threading; | |
using Cysharp.Threading.Tasks; | |
using Cysharp.Threading.Tasks.Linq; | |
using Mirage; | |
using Mirage.Collections; | |
using Mirage.Serialization; | |
namespace NetworkCore | |
{ | |
public interface ISyncLink { } | |
[Serializable] | |
public class SyncLink<T> : AsyncReactiveProperty<T>, ISyncObject, ISyncLink where T : NetworkBehaviour | |
{ | |
[NonSerialized] | |
private uint _netId; | |
[NonSerialized] | |
private CancellationTokenSource _ct; | |
private static readonly EqualityComparer<T> Comparer = EqualityComparer<T>.Default; | |
public bool HasValue => !Comparer.Equals(Value, null); | |
public SyncLink() : this(default) | |
{ | |
_netId = 0; | |
} | |
public SyncLink(T entity) : base(entity) | |
{ | |
if (!Comparer.Equals(entity, null)) | |
{ | |
_netId = entity.NetId; | |
} | |
this.Subscribe(_ => DidChange()); | |
} | |
private void DidChange() | |
{ | |
if (Comparer.Equals(Value, null) && _netId != 0) | |
{ | |
_netId = 0; | |
IsDirty = true; | |
OnChange?.Invoke(); | |
return; | |
} | |
if (Comparer.Equals(Value, null) || Value.Identity.NetId == _netId && Value.Identity.IsSpawned) return; | |
if (!Value.Identity.IsSpawned) | |
Value.Identity.OnStartServer.AddListener(UpdateNetId); | |
else | |
UpdateNetId(); | |
} | |
private void UpdateNetId() | |
{ | |
_netId = Value.NetId; | |
IsDirty = true; | |
OnChange?.Invoke(); | |
} | |
void ISyncObject.SetShouldSyncFrom(bool shouldSync) | |
{ | |
} | |
public void Flush() | |
{ | |
IsDirty = false; | |
} | |
public void OnSerializeAll(NetworkWriter writer) | |
{ | |
writer.WritePackedUInt32(_netId); | |
} | |
public void OnSerializeDelta(NetworkWriter writer) | |
{ | |
OnSerializeAll(writer); | |
} | |
public void OnDeserializeAll(NetworkReader reader) | |
{ | |
_ct?.Cancel(); | |
AsyncDeserializeAll(reader).Forget(); | |
} | |
private async UniTaskVoid AsyncDeserializeAll(NetworkReader reader) | |
{ | |
var netId = reader.ReadPackedUInt32(); | |
if (netId == _netId) return; | |
if (netId > 0) | |
{ | |
_netId = netId; | |
NetworkIdentity target; | |
var locator = reader.ToMirageReader().ObjectLocator; | |
if (!locator.TryGetIdentity(_netId, out target)) | |
{ | |
_ct = new CancellationTokenSource(); | |
await UniTask.WaitUntil(() => locator.TryGetIdentity(_netId, out target), | |
PlayerLoopTiming.EarlyUpdate, _ct.Token); | |
} | |
Value = target.GetComponent<T>(); | |
} | |
else | |
{ | |
_netId = 0; | |
Value = null; | |
} | |
OnChange?.Invoke(); | |
} | |
public void OnDeserializeDelta(NetworkReader reader) | |
{ | |
OnDeserializeAll(reader); | |
} | |
public void Reset() | |
{ | |
_netId = 0; | |
IsDirty = false; | |
} | |
public bool IsDirty { get; private set; } | |
public event Action OnChange; | |
public static implicit operator T(SyncLink<T> d) => d.Value; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment