339 lines
8.0 KiB
C#
Raw Normal View History

2022-01-16 06:53:45 -08:00
using Mirror;
using OWML.Common;
using QSB.Player;
using QSB.Utility;
2021-07-17 09:51:47 +01:00
using QSB.WorldSync;
2021-08-14 14:45:52 +01:00
using System;
using System.Linq;
using UnityEngine;
namespace QSB.Syncs
{
2022-01-14 22:39:41 -08:00
/*
2022-01-21 17:44:12 -08:00
* Rewrite number : 11
2022-01-14 22:39:41 -08:00
* God has cursed me for my hubris, and my work is never finished.
*/
public abstract class SyncBase : QSBNetworkTransform
2022-01-14 20:59:42 -08:00
{
/// <summary>
2022-01-25 21:17:05 -08:00
/// valid if IsPlayerObject, otherwise null
2022-01-14 20:59:42 -08:00
/// </summary>
2022-01-16 08:15:50 -08:00
public PlayerInfo Player
{
get
{
if (_player == null)
{
DebugLog.ToConsole($"Error - trying to get SyncBase.Player for {netId} before Start has been called! "
2022-01-16 08:15:50 -08:00
+ "this really should not be happening!\n"
2022-01-20 22:36:23 -08:00
+ Environment.StackTrace,
2022-01-18 01:46:41 -08:00
MessageType.Error);
2022-01-16 08:15:50 -08:00
}
return _player;
}
}
private PlayerInfo _player;
2022-01-14 20:59:42 -08:00
private bool IsInitialized;
protected virtual bool CheckReady()
2022-01-14 20:59:42 -08:00
{
if (netId is uint.MaxValue or 0)
2022-01-14 20:59:42 -08:00
{
return false;
}
if (!QSBWorldSync.AllObjectsAdded)
2022-01-14 20:59:42 -08:00
{
return false;
}
2022-01-14 20:59:42 -08:00
if (IsPlayerObject)
{
if (_player == null)
2022-01-14 20:59:42 -08:00
{
return false;
}
if (!isLocalPlayer && !_player.IsReady)
2022-01-14 20:59:42 -08:00
{
return false;
}
}
return true;
2022-01-14 20:59:42 -08:00
}
/// <summary>
/// can be true with null reference transform. <br/>
/// can be true with inactive attached object.
/// </summary>
public bool IsValid { get; private set; }
protected virtual bool CheckValid()
{
if (!IsInitialized)
{
return false;
}
if (!AttachedTransform)
{
2022-01-23 00:31:15 -08:00
DebugLog.ToConsole($"Error - AttachedObject {this} is null!", MessageType.Error);
return false;
}
2022-01-14 20:59:42 -08:00
2022-01-21 20:58:12 -08:00
if (!AllowInactiveAttachedObject && !AttachedTransform.gameObject.activeInHierarchy)
{
return false;
2022-01-14 20:59:42 -08:00
}
if (!AllowNullReferenceTransform && !ReferenceTransform)
{
2022-01-23 00:31:15 -08:00
DebugLog.ToConsole($"Warning - {this}'s ReferenceTransform is null.", MessageType.Warning);
return false;
}
if (ReferenceTransform == Locator.GetRootTransform())
{
return false;
}
return true;
2022-01-14 20:59:42 -08:00
}
2022-01-16 06:11:44 -08:00
protected abstract bool UseInterpolation { get; }
2022-01-21 20:58:12 -08:00
protected virtual bool AllowInactiveAttachedObject => false;
2022-01-16 06:11:44 -08:00
protected abstract bool AllowNullReferenceTransform { get; }
2022-01-16 06:53:45 -08:00
protected virtual bool IsPlayerObject => false;
protected virtual bool OnlyApplyOnDeserialize => false;
2022-01-14 20:59:42 -08:00
2022-01-16 05:38:06 -08:00
public Transform AttachedTransform { get; private set; }
public Transform ReferenceTransform { get; private set; }
2022-01-14 20:59:42 -08:00
2022-01-21 18:00:02 -08:00
public string Name => AttachedTransform ? AttachedTransform.name : "<NullObject!>";
2022-01-23 00:29:59 -08:00
public override string ToString() => (IsPlayerObject ? $"{Player.PlayerId}." : string.Empty)
2022-01-21 18:00:02 -08:00
+ $"{netId}:{GetType().Name} ({Name})";
2022-01-16 08:04:15 -08:00
protected virtual float DistanceLeeway => 5f;
protected virtual float AngleLeeway => 5f;
private float _prevDistance;
private float _prevAngle;
2022-01-14 20:59:42 -08:00
protected const float SmoothTime = 0.1f;
private Vector3 _positionSmoothVelocity;
private Quaternion _rotationSmoothVelocity;
2022-01-21 16:26:21 -08:00
protected Vector3 SmoothPosition { get; private set; }
protected Quaternion SmoothRotation { get; private set; }
2022-01-14 20:59:42 -08:00
2022-01-16 04:34:52 -08:00
protected abstract Transform InitAttachedTransform();
2022-01-16 06:53:45 -08:00
protected abstract void GetFromAttached();
protected abstract void ApplyToAttached();
2022-01-14 20:59:42 -08:00
2022-01-18 12:19:58 -08:00
public override void OnStartClient()
2022-01-14 20:59:42 -08:00
{
if (IsPlayerObject)
{
// get player objects spawned before this object (or is this one)
// and use the closest one
2022-01-21 16:26:21 -08:00
_player = QSBPlayerManager.PlayerList
2022-01-14 20:59:42 -08:00
.Where(x => x.PlayerId <= netId)
.MaxBy(x => x.PlayerId);
2022-01-14 20:59:42 -08:00
}
DontDestroyOnLoad(gameObject);
QSBSceneManager.OnSceneLoaded += OnSceneLoaded;
}
2022-01-18 15:06:45 -08:00
public override void OnStopClient()
2022-01-14 20:59:42 -08:00
{
2022-01-21 23:23:13 -08:00
QSBSceneManager.OnSceneLoaded -= OnSceneLoaded;
2022-01-21 16:26:21 -08:00
if (IsInitialized)
2022-01-14 20:59:42 -08:00
{
SafeUninit();
2022-01-14 20:59:42 -08:00
}
}
2022-01-21 16:26:21 -08:00
private void OnSceneLoaded(OWScene oldScene, OWScene newScene, bool isInUniverse)
2022-01-14 20:59:42 -08:00
{
2022-01-21 16:26:21 -08:00
if (IsInitialized)
2022-01-14 20:59:42 -08:00
{
SafeUninit();
2022-01-14 20:59:42 -08:00
}
2022-01-21 16:26:21 -08:00
}
2022-01-14 20:59:42 -08:00
private const float _pauseTimerDelay = 1;
private float _pauseTimer;
private void SafeInit()
{
this.Try("initializing", () =>
{
Init();
IsInitialized = true;
});
if (!IsInitialized)
{
_pauseTimer = _pauseTimerDelay;
}
}
2022-01-14 20:59:42 -08:00
private void SafeUninit()
{
this.Try("uninitializing", () =>
{
Uninit();
IsInitialized = false;
IsValid = false;
});
if (IsInitialized)
{
_pauseTimer = _pauseTimerDelay;
}
}
protected virtual void Init() =>
AttachedTransform = InitAttachedTransform();
2022-01-21 16:26:21 -08:00
protected virtual void Uninit()
{
if (IsPlayerObject && !hasAuthority && AttachedTransform)
2022-01-14 20:59:42 -08:00
{
2022-01-16 04:34:52 -08:00
Destroy(AttachedTransform.gameObject);
2022-01-14 20:59:42 -08:00
}
}
2022-01-16 06:53:45 -08:00
private bool _shouldApply;
2022-01-16 08:15:50 -08:00
protected override void Deserialize(NetworkReader reader)
2022-01-16 06:53:45 -08:00
{
base.Deserialize(reader);
2022-01-16 06:53:45 -08:00
if (OnlyApplyOnDeserialize)
{
_shouldApply = true;
}
}
2022-01-16 06:11:44 -08:00
protected sealed override void Update()
2022-01-14 20:59:42 -08:00
{
if (_pauseTimer > 0)
{
_pauseTimer = Mathf.Max(0, _pauseTimer - Time.unscaledDeltaTime);
return;
}
if (!IsInitialized && CheckReady())
2022-01-14 20:59:42 -08:00
{
SafeInit();
2022-01-14 20:59:42 -08:00
}
else if (IsInitialized && !CheckReady())
2022-01-14 20:59:42 -08:00
{
SafeUninit();
2022-01-14 20:59:42 -08:00
return;
}
IsValid = CheckValid();
if (!IsValid)
2022-01-14 20:59:42 -08:00
{
2022-01-16 04:34:52 -08:00
return;
2022-01-14 20:59:42 -08:00
}
2022-01-21 16:52:30 -08:00
if (ReferenceTransform && ReferenceTransform.position == Vector3.zero)
2022-01-14 20:59:42 -08:00
{
2022-01-23 00:31:15 -08:00
DebugLog.ToConsole($"Warning - {this}'s ReferenceTransform is at (0,0,0). ReferenceTransform:{ReferenceTransform.name}", MessageType.Warning);
2022-01-14 20:59:42 -08:00
}
2022-01-16 06:53:45 -08:00
if (hasAuthority)
{
GetFromAttached();
base.Update();
2022-01-16 06:53:45 -08:00
}
2022-01-16 08:15:50 -08:00
else if (!OnlyApplyOnDeserialize || _shouldApply)
2022-01-16 06:53:45 -08:00
{
Interpolate();
2022-01-16 08:15:50 -08:00
_shouldApply = false;
ApplyToAttached();
2022-01-16 06:53:45 -08:00
}
2022-01-14 20:59:42 -08:00
}
private void Interpolate()
2022-01-16 08:04:15 -08:00
{
var distance = Vector3.Distance(SmoothPosition, transform.position);
SmoothPosition = Mathf.Abs(distance - _prevDistance) > DistanceLeeway ?
transform.position :
Vector3.SmoothDamp(SmoothPosition, transform.position, ref _positionSmoothVelocity, SmoothTime);
_prevDistance = distance;
var angle = Quaternion.Angle(SmoothRotation, transform.rotation);
SmoothRotation = Mathf.Abs(angle - _prevAngle) > AngleLeeway ?
transform.rotation :
QuaternionHelper.SmoothDamp(SmoothRotation, transform.rotation, ref _rotationSmoothVelocity, SmoothTime);
_prevAngle = angle;
2022-01-16 08:04:15 -08:00
}
public virtual void SetReferenceTransform(Transform referenceTransform)
2022-01-14 20:59:42 -08:00
{
if (ReferenceTransform == referenceTransform)
{
return;
}
ReferenceTransform = referenceTransform;
2022-01-21 18:58:14 -08:00
if (!hasAuthority && UseInterpolation)
2022-01-14 20:59:42 -08:00
{
2022-01-21 18:58:14 -08:00
if (IsPlayerObject)
{
2022-02-12 20:16:37 -08:00
AttachedTransform.parent = ReferenceTransform;
AttachedTransform.localScale = Vector3.one;
2022-01-21 18:58:14 -08:00
SmoothPosition = AttachedTransform.localPosition;
SmoothRotation = AttachedTransform.localRotation;
}
else
{
SmoothPosition = ReferenceTransform.ToRelPos(AttachedTransform.position);
SmoothRotation = ReferenceTransform.ToRelRot(AttachedTransform.rotation);
}
2022-01-14 20:59:42 -08:00
}
}
protected virtual void OnRenderObject()
{
2022-01-20 22:33:03 +00:00
if (!QSBCore.DebugSettings.DrawLines
|| !IsValid
2022-01-27 02:15:42 -08:00
|| !ReferenceTransform)
2022-01-14 20:59:42 -08:00
{
return;
}
/* Red Cube = Where visible object should be
* Green cube = Where visible object is
* Magenta cube = Reference transform
* Red Line = Connection between Red Cube and Green Cube
* Cyan Line = Connection between Green cube and reference transform
*/
Popcron.Gizmos.Cube(ReferenceTransform.FromRelPos(transform.position), ReferenceTransform.FromRelRot(transform.rotation), Vector3.one / 8, Color.red);
Popcron.Gizmos.Line(ReferenceTransform.FromRelPos(transform.position), AttachedTransform.transform.position, Color.red);
Popcron.Gizmos.Cube(AttachedTransform.transform.position, AttachedTransform.transform.rotation, Vector3.one / 6, Color.green);
Popcron.Gizmos.Cube(ReferenceTransform.position, ReferenceTransform.rotation, Vector3.one / 8, Color.magenta);
Popcron.Gizmos.Line(AttachedTransform.transform.position, ReferenceTransform.position, Color.cyan);
}
private void OnGUI()
{
2022-02-02 22:00:49 -08:00
if (!QSBCore.DebugSettings.DrawLabels
|| Event.current.type != EventType.Repaint
|| !IsValid
2022-01-27 02:15:42 -08:00
|| !ReferenceTransform)
2022-01-14 20:59:42 -08:00
{
return;
}
2022-01-23 00:29:59 -08:00
DebugGUI.DrawLabel(AttachedTransform.transform, ToString());
2022-01-14 20:59:42 -08:00
}
}
}