583 lines
14 KiB
C#
Raw Normal View History

2020-12-04 22:15:41 +00:00
using OWML.Logging;
2020-12-07 21:19:16 +00:00
using QuantumUNET.Messages;
2020-12-03 13:18:45 +00:00
using UnityEngine;
using UnityEngine.Networking;
2020-12-07 21:19:16 +00:00
namespace QuantumUNET.Components
2020-12-03 13:18:45 +00:00
{
public class QSBNetworkTransform : QSBNetworkBehaviour
{
2020-12-04 09:23:27 +00:00
public float SendInterval { get; set; } = 0.1f;
2020-12-16 09:07:40 +00:00
2020-12-04 09:23:27 +00:00
public AxisSyncMode SyncRotationAxis { get; set; } = AxisSyncMode.AxisXYZ;
2020-12-16 09:07:40 +00:00
2020-12-04 09:23:27 +00:00
public CompressionSyncMode RotationSyncCompression { get; set; } = CompressionSyncMode.None;
2020-12-16 09:07:40 +00:00
2020-12-04 09:23:27 +00:00
public bool SyncSpin { get; set; }
2020-12-16 09:07:40 +00:00
2020-12-04 09:23:27 +00:00
public float MovementTheshold { get; set; } = 0.001f;
2020-12-16 09:07:40 +00:00
2020-12-04 09:23:27 +00:00
public float velocityThreshold { get; set; } = 0.0001f;
2020-12-16 09:07:40 +00:00
2020-12-04 09:23:27 +00:00
public float SnapThreshold { get; set; } = 5f;
2020-12-16 09:07:40 +00:00
2020-12-04 09:23:27 +00:00
public float InterpolateRotation { get; set; } = 1f;
2020-12-16 09:07:40 +00:00
2020-12-04 09:23:27 +00:00
public float InterpolateMovement { get; set; } = 1f;
2020-12-16 09:07:40 +00:00
2020-12-04 09:23:27 +00:00
public ClientMoveCallback3D clientMoveCallback3D { get; set; }
2020-12-16 09:07:40 +00:00
2020-12-04 09:23:27 +00:00
public float LastSyncTime { get; private set; }
2020-12-16 09:07:40 +00:00
public Vector3 TargetSyncPosition
{
get
{
return m_TargetSyncPosition;
}
}
public Vector3 targetSyncVelocity
{
get
{
return m_TargetSyncVelocity;
}
}
public Quaternion targetSyncRotation3D
{
get
{
return m_TargetSyncRotation3D;
}
}
2020-12-04 09:23:27 +00:00
public bool Grounded { get; set; } = true;
2020-12-03 13:18:45 +00:00
2020-12-16 09:07:40 +00:00
private void OnValidate()
{
if (SendInterval < 0f)
{
SendInterval = 0f;
}
if (SyncRotationAxis < AxisSyncMode.None || SyncRotationAxis > AxisSyncMode.AxisXYZ)
{
SyncRotationAxis = AxisSyncMode.None;
}
if (MovementTheshold < 0f)
{
MovementTheshold = 0f;
}
if (velocityThreshold < 0f)
{
velocityThreshold = 0f;
}
if (SnapThreshold < 0f)
{
SnapThreshold = 0.01f;
}
if (InterpolateRotation < 0f)
{
InterpolateRotation = 0.01f;
}
if (InterpolateMovement < 0f)
{
InterpolateMovement = 0.01f;
}
}
private void Awake()
2020-12-03 13:18:45 +00:00
{
2020-12-04 09:23:27 +00:00
m_PrevPosition = transform.position;
m_PrevRotation = transform.rotation;
if (LocalPlayerAuthority)
2020-12-03 13:18:45 +00:00
{
2020-12-04 09:23:27 +00:00
m_LocalTransformWriter = new QSBNetworkWriter();
2020-12-03 13:18:45 +00:00
}
}
2020-12-16 09:07:40 +00:00
public override void OnStartServer()
{
LastSyncTime = 0f;
}
2020-12-03 13:18:45 +00:00
2020-12-04 09:23:27 +00:00
public override bool OnSerialize(QSBNetworkWriter writer, bool initialState)
2020-12-03 13:18:45 +00:00
{
if (!initialState)
{
2020-12-04 09:23:27 +00:00
if (SyncVarDirtyBits == 0U)
2020-12-03 13:18:45 +00:00
{
writer.WritePackedUInt32(0U);
return false;
}
writer.WritePackedUInt32(1U);
}
2020-12-04 09:23:27 +00:00
SerializeModeTransform(writer);
2020-12-03 13:18:45 +00:00
return true;
}
2020-12-04 09:23:27 +00:00
private void SerializeModeTransform(QSBNetworkWriter writer)
2020-12-03 13:18:45 +00:00
{
2020-12-04 09:23:27 +00:00
writer.Write(transform.position);
if (SyncRotationAxis != AxisSyncMode.None)
2020-12-03 13:18:45 +00:00
{
2020-12-04 09:23:27 +00:00
SerializeRotation3D(writer, transform.rotation, SyncRotationAxis, RotationSyncCompression);
2020-12-03 13:18:45 +00:00
}
2020-12-04 09:23:27 +00:00
m_PrevPosition = transform.position;
m_PrevRotation = transform.rotation;
2020-12-03 13:18:45 +00:00
}
2020-12-04 09:23:27 +00:00
public override void OnDeserialize(QSBNetworkReader reader, bool initialState)
2020-12-03 13:18:45 +00:00
{
2020-12-04 09:23:27 +00:00
if (!IsServer || !QSBNetworkServer.localClientActive)
2020-12-03 13:18:45 +00:00
{
if (!initialState)
{
if (reader.ReadPackedUInt32() == 0U)
{
return;
}
}
2020-12-04 09:23:27 +00:00
UnserializeModeTransform(reader, initialState);
LastSyncTime = Time.time;
2020-12-03 13:18:45 +00:00
}
}
2020-12-04 09:23:27 +00:00
private void UnserializeModeTransform(QSBNetworkReader reader, bool initialState)
2020-12-03 13:18:45 +00:00
{
2020-12-04 09:23:27 +00:00
if (HasAuthority)
2020-12-03 13:18:45 +00:00
{
reader.ReadVector3();
2020-12-04 09:23:27 +00:00
if (SyncRotationAxis != AxisSyncMode.None)
2020-12-03 13:18:45 +00:00
{
2020-12-04 09:23:27 +00:00
UnserializeRotation3D(reader, SyncRotationAxis, RotationSyncCompression);
2020-12-03 13:18:45 +00:00
}
}
2020-12-04 09:23:27 +00:00
else if (IsServer && clientMoveCallback3D != null)
2020-12-03 13:18:45 +00:00
{
2020-12-04 09:23:27 +00:00
var position = reader.ReadVector3();
var zero = Vector3.zero;
var rotation = Quaternion.identity;
if (SyncRotationAxis != AxisSyncMode.None)
2020-12-03 13:18:45 +00:00
{
2020-12-04 09:23:27 +00:00
rotation = UnserializeRotation3D(reader, SyncRotationAxis, RotationSyncCompression);
2020-12-03 13:18:45 +00:00
}
2020-12-04 09:23:27 +00:00
if (clientMoveCallback3D(ref position, ref zero, ref rotation))
2020-12-03 13:18:45 +00:00
{
2020-12-04 09:23:27 +00:00
transform.position = position;
if (SyncRotationAxis != AxisSyncMode.None)
2020-12-03 13:18:45 +00:00
{
2020-12-04 09:23:27 +00:00
transform.rotation = rotation;
2020-12-03 13:18:45 +00:00
}
}
}
else
{
2020-12-04 09:23:27 +00:00
transform.position = reader.ReadVector3();
if (SyncRotationAxis != AxisSyncMode.None)
2020-12-03 13:18:45 +00:00
{
2020-12-04 09:23:27 +00:00
transform.rotation = UnserializeRotation3D(reader, SyncRotationAxis, RotationSyncCompression);
2020-12-03 13:18:45 +00:00
}
}
}
private void FixedUpdate()
{
2020-12-04 09:23:27 +00:00
if (IsServer)
2020-12-03 13:18:45 +00:00
{
2020-12-04 09:23:27 +00:00
FixedUpdateServer();
2020-12-03 13:18:45 +00:00
}
}
private void FixedUpdateServer()
{
2020-12-04 09:23:27 +00:00
if (SyncVarDirtyBits == 0U)
2020-12-03 13:18:45 +00:00
{
if (QSBNetworkServer.active)
{
2020-12-04 09:23:27 +00:00
if (IsServer)
2020-12-03 13:18:45 +00:00
{
2020-12-04 09:23:27 +00:00
if (GetNetworkSendInterval() != 0f)
2020-12-03 13:18:45 +00:00
{
2020-12-04 09:23:27 +00:00
if (HasMoved())
2020-12-03 13:18:45 +00:00
{
2020-12-04 09:23:27 +00:00
SetDirtyBit(1U);
2020-12-03 13:18:45 +00:00
}
}
}
}
}
}
private void Update()
{
2020-12-04 09:23:27 +00:00
if (HasAuthority)
2020-12-03 13:18:45 +00:00
{
2020-12-04 09:23:27 +00:00
if (LocalPlayerAuthority)
2020-12-03 13:18:45 +00:00
{
if (!QSBNetworkServer.active)
{
2020-12-04 09:23:27 +00:00
if (Time.time - m_LastClientSendTime > GetNetworkSendInterval())
2020-12-03 13:18:45 +00:00
{
2020-12-04 09:23:27 +00:00
SendTransform();
m_LastClientSendTime = Time.time;
2020-12-03 13:18:45 +00:00
}
}
}
}
}
private bool HasMoved()
{
2020-12-04 09:23:27 +00:00
var num = (transform.position - m_PrevPosition).magnitude;
2020-12-03 13:18:45 +00:00
bool result;
if (num > 1E-05f)
{
result = true;
}
else
{
2020-12-04 09:23:27 +00:00
num = Quaternion.Angle(transform.rotation, m_PrevRotation);
2020-12-03 13:18:45 +00:00
if (num > 1E-05f)
{
result = true;
}
else
{
result = (num > 1E-05f);
}
}
return result;
}
[Client]
private void SendTransform()
{
2020-12-04 09:23:27 +00:00
if (HasMoved() && QSBClientScene.readyConnection != null)
2020-12-03 13:18:45 +00:00
{
2020-12-04 09:23:27 +00:00
m_LocalTransformWriter.StartMessage(6);
m_LocalTransformWriter.Write(NetId);
SerializeModeTransform(m_LocalTransformWriter);
m_PrevPosition = transform.position;
m_PrevRotation = transform.rotation;
m_LocalTransformWriter.FinishMessage();
QSBClientScene.readyConnection.SendWriter(m_LocalTransformWriter, GetNetworkChannel());
2020-12-03 13:18:45 +00:00
}
}
public static void HandleTransform(QSBNetworkMessage netMsg)
{
2020-12-04 09:23:27 +00:00
var networkInstanceId = netMsg.Reader.ReadNetworkId();
var gameObject = QSBNetworkServer.FindLocalObject(networkInstanceId);
2020-12-03 13:18:45 +00:00
if (gameObject == null)
{
2020-12-04 22:14:53 +00:00
ModConsole.OwmlConsole.WriteLine("Warning - Received NetworkTransform data for GameObject that doesn't exist");
2020-12-03 13:18:45 +00:00
}
else
{
2020-12-04 09:23:27 +00:00
var component = gameObject.GetComponent<QSBNetworkTransform>();
2020-12-03 13:18:45 +00:00
if (component == null)
{
2020-12-04 22:14:53 +00:00
ModConsole.OwmlConsole.WriteLine("Warning - HandleTransform null target");
2020-12-03 13:18:45 +00:00
}
else if (!component.LocalPlayerAuthority)
{
2020-12-04 22:14:53 +00:00
ModConsole.OwmlConsole.WriteLine("Warning - HandleTransform no localPlayerAuthority");
2020-12-03 13:18:45 +00:00
}
else if (netMsg.Connection.ClientOwnedObjects == null)
{
2020-12-04 22:14:53 +00:00
ModConsole.OwmlConsole.WriteLine("Warning - HandleTransform object not owned by connection");
2020-12-03 13:18:45 +00:00
}
else if (netMsg.Connection.ClientOwnedObjects.Contains(networkInstanceId))
{
2020-12-04 09:23:27 +00:00
component.UnserializeModeTransform(netMsg.Reader, false);
component.LastSyncTime = Time.time;
2020-12-03 13:18:45 +00:00
}
2020-12-16 09:07:40 +00:00
else if (LogFilter.logWarn)
{
ModConsole.OwmlConsole.WriteLine("Warning - HandleTransform netId:" + networkInstanceId + " is not for a valid player");
}
2020-12-03 13:18:45 +00:00
}
}
2020-12-04 09:23:27 +00:00
private static void WriteAngle(QSBNetworkWriter writer, float angle, CompressionSyncMode compression)
2020-12-03 13:18:45 +00:00
{
if (compression != CompressionSyncMode.None)
{
if (compression != CompressionSyncMode.Low)
{
if (compression == CompressionSyncMode.High)
{
writer.Write((short)angle);
}
}
else
{
writer.Write((short)angle);
}
}
else
{
writer.Write(angle);
}
}
2020-12-04 09:23:27 +00:00
private static float ReadAngle(QSBNetworkReader reader, CompressionSyncMode compression)
2020-12-03 13:18:45 +00:00
{
float result;
if (compression != CompressionSyncMode.None)
{
if (compression != CompressionSyncMode.Low)
{
if (compression != CompressionSyncMode.High)
{
result = 0f;
}
else
{
2020-12-16 09:07:40 +00:00
result = (float)reader.ReadInt16();
2020-12-03 13:18:45 +00:00
}
}
else
{
2020-12-16 09:07:40 +00:00
result = (float)reader.ReadInt16();
2020-12-03 13:18:45 +00:00
}
}
else
{
result = reader.ReadSingle();
}
return result;
}
2020-12-16 09:07:40 +00:00
public static void SerializeVelocity3D(QSBNetworkWriter writer, Vector3 velocity, CompressionSyncMode compression)
{
2020-12-03 13:18:45 +00:00
writer.Write(velocity);
2020-12-16 09:07:40 +00:00
}
2020-12-03 13:18:45 +00:00
2020-12-04 09:23:27 +00:00
public static void SerializeRotation3D(QSBNetworkWriter writer, Quaternion rot, AxisSyncMode mode, CompressionSyncMode compression)
2020-12-03 13:18:45 +00:00
{
switch (mode)
{
case AxisSyncMode.AxisX:
WriteAngle(writer, rot.eulerAngles.x, compression);
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisY:
WriteAngle(writer, rot.eulerAngles.y, compression);
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisZ:
WriteAngle(writer, rot.eulerAngles.z, compression);
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisXY:
WriteAngle(writer, rot.eulerAngles.x, compression);
WriteAngle(writer, rot.eulerAngles.y, compression);
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisXZ:
WriteAngle(writer, rot.eulerAngles.x, compression);
WriteAngle(writer, rot.eulerAngles.z, compression);
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisYZ:
WriteAngle(writer, rot.eulerAngles.y, compression);
WriteAngle(writer, rot.eulerAngles.z, compression);
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisXYZ:
WriteAngle(writer, rot.eulerAngles.x, compression);
WriteAngle(writer, rot.eulerAngles.y, compression);
WriteAngle(writer, rot.eulerAngles.z, compression);
break;
}
}
2020-12-04 09:23:27 +00:00
public static void SerializeSpin3D(QSBNetworkWriter writer, Vector3 angularVelocity, AxisSyncMode mode, CompressionSyncMode compression)
2020-12-03 13:18:45 +00:00
{
switch (mode)
{
case AxisSyncMode.AxisX:
WriteAngle(writer, angularVelocity.x, compression);
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisY:
WriteAngle(writer, angularVelocity.y, compression);
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisZ:
WriteAngle(writer, angularVelocity.z, compression);
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisXY:
WriteAngle(writer, angularVelocity.x, compression);
WriteAngle(writer, angularVelocity.y, compression);
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisXZ:
WriteAngle(writer, angularVelocity.x, compression);
WriteAngle(writer, angularVelocity.z, compression);
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisYZ:
WriteAngle(writer, angularVelocity.y, compression);
WriteAngle(writer, angularVelocity.z, compression);
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisXYZ:
WriteAngle(writer, angularVelocity.x, compression);
WriteAngle(writer, angularVelocity.y, compression);
WriteAngle(writer, angularVelocity.z, compression);
break;
}
}
2020-12-16 09:07:40 +00:00
public static Vector3 UnserializeVelocity3D(QSBNetworkReader reader, CompressionSyncMode compression)
{
return reader.ReadVector3();
}
2020-12-03 13:18:45 +00:00
2020-12-04 09:23:27 +00:00
public static Quaternion UnserializeRotation3D(QSBNetworkReader reader, AxisSyncMode mode, CompressionSyncMode compression)
2020-12-03 13:18:45 +00:00
{
2020-12-04 09:23:27 +00:00
var identity = Quaternion.identity;
var zero = Vector3.zero;
2020-12-03 13:18:45 +00:00
switch (mode)
{
case AxisSyncMode.AxisX:
zero.Set(ReadAngle(reader, compression), 0f, 0f);
identity.eulerAngles = zero;
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisY:
zero.Set(0f, ReadAngle(reader, compression), 0f);
identity.eulerAngles = zero;
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisZ:
zero.Set(0f, 0f, ReadAngle(reader, compression));
identity.eulerAngles = zero;
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisXY:
zero.Set(ReadAngle(reader, compression), ReadAngle(reader, compression), 0f);
identity.eulerAngles = zero;
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisXZ:
zero.Set(ReadAngle(reader, compression), 0f, ReadAngle(reader, compression));
identity.eulerAngles = zero;
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisYZ:
zero.Set(0f, ReadAngle(reader, compression), ReadAngle(reader, compression));
identity.eulerAngles = zero;
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisXYZ:
zero.Set(ReadAngle(reader, compression), ReadAngle(reader, compression), ReadAngle(reader, compression));
identity.eulerAngles = zero;
break;
}
return identity;
}
2020-12-04 09:23:27 +00:00
public static Vector3 UnserializeSpin3D(QSBNetworkReader reader, AxisSyncMode mode, CompressionSyncMode compression)
2020-12-03 13:18:45 +00:00
{
2020-12-04 09:23:27 +00:00
var zero = Vector3.zero;
2020-12-03 13:18:45 +00:00
switch (mode)
{
case AxisSyncMode.AxisX:
zero.Set(ReadAngle(reader, compression), 0f, 0f);
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisY:
zero.Set(0f, ReadAngle(reader, compression), 0f);
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisZ:
zero.Set(0f, 0f, ReadAngle(reader, compression));
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisXY:
zero.Set(ReadAngle(reader, compression), ReadAngle(reader, compression), 0f);
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisXZ:
zero.Set(ReadAngle(reader, compression), 0f, ReadAngle(reader, compression));
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisYZ:
zero.Set(0f, ReadAngle(reader, compression), ReadAngle(reader, compression));
break;
2020-12-04 09:29:23 +00:00
2020-12-03 13:18:45 +00:00
case AxisSyncMode.AxisXYZ:
zero.Set(ReadAngle(reader, compression), ReadAngle(reader, compression), ReadAngle(reader, compression));
break;
}
return zero;
}
2020-12-16 09:07:40 +00:00
public override int GetNetworkChannel()
{
return 1;
}
2020-12-03 13:18:45 +00:00
2020-12-16 09:07:40 +00:00
public override float GetNetworkSendInterval()
{
return SendInterval;
}
2020-12-03 13:18:45 +00:00
2020-12-16 09:07:40 +00:00
public override void OnStartAuthority()
{
LastSyncTime = 0f;
}
2020-12-03 13:18:45 +00:00
private Vector3 m_TargetSyncPosition;
private Vector3 m_TargetSyncVelocity;
private Vector3 m_FixedPosDiff;
private Quaternion m_TargetSyncRotation3D;
private Vector3 m_TargetSyncAngularVelocity3D;
private float m_LastClientSendTime;
private Vector3 m_PrevPosition;
private Quaternion m_PrevRotation;
private const float k_LocalMovementThreshold = 1E-05f;
private const float k_LocalRotationThreshold = 1E-05f;
private const float k_LocalVelocityThreshold = 1E-05f;
private const float k_MoveAheadRatio = 0.1f;
2020-12-04 09:23:27 +00:00
private QSBNetworkWriter m_LocalTransformWriter;
2020-12-03 13:18:45 +00:00
public enum AxisSyncMode
{
None,
AxisX,
AxisY,
AxisZ,
AxisXY,
AxisXZ,
AxisYZ,
AxisXYZ
}
public enum CompressionSyncMode
{
None,
Low,
High
}
public delegate bool ClientMoveCallback3D(ref Vector3 position, ref Vector3 velocity, ref Quaternion rotation);
}
2020-12-04 09:29:23 +00:00
}