diff --git a/QSB/OrbSync/Events/OrbUserEvent.cs b/QSB/OrbSync/Events/OrbUserEvent.cs
index 540f8372..f9d98a54 100644
--- a/QSB/OrbSync/Events/OrbUserEvent.cs
+++ b/QSB/OrbSync/Events/OrbUserEvent.cs
@@ -78,6 +78,7 @@ namespace QSB.OrbSync.Events
DebugLog.ToConsole($"Error - Orb identity is null. (ID {message.ObjectId})", MessageType.Error);
return;
}
+ DebugLog.DebugWrite($"Orb {message.ObjectId} to owner {message.FromId}");
if (orbIdentity.ClientAuthorityOwner != null && orbIdentity.ClientAuthorityOwner != fromPlayer)
{
orbIdentity.RemoveClientAuthority(orbIdentity.ClientAuthorityOwner);
@@ -103,6 +104,7 @@ namespace QSB.OrbSync.Events
DebugLog.ToConsole($"Error - No NomaiOrbTransformSync has AttachedOrb with objectId {message.ObjectId}!");
return;
}
+ DebugLog.DebugWrite($"Orb {message.ObjectId} to owner {message.FromId}");
var orb = QSBWorldSync.OrbSyncList
.First(x => x.AttachedOrb == QSBWorldSync.OldOrbList[message.ObjectId]);
orb.enabled = true;
diff --git a/QSB/OrbSync/TransformSync/NomaiOrbTransformSync.cs b/QSB/OrbSync/TransformSync/NomaiOrbTransformSync.cs
index fce6c87d..50cd1964 100644
--- a/QSB/OrbSync/TransformSync/NomaiOrbTransformSync.cs
+++ b/QSB/OrbSync/TransformSync/NomaiOrbTransformSync.cs
@@ -43,7 +43,6 @@ namespace QSB.OrbSync.TransformSync
protected void Init()
{
- DebugLog.DebugWrite($"Init");
OrbTransform = AttachedOrb.transform;
_orbParent = AttachedOrb.GetAttachedOWRigidbody().GetOrigParent();
_isInitialized = true;
@@ -82,5 +81,16 @@ namespace QSB.OrbSync.TransformSync
OrbTransform.rotation = transform.rotation;
}
}
+
+ private void OnRenderObject()
+ {
+ if (!QSBCore.HasWokenUp || !QSBCore.DebugMode || !QSBCore.ShowLinesInDebug)
+ {
+ return;
+ }
+
+ Popcron.Gizmos.Cube(OrbTransform.position, OrbTransform.rotation, Vector3.one / 2, Color.blue);
+ Popcron.Gizmos.Cube(_orbParent.TransformPoint(transform.position), transform.rotation, Vector3.one / 2, Color.red);
+ }
}
}
\ No newline at end of file
diff --git a/QSB/Player/TransformSync/PlayerCameraSync.cs b/QSB/Player/TransformSync/PlayerCameraSync.cs
index 99cfdaf3..820b316f 100644
--- a/QSB/Player/TransformSync/PlayerCameraSync.cs
+++ b/QSB/Player/TransformSync/PlayerCameraSync.cs
@@ -6,7 +6,7 @@ using UnityEngine;
namespace QSB.Player.TransformSync
{
- public class PlayerCameraSync : QSBNetworkTransform
+ public class PlayerCameraSync : SectoredTransformSync
{
protected override GameObject InitLocalTransform()
{
diff --git a/QSB/Player/TransformSync/PlayerTransformSync.cs b/QSB/Player/TransformSync/PlayerTransformSync.cs
index f3ea3ab7..8c38bbec 100644
--- a/QSB/Player/TransformSync/PlayerTransformSync.cs
+++ b/QSB/Player/TransformSync/PlayerTransformSync.cs
@@ -5,7 +5,7 @@ using UnityEngine;
namespace QSB.Player.TransformSync
{
- public class PlayerTransformSync : QSBNetworkTransform
+ public class PlayerTransformSync : SectoredTransformSync
{
public static PlayerTransformSync LocalInstance { get; private set; }
diff --git a/QSB/ProbeSync/TransformSync/PlayerProbeSync.cs b/QSB/ProbeSync/TransformSync/PlayerProbeSync.cs
index 281c4d02..4bcfa82d 100644
--- a/QSB/ProbeSync/TransformSync/PlayerProbeSync.cs
+++ b/QSB/ProbeSync/TransformSync/PlayerProbeSync.cs
@@ -7,14 +7,17 @@ using UnityEngine;
namespace QSB.ProbeSync.TransformSync
{
- public class PlayerProbeSync : QSBNetworkTransform
+ public class PlayerProbeSync : SectoredTransformSync
{
public static PlayerProbeSync LocalInstance { get; private set; }
protected override float DistanceLeeway => 10f;
public override void OnStartAuthority()
- => LocalInstance = this;
+ {
+ DebugLog.DebugWrite($"OnStartAuthority probe");
+ LocalInstance = this;
+ }
private Transform GetProbe() =>
Locator.GetProbe().transform.Find("CameraPivot").Find("Geometry");
diff --git a/QSB/QSB.csproj b/QSB/QSB.csproj
index 09b91421..9e66b02b 100644
--- a/QSB/QSB.csproj
+++ b/QSB/QSB.csproj
@@ -237,9 +237,11 @@
+
+
diff --git a/QSB/QSBCore.cs b/QSB/QSBCore.cs
index 1ea1a765..a3aaeb85 100644
--- a/QSB/QSBCore.cs
+++ b/QSB/QSBCore.cs
@@ -149,9 +149,13 @@ namespace QSB
}
var offset3 = 10f;
- GUI.Label(new Rect(420, offset3, 400f, 20f), $"Current sector : {PlayerTransformSync.LocalInstance.ReferenceSector.Name}");
+ var playerSector = PlayerTransformSync.LocalInstance.ReferenceSector;
+ var playerText = playerSector == null ? "NULL" : playerSector.Name;
+ GUI.Label(new Rect(420, offset3, 400f, 20f), $"Current sector : {playerText}");
offset3 += _debugLineSpacing;
- GUI.Label(new Rect(420, offset3, 400f, 20f), $"Probe sector : {PlayerProbeSync.LocalInstance.ReferenceSector.Name}");
+ var probeSector = PlayerProbeSync.LocalInstance.ReferenceSector;
+ var probeText = probeSector == null ? "NULL" : probeSector.Name;
+ GUI.Label(new Rect(420, offset3, 400f, 20f), $"Probe sector : {probeText}");
offset3 += _debugLineSpacing;
var offset2 = 10f;
diff --git a/QSB/RoastingSync/TransformSync/RoastingStickTransformSync.cs b/QSB/RoastingSync/TransformSync/RoastingStickTransformSync.cs
index 2b1d9957..0c755538 100644
--- a/QSB/RoastingSync/TransformSync/RoastingStickTransformSync.cs
+++ b/QSB/RoastingSync/TransformSync/RoastingStickTransformSync.cs
@@ -7,7 +7,7 @@ using UnityEngine;
namespace QSB.RoastingSync.TransformSync
{
- internal class RoastingStickTransformSync : QSBNetworkTransform
+ internal class RoastingStickTransformSync : SectoredTransformSync
{
private Transform _stickTip;
private Transform _networkStickTip => gameObject.transform.GetChild(0);
diff --git a/QSB/SectorSync/QSBSectorManager.cs b/QSB/SectorSync/QSBSectorManager.cs
index 2c57866b..d85851bb 100644
--- a/QSB/SectorSync/QSBSectorManager.cs
+++ b/QSB/SectorSync/QSBSectorManager.cs
@@ -20,7 +20,7 @@ namespace QSB.SectorSync
public void Invoke()
{
- foreach (var sync in QSBNetworkTransform.NetworkTransformList)
+ foreach (var sync in SectoredTransformSync.SectoredNetworkTransformList)
{
if (sync.AttachedObject == null)
{
@@ -64,7 +64,7 @@ namespace QSB.SectorSync
IsReady = QSBWorldSync.GetWorldObjects().Any();
}
- private void CheckTransformSyncSector(QSBNetworkTransform transformSync)
+ private void CheckTransformSyncSector(SectoredTransformSync transformSync)
{
var attachedObject = transformSync.AttachedObject;
var closestSector = transformSync.SectorSync.GetClosestSector(attachedObject.transform);
diff --git a/QSB/ShipSync/TransformSync/ShipTransformSync.cs b/QSB/ShipSync/TransformSync/ShipTransformSync.cs
index 4494835a..f82e5c48 100644
--- a/QSB/ShipSync/TransformSync/ShipTransformSync.cs
+++ b/QSB/ShipSync/TransformSync/ShipTransformSync.cs
@@ -4,7 +4,7 @@ using UnityEngine;
namespace QSB.ShipSync.TransformSync
{
- public class ShipTransformSync : QSBNetworkTransform
+ public class ShipTransformSync : SectoredTransformSync
{
protected override float DistanceLeeway => 20f;
diff --git a/QSB/TransformSync/BaseTransformSync.cs b/QSB/TransformSync/BaseTransformSync.cs
new file mode 100644
index 00000000..ac5984c3
--- /dev/null
+++ b/QSB/TransformSync/BaseTransformSync.cs
@@ -0,0 +1,218 @@
+using OWML.Common;
+using QSB.Player;
+using QSB.Player.TransformSync;
+using QSB.Utility;
+using QuantumUNET.Components;
+using QuantumUNET.Transport;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using UnityEngine;
+
+namespace QSB.TransformSync
+{
+ public abstract class BaseTransformSync : QNetworkTransform
+ {
+ public uint AttachedNetId => NetIdentity?.NetId.Value ?? uint.MaxValue;
+ public uint PlayerId => NetIdentity.RootIdentity?.NetId.Value ?? NetIdentity.NetId.Value;
+ public PlayerInfo Player => QSBPlayerManager.GetPlayer(PlayerId);
+
+ public Transform ReferenceTransform { get; set; }
+ public GameObject AttachedObject { get; set; }
+
+ public abstract bool IsReady { get; }
+
+ protected abstract GameObject InitLocalTransform();
+ protected abstract GameObject InitRemoteTransform();
+
+ private bool _isInitialized;
+ private const float SmoothTime = 0.1f;
+ protected virtual float DistanceLeeway { get; } = 5f;
+ private float _previousDistance;
+ private Vector3 _positionSmoothVelocity;
+ private Quaternion _rotationSmoothVelocity;
+ protected IntermediaryTransform _intermediaryTransform;
+
+ public virtual void Start()
+ {
+ var lowestBound = Resources.FindObjectsOfTypeAll()
+ .Where(x => x.NetId.Value <= NetId.Value).OrderBy(x => x.NetId.Value).Last();
+ NetIdentity.SetRootIdentity(lowestBound.NetIdentity);
+
+ DontDestroyOnLoad(gameObject);
+ _intermediaryTransform = new IntermediaryTransform(transform);
+ QSBSceneManager.OnSceneLoaded += OnSceneLoaded;
+ }
+
+ protected virtual void OnDestroy()
+ {
+ if (!HasAuthority && AttachedObject != null)
+ {
+ Destroy(AttachedObject);
+ }
+ QSBSceneManager.OnSceneLoaded -= OnSceneLoaded;
+ }
+
+ private void OnSceneLoaded(OWScene scene, bool isInUniverse) =>
+ _isInitialized = false;
+
+ protected virtual void Init()
+ {
+ AttachedObject = HasAuthority ? InitLocalTransform() : InitRemoteTransform();
+ _isInitialized = true;
+ }
+
+ public override void SerializeTransform(QNetworkWriter writer)
+ {
+ if (_intermediaryTransform == null)
+ {
+ _intermediaryTransform = new IntermediaryTransform(transform);
+ }
+
+ var worldPos = _intermediaryTransform.GetPosition();
+ var worldRot = _intermediaryTransform.GetRotation();
+ writer.Write(worldPos);
+ SerializeRotation(writer, worldRot);
+ _prevPosition = worldPos;
+ _prevRotation = worldRot;
+ }
+
+ public override void DeserializeTransform(QNetworkReader reader)
+ {
+ if (!QSBCore.HasWokenUp)
+ {
+ reader.ReadVector3();
+ DeserializeRotation(reader);
+ return;
+ }
+
+ var pos = reader.ReadVector3();
+ var rot = DeserializeRotation(reader);
+
+ if (HasAuthority)
+ {
+ return;
+ }
+
+ _intermediaryTransform.SetPosition(pos);
+ _intermediaryTransform.SetRotation(rot);
+
+ if (_intermediaryTransform.GetPosition() == Vector3.zero)
+ {
+ DebugLog.ToConsole($"Warning - {PlayerId}.{GetType().Name} at (0,0,0)! - Given position was {pos}", MessageType.Warning);
+ }
+ }
+
+ public override void Update()
+ {
+ if (!_isInitialized && IsReady)
+ {
+ Init();
+ }
+ else if (_isInitialized && !IsReady)
+ {
+ _isInitialized = false;
+ return;
+ }
+
+ if (!_isInitialized)
+ {
+ return;
+ }
+
+ if (AttachedObject == null)
+ {
+ DebugLog.ToConsole($"Warning - AttachedObject {Player.PlayerId}.{GetType().Name} is null.", MessageType.Warning);
+ return;
+ }
+
+ UpdateTransform();
+
+ base.Update();
+ }
+
+ protected virtual void UpdateTransform()
+ {
+ if (HasAuthority)
+ {
+ _intermediaryTransform.EncodePosition(AttachedObject.transform.position);
+ _intermediaryTransform.EncodeRotation(AttachedObject.transform.rotation);
+ }
+ else
+ {
+ 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 = (_intermediaryTransform.GetPosition() - _prevPosition).magnitude;
+ return displacementMagnitude > 1E-03f
+ || Quaternion.Angle(_intermediaryTransform.GetRotation(), _prevRotation) > 1E-03f;
+ }
+
+ public void SetReferenceTransform(Transform transform)
+ {
+ if (ReferenceTransform == transform)
+ {
+ return;
+ }
+ ReferenceTransform = transform;
+ _intermediaryTransform.SetReferenceTransform(transform);
+ if (AttachedObject == null)
+ {
+ DebugLog.ToConsole($"Warning - AttachedObject was null for {PlayerId}.{GetType().Name} when trying to set reference transform to {transform.name}. Waiting until not null...", MessageType.Warning);
+ QSBCore.UnityEvents.RunWhen(
+ () => AttachedObject != null,
+ () => ReparentAttachedObject(transform));
+ return;
+ }
+ if (!HasAuthority)
+ {
+ ReparentAttachedObject(transform);
+ }
+ }
+
+ private void ReparentAttachedObject(Transform sectorTransform)
+ {
+ if (AttachedObject.transform.parent != null && AttachedObject.transform.parent.GetComponent() == null)
+ {
+ DebugLog.ToConsole($" - ERROR - Trying to reparent attachedObject which wasnt attached to sector!", MessageType.Error);
+ return;
+ }
+ AttachedObject.transform.SetParent(sectorTransform, true);
+ AttachedObject.transform.localScale = GetType() == typeof(PlayerTransformSync)
+ ? Vector3.one / 10
+ : Vector3.one;
+ }
+
+ private Vector3 SmartSmoothDamp(Vector3 currentPosition, Vector3 targetPosition)
+ {
+ var distance = Vector3.Distance(currentPosition, targetPosition);
+ if (distance > _previousDistance + DistanceLeeway)
+ {
+ _previousDistance = distance;
+ return targetPosition;
+ }
+ _previousDistance = distance;
+ return Vector3.SmoothDamp(currentPosition, targetPosition, ref _positionSmoothVelocity, SmoothTime);
+ }
+
+ private void OnRenderObject()
+ {
+ if (!QSBCore.HasWokenUp || !QSBCore.DebugMode || !QSBCore.ShowLinesInDebug || !IsReady)
+ {
+ return;
+ }
+
+ 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, ReferenceTransform.position, Color.cyan);
+ }
+ }
+}
diff --git a/QSB/TransformSync/IntermediaryTransform.cs b/QSB/TransformSync/IntermediaryTransform.cs
index 26249222..5b069c2a 100644
--- a/QSB/TransformSync/IntermediaryTransform.cs
+++ b/QSB/TransformSync/IntermediaryTransform.cs
@@ -3,10 +3,10 @@ using UnityEngine;
namespace QSB.TransformSync
{
- internal class IntermediaryTransform
+ public class IntermediaryTransform
{
private Transform _attachedTransform;
- private QSBSector _referenceSector;
+ private Transform _referenceTransform;
public IntermediaryTransform(Transform transform) => _attachedTransform = transform;
///
@@ -34,25 +34,25 @@ namespace QSB.TransformSync
=> _attachedTransform.rotation = worldRot;
///
- /// Sets the reference sector - what sector this transform is syncing to.
+ /// Sets the reference transform - what transform this transform is syncing to.
///
/// The new reference sector.
- public void SetReferenceSector(QSBSector sector)
- => _referenceSector = sector;
+ public void SetReferenceTransform(Transform transform)
+ => _referenceTransform = transform;
///
/// 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));
+ => SetPosition(_referenceTransform.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));
+ => SetRotation(_referenceTransform.InverseTransformRotation(worldRotation));
///
/// Gets what the VISIBLE transform's position should be, from the reference sector and the position of the INVISIBLE transform.
diff --git a/QSB/TransformSync/QSBNetworkTransform.cs b/QSB/TransformSync/QSBNetworkTransform.cs
index a81718a5..19f46894 100644
--- a/QSB/TransformSync/QSBNetworkTransform.cs
+++ b/QSB/TransformSync/QSBNetworkTransform.cs
@@ -12,6 +12,7 @@ using UnityEngine;
namespace QSB.TransformSync
{
+ /*
public abstract class QSBNetworkTransform : QNetworkTransform
{
public uint AttachedNetId => NetIdentity?.NetId.Value ?? uint.MaxValue;
@@ -246,4 +247,5 @@ namespace QSB.TransformSync
Popcron.Gizmos.Line(AttachedObject.transform.position, ReferenceSector.Transform.position, Color.cyan);
}
}
+ */
}
diff --git a/QSB/TransformSync/SectoredTransformSync.cs b/QSB/TransformSync/SectoredTransformSync.cs
new file mode 100644
index 00000000..a3b3daa8
--- /dev/null
+++ b/QSB/TransformSync/SectoredTransformSync.cs
@@ -0,0 +1,87 @@
+using QSB.SectorSync.WorldObjects;
+using QSB.Utility;
+using QSB.WorldSync;
+using QuantumUNET.Transport;
+using System.Collections.Generic;
+
+namespace QSB.TransformSync
+{
+ public abstract class SectoredTransformSync : BaseTransformSync
+ {
+ public QSBSector ReferenceSector { get; set; }
+ public SectorSync.SectorSync SectorSync { get; private set; }
+ public static List SectoredNetworkTransformList = new List();
+
+ public override void Start()
+ {
+ DebugLog.DebugWrite($"Start of {GetType().Name}");
+ SectorSync = gameObject.AddComponent();
+ SectoredNetworkTransformList.Add(this);
+ base.Start();
+ }
+
+ protected override void OnDestroy()
+ {
+ DebugLog.DebugWrite($"OnDestroy of {GetType().Name}");
+ base.OnDestroy();
+ SectoredNetworkTransformList.Remove(this);
+ if (SectorSync != null)
+ {
+ Destroy(SectorSync);
+ }
+ }
+
+ protected override void Init()
+ {
+ DebugLog.DebugWrite($"Init of {GetType().Name}");
+ base.Init();
+ SetReferenceTransform(SectorSync.GetClosestSector(AttachedObject.transform).Transform);
+ }
+
+ public override void SerializeTransform(QNetworkWriter writer)
+ {
+ if (_intermediaryTransform == null)
+ {
+ _intermediaryTransform = new IntermediaryTransform(transform);
+ }
+ if (ReferenceSector != null)
+ {
+ writer.Write(ReferenceSector.ObjectId);
+ }
+ else
+ {
+ writer.Write(-1);
+ }
+ base.SerializeTransform(writer);
+ }
+
+ public override void DeserializeTransform(QNetworkReader reader)
+ {
+ if (!QSBCore.HasWokenUp)
+ {
+ reader.ReadInt32();
+ reader.ReadVector3();
+ DeserializeRotation(reader);
+ return;
+ }
+
+ var sectorId = reader.ReadInt32();
+ var sector = sectorId == -1
+ ? null
+ : QSBWorldSync.GetWorldFromId(sectorId);
+
+ if (sector != ReferenceSector)
+ {
+ SetReferenceSector(sector);
+ }
+
+ base.DeserializeTransform(reader);
+ }
+
+ public void SetReferenceSector(QSBSector sector)
+ {
+ ReferenceSector = sector;
+ SetReferenceTransform(sector.Transform);
+ }
+ }
+}