diff --git a/QSB/QSB.csproj b/QSB/QSB.csproj index f020c769..09b91421 100644 --- a/QSB/QSB.csproj +++ b/QSB/QSB.csproj @@ -237,6 +237,7 @@ + diff --git a/QSB/TransformSync/IntermediaryTransform.cs b/QSB/TransformSync/IntermediaryTransform.cs new file mode 100644 index 00000000..2725adbc --- /dev/null +++ b/QSB/TransformSync/IntermediaryTransform.cs @@ -0,0 +1,72 @@ +using QSB.SectorSync.WorldObjects; +using UnityEngine; + +namespace QSB.TransformSync +{ + class IntermediaryTransform + { + private Transform _attachedTransform; + private QSBSector _referenceSector; + + public IntermediaryTransform(Transform transform) + { + _attachedTransform = transform; + } + /// + /// Get the world position of this INVISIBLE transform. + /// + public Vector3 GetPosition() + => _attachedTransform.position; + + /// + /// Set the world position of this INVISIBLE transform. + /// + public void SetPosition(Vector3 worldPos) + => _attachedTransform.position = worldPos; + + /// + /// Get the world rotation of this INVISIBLE transform. + /// + public Quaternion GetRotation() + => _attachedTransform.rotation; + + /// + /// Set the world rotation of this INVISIBLE transform. + /// + public void SetRotation(Quaternion worldRot) + => _attachedTransform.rotation = worldRot; + + /// + /// Sets the reference sector - what sector this transform is syncing to. + /// + /// The new reference sector. + public void SetReferenceSector(QSBSector sector) + => _referenceSector = sector; + + /// + /// Sets the position of the INVISIBLE transform to be correct, according to the reference sector and the position of the VISIBLE transform. + /// + /// The world position of the VISIBLE transform. + public void EncodePosition(Vector3 worldPosition) + => SetPosition(_referenceSector.Transform.InverseTransformPoint(worldPosition)); + + /// + /// Sets the rotation of the INVISIBLE transform to be correct, according to the reference sector and the rotation of the VISIBLE transform. + /// + /// The world rotation of the VISIBLE transform. + public void EncodeRotation(Quaternion worldRotation) + => SetRotation(_referenceSector.Transform.InverseTransformRotation(worldRotation)); + + /// + /// Gets what the VISIBLE transform's position should be, from the reference sector and the position of the INVISIBLE transform. + /// + public Vector3 GetTargetPosition() + => GetPosition(); + + /// + /// Gets what the VISIBLE transform's rotation should be, from the reference sector and the rotation of the INVISIBLE transform. + /// + public Quaternion GetTargetRotation() + => GetRotation(); + } +} diff --git a/QSB/TransformSync/QSBNetworkTransform.cs b/QSB/TransformSync/QSBNetworkTransform.cs index 87c9e693..f59c2e1b 100644 --- a/QSB/TransformSync/QSBNetworkTransform.cs +++ b/QSB/TransformSync/QSBNetworkTransform.cs @@ -35,6 +35,7 @@ namespace QSB.TransformSync private float _previousDistance; private Vector3 _positionSmoothVelocity; private Quaternion _rotationSmoothVelocity; + private IntermediaryTransform _intermediaryTransform; public virtual void Start() { @@ -47,6 +48,7 @@ namespace QSB.TransformSync NetworkTransformList.Add(this); DontDestroyOnLoad(gameObject); + _intermediaryTransform = new IntermediaryTransform(transform); QSBSceneManager.OnSceneLoaded += OnSceneLoaded; } @@ -78,6 +80,10 @@ namespace QSB.TransformSync public override void SerializeTransform(QNetworkWriter writer) { + if (_intermediaryTransform == null) + { + _intermediaryTransform = new IntermediaryTransform(transform); + } if (ReferenceSector != null) { writer.Write(ReferenceSector.ObjectId); @@ -87,10 +93,12 @@ namespace QSB.TransformSync writer.Write(-1); } - writer.Write(transform.position); - SerializeRotation(writer, transform.rotation); - _prevPosition = transform.position; - _prevRotation = transform.rotation; + var worldPos = _intermediaryTransform.GetPosition(); + var worldRot = _intermediaryTransform.GetRotation(); + writer.Write(worldPos); + SerializeRotation(writer, worldRot); + _prevPosition = worldPos; + _prevRotation = worldRot; } public override void DeserializeTransform(QNetworkReader reader) @@ -121,10 +129,10 @@ namespace QSB.TransformSync return; } - transform.position = pos; - transform.rotation = rot; + _intermediaryTransform.SetPosition(pos); + _intermediaryTransform.SetRotation(rot); - if (transform.position == Vector3.zero) + if (_intermediaryTransform.GetPosition() == Vector3.zero) { DebugLog.ToConsole($"Warning - {PlayerId}.{GetType().Name} at (0,0,0)! - Given position was {pos} at sector {sector?.Name}", MessageType.Warning); } @@ -162,23 +170,23 @@ namespace QSB.TransformSync { if (HasAuthority) { - transform.position = ReferenceSector.Transform.InverseTransformPoint(AttachedObject.transform.position); - transform.rotation = ReferenceSector.Transform.InverseTransformRotation(AttachedObject.transform.rotation); + _intermediaryTransform.EncodePosition(AttachedObject.transform.position); + _intermediaryTransform.EncodeRotation(AttachedObject.transform.rotation); } else { - var localToWorldPos = ReferenceSector.Transform.TransformPoint(transform.position); - var localToWorldRot = ReferenceSector.Transform.TransformRotation(transform.rotation); - AttachedObject.transform.localPosition = SmartSmoothDamp(AttachedObject.transform.localPosition, localToWorldPos); - AttachedObject.transform.localRotation = QuaternionHelper.SmoothDamp(AttachedObject.transform.localRotation, localToWorldRot, ref _rotationSmoothVelocity, SmoothTime); + var targetPos = _intermediaryTransform.GetTargetPosition(); + var targetRot = _intermediaryTransform.GetTargetRotation(); + AttachedObject.transform.localPosition = SmartSmoothDamp(AttachedObject.transform.localPosition, targetPos); + AttachedObject.transform.localRotation = QuaternionHelper.SmoothDamp(AttachedObject.transform.localRotation, targetRot, ref _rotationSmoothVelocity, SmoothTime); } } public override bool HasMoved() { - var displacementMagnitude = (transform.position - _prevPosition).magnitude; + var displacementMagnitude = (_intermediaryTransform.GetPosition() - _prevPosition).magnitude; return displacementMagnitude > 1E-03f - || Quaternion.Angle(transform.rotation, _prevRotation) > 1E-03f; + || Quaternion.Angle(_intermediaryTransform.GetRotation(), _prevRotation) > 1E-03f; } public void SetReferenceSector(QSBSector sector) @@ -188,6 +196,7 @@ namespace QSB.TransformSync return; } ReferenceSector = sector; + _intermediaryTransform.SetReferenceSector(sector); if (AttachedObject == null) { DebugLog.ToConsole($"Warning - AttachedObject was null for {PlayerId}.{GetType().Name} when trying to set reference sector to {sector.Name}. Waiting until not null...", MessageType.Warning); @@ -238,7 +247,7 @@ namespace QSB.TransformSync return; } - Popcron.Gizmos.Cube(transform.position, transform.rotation, Vector3.one / 2, Color.red); + Popcron.Gizmos.Cube(_intermediaryTransform.GetTargetPosition(), _intermediaryTransform.GetTargetRotation(), Vector3.one / 2, Color.red); var color = HasMoved() ? Color.green : Color.yellow; Popcron.Gizmos.Cube(AttachedObject.transform.position, AttachedObject.transform.rotation, Vector3.one / 2, color); Popcron.Gizmos.Line(AttachedObject.transform.position, ReferenceSector.Transform.position, Color.cyan);