quantum-space-buddies/QSB/Syncs/Sectored/Rigidbodies/SectoredRigidbodySync.cs
Mister_Nebula 03f615525b cleanup
2021-11-25 15:32:34 +00:00

214 lines
5.9 KiB
C#

using OWML.Common;
using QSB.Utility;
using QuantumUNET.Transport;
using UnityEngine;
namespace QSB.Syncs.Sectored.Rigidbodies
{
public abstract class SectoredRigidbodySync : BaseSectoredSync
{
public override bool ShouldReparentAttachedObject => false;
public const float PositionMovedThreshold = 0.05f;
public const float AngleRotatedThreshold = 0.05f;
public const float VelocityChangeThreshold = 0.05f;
public const float AngVelocityChangeThreshold = 0.05f;
protected Vector3 _relativeVelocity;
protected Vector3 _relativeAngularVelocity;
protected Vector3 _prevVelocity;
protected Vector3 _prevAngularVelocity;
/// <summary>
/// The previous position of the VISIBLE object, as if parented to the reference.
/// </summary>
protected Vector3 _localPrevPosition;
/// <summary>
/// The previous rotation of the VISIBLE object, as if parented to the reference.
/// </summary>
protected Quaternion _localPrevRotation;
protected Vector3 _localPrevVelocity;
protected Vector3 _localPrevAngularVelocity;
protected abstract OWRigidbody GetRigidbody();
protected override Component SetAttachedObject()
=> GetRigidbody();
public override void SerializeTransform(QNetworkWriter writer, bool initialState)
{
base.SerializeTransform(writer, initialState);
var worldPos = transform.position;
var worldRot = transform.rotation;
var relativeVelocity = _relativeVelocity;
var relativeAngularVelocity = _relativeAngularVelocity;
writer.Write(worldPos);
SerializeRotation(writer, worldRot);
writer.Write(relativeVelocity);
writer.Write(relativeAngularVelocity);
_prevPosition = worldPos;
_prevRotation = worldRot;
_prevVelocity = relativeVelocity;
_prevAngularVelocity = relativeAngularVelocity;
}
public override void DeserializeTransform(QNetworkReader reader, bool initialState)
{
base.DeserializeTransform(reader, initialState);
if (!QSBCore.WorldObjectsReady)
{
reader.ReadVector3();
DeserializeRotation(reader);
reader.ReadVector3();
reader.ReadVector3();
return;
}
var pos = reader.ReadVector3();
var rot = DeserializeRotation(reader);
var relativeVelocity = reader.ReadVector3();
var relativeAngularVelocity = reader.ReadVector3();
if (HasAuthority)
{
return;
}
transform.position = pos;
transform.rotation = rot;
_relativeVelocity = relativeVelocity;
_relativeAngularVelocity = relativeAngularVelocity;
if (transform.position == Vector3.zero)
{
DebugLog.ToConsole($"Warning - {LogName} at (0,0,0)! - Given position was {pos}", MessageType.Warning);
}
}
protected void SetValuesToSync()
{
transform.position = ReferenceTransform.EncodePos(AttachedObject.transform.position);
transform.rotation = ReferenceTransform.EncodeRot(AttachedObject.transform.rotation);
_relativeVelocity = ReferenceTransform.GetAttachedOWRigidbody().EncodeVel(((OWRigidbody)AttachedObject).GetVelocity(), AttachedObject.transform.position);
_relativeAngularVelocity = ReferenceTransform.GetAttachedOWRigidbody().EncodeAngVel(((OWRigidbody)AttachedObject).GetAngularVelocity());
}
protected override bool UpdateTransform()
{
if (!base.UpdateTransform())
{
return false;
}
if (HasAuthority)
{
SetValuesToSync();
return true;
}
var targetPos = ReferenceTransform.DecodePos(transform.position);
var targetRot = ReferenceTransform.DecodeRot(transform.rotation);
if (targetPos == Vector3.zero || transform.position == Vector3.zero)
{
return false;
}
var positionToSet = targetPos;
var rotationToSet = targetRot;
if (UseInterpolation)
{
positionToSet = SmartSmoothDamp(AttachedObject.transform.position, targetPos);
rotationToSet = QuaternionHelper.SmoothDamp(AttachedObject.transform.rotation, targetRot, ref _rotationSmoothVelocity, SmoothTime);
}
var hasMoved = CustomHasMoved(
transform.position,
_localPrevPosition,
transform.rotation,
_localPrevRotation,
_relativeVelocity,
_localPrevVelocity,
_relativeAngularVelocity,
_localPrevAngularVelocity);
_localPrevPosition = transform.position;
_localPrevRotation = transform.rotation;
_localPrevVelocity = _relativeVelocity;
_localPrevAngularVelocity = _relativeAngularVelocity;
if (!hasMoved)
{
return true;
}
((OWRigidbody)AttachedObject).MoveToPosition(positionToSet);
((OWRigidbody)AttachedObject).MoveToRotation(rotationToSet);
var targetVelocity = ReferenceTransform.GetAttachedOWRigidbody().DecodeVel(_relativeVelocity, targetPos);
var targetAngularVelocity = ReferenceTransform.GetAttachedOWRigidbody().DecodeAngVel(_relativeAngularVelocity);
((OWRigidbody)AttachedObject).SetVelocity(targetVelocity);
((OWRigidbody)AttachedObject).SetAngularVelocity(targetAngularVelocity);
return true;
}
public override bool HasMoved()
=> CustomHasMoved(
transform.position,
_prevPosition,
transform.rotation,
_prevRotation,
_relativeVelocity,
_prevVelocity,
_relativeAngularVelocity,
_prevAngularVelocity);
// OPTIMIZE : optimize by using sqrMagnitude
private bool CustomHasMoved(
Vector3 newPosition,
Vector3 prevPosition,
Quaternion newRotation,
Quaternion prevRotation,
Vector3 newVelocity,
Vector3 prevVelocity,
Vector3 newAngVelocity,
Vector3 prevAngVelocity)
{
var displacementMagnitude = (newPosition - prevPosition).magnitude;
if (displacementMagnitude > PositionMovedThreshold)
{
return true;
}
if (Quaternion.Angle(newRotation, prevRotation) > AngleRotatedThreshold)
{
return true;
}
var velocityChangeMagnitude = (newVelocity - prevVelocity).magnitude;
var angularVelocityChangeMagnitude = (newAngVelocity - prevAngVelocity).magnitude;
if (velocityChangeMagnitude > VelocityChangeThreshold)
{
return true;
}
if (angularVelocityChangeMagnitude > AngVelocityChangeThreshold)
{
return true;
}
return false;
}
}
}