2021-08-22 16:57:09 +01:00
using OWML.Common ;
2021-07-07 22:12:41 +01:00
using QSB.Player ;
using QSB.Utility ;
2021-07-17 09:51:47 +01:00
using QSB.WorldSync ;
2021-07-07 22:12:41 +01:00
using QuantumUNET.Components ;
2021-08-14 14:45:52 +01:00
using System ;
using System.Linq ;
2021-07-07 22:12:41 +01:00
using UnityEngine ;
namespace QSB.Syncs
{
2021-08-14 14:45:52 +01:00
/ *
* Rewrite number : 9
* God has cursed me for my hubris , and my work is never finished .
* /
2021-12-25 16:58:41 -08:00
public abstract class SyncBase < T > : QNetworkTransform where T : Component
2021-07-07 22:12:41 +01:00
{
2022-01-07 15:36:31 -08:00
/// <summary>
2022-01-07 15:38:22 -08:00
/// valid if IsPlayerObject, otherwise null
2022-01-07 15:36:31 -08:00
/// </summary>
2022-01-07 15:28:33 -08:00
public PlayerInfo Player { get ; private set ; }
2021-12-11 10:50:17 +00:00
2021-12-13 12:42:27 -08:00
private bool _baseIsReady
{
2021-12-11 10:50:17 +00:00
get
{
2022-01-07 15:08:20 -08:00
if ( NetId . Value is uint . MaxValue or 0 )
2021-12-11 10:50:17 +00:00
{
return false ;
}
if ( ! WorldObjectManager . AllObjectsAdded )
{
return false ;
}
if ( IsPlayerObject )
{
if ( ! Player . IsReady & & ! IsLocalPlayer )
{
return false ;
}
}
return true ;
}
}
2021-07-07 22:12:41 +01:00
public abstract bool IsReady { get ; }
public abstract bool UseInterpolation { get ; }
2021-07-11 16:18:47 +01:00
public abstract bool IgnoreDisabledAttachedObject { get ; }
public abstract bool IgnoreNullReferenceTransform { get ; }
2021-12-18 14:22:37 -08:00
public abstract bool DestroyAttachedObject { get ; }
2021-12-28 22:27:16 -08:00
public abstract bool IsPlayerObject { get ; }
2021-07-07 22:12:41 +01:00
2021-12-13 12:42:27 -08:00
public T AttachedObject { get ; set ; }
2021-07-07 22:12:41 +01:00
public Transform ReferenceTransform { get ; set ; }
2022-01-07 17:12:08 -08:00
public string LogName = > ( IsPlayerObject ? $"{Player.PlayerId}." : string . Empty ) + $"{NetId.Value}:{GetType().Name}" ;
2021-07-07 22:12:41 +01:00
protected virtual float DistanceLeeway { get ; } = 5f ;
private float _previousDistance ;
protected const float SmoothTime = 0.1f ;
2021-12-13 13:33:18 -08:00
private Vector3 _positionSmoothVelocity ;
private Quaternion _rotationSmoothVelocity ;
2021-07-07 22:12:41 +01:00
protected bool _isInitialized ;
2021-12-18 14:42:15 -08:00
protected Vector3 SmoothPosition ;
protected Quaternion SmoothRotation ;
2021-07-07 22:12:41 +01:00
2021-12-13 12:42:27 -08:00
protected abstract T SetAttachedObject ( ) ;
2021-07-11 16:18:47 +01:00
protected abstract bool UpdateTransform ( ) ;
2021-07-07 22:12:41 +01:00
2021-08-14 14:45:52 +01:00
public virtual void Start ( )
2021-07-07 22:12:41 +01:00
{
2021-12-10 22:13:39 +00:00
if ( IsPlayerObject )
{
2022-01-07 15:08:20 -08:00
// get player objects spawned before this object (or is this one)
// and use the closest one
Player = QSBPlayerManager . PlayerList
. Where ( x = > x . PlayerId < = NetId . Value )
. OrderBy ( x = > x . PlayerId ) . Last ( ) ;
2021-12-10 22:13:39 +00:00
}
2021-08-14 14:45:52 +01:00
DontDestroyOnLoad ( gameObject ) ;
QSBSceneManager . OnSceneLoaded + = OnSceneLoaded ;
}
protected virtual void OnDestroy ( )
{
2021-12-18 14:22:37 -08:00
if ( DestroyAttachedObject )
2021-08-14 14:45:52 +01:00
{
if ( ! HasAuthority & & AttachedObject ! = null )
{
Destroy ( AttachedObject . gameObject ) ;
}
}
QSBSceneManager . OnSceneLoaded - = OnSceneLoaded ;
}
protected virtual void Init ( )
{
if ( ! QSBSceneManager . IsInUniverse )
{
2021-11-10 21:51:14 -08:00
DebugLog . ToConsole ( $"Error - {LogName} is being init-ed when not in the universe!" , MessageType . Error ) ;
2021-08-14 14:45:52 +01:00
}
2021-12-18 14:22:37 -08:00
if ( DestroyAttachedObject )
2021-08-14 14:45:52 +01:00
{
if ( ! HasAuthority & & AttachedObject ! = null )
{
Destroy ( AttachedObject . gameObject ) ;
}
}
AttachedObject = SetAttachedObject ( ) ;
_isInitialized = true ;
}
2021-10-29 23:00:13 +01:00
protected virtual void OnSceneLoaded ( OWScene oldScene , OWScene newScene , bool isInUniverse ) = > _isInitialized = false ;
2021-07-07 22:12:41 +01:00
2021-07-07 23:04:00 +01:00
public override void Update ( )
{
2021-07-17 09:51:47 +01:00
if ( ! _isInitialized & & IsReady & & _baseIsReady )
2021-07-07 23:04:00 +01:00
{
2021-11-12 10:06:51 +00:00
try
{
Init ( ) ;
}
catch ( Exception ex )
{
DebugLog . ToConsole ( $"Exception when initializing {name} : {ex}" , MessageType . Error ) ;
enabled = false ;
}
2021-11-25 15:38:05 +00:00
2021-07-17 09:51:47 +01:00
base . Update ( ) ;
return ;
2021-07-07 23:04:00 +01:00
}
2021-07-17 09:51:47 +01:00
else if ( _isInitialized & & ( ! IsReady | | ! _baseIsReady ) )
2021-07-07 23:04:00 +01:00
{
_isInitialized = false ;
2021-07-11 16:18:47 +01:00
base . Update ( ) ;
2021-07-07 23:04:00 +01:00
return ;
}
if ( ! _isInitialized )
{
2021-07-11 16:18:47 +01:00
base . Update ( ) ;
2021-07-07 23:04:00 +01:00
return ;
}
if ( AttachedObject = = null )
{
2021-11-10 21:51:14 -08:00
DebugLog . ToConsole ( $"Warning - AttachedObject {LogName} is null." , MessageType . Warning ) ;
2021-07-07 23:04:00 +01:00
_isInitialized = false ;
2021-07-11 16:18:47 +01:00
base . Update ( ) ;
2021-07-07 23:04:00 +01:00
return ;
}
2022-01-12 23:08:07 +00:00
if ( ! AttachedObject . gameObject . activeInHierarchy & & ! IgnoreDisabledAttachedObject )
{
base . Update ( ) ;
return ;
}
else
2021-07-09 15:55:01 +01:00
{
2022-01-12 23:08:07 +00:00
if ( ReferenceTransform ! = null & & ReferenceTransform . position = = Vector3 . zero & & ReferenceTransform ! = Locator . GetRootTransform ( ) )
{
DebugLog . ToConsole ( $"Warning - {LogName}'s ReferenceTransform is at (0,0,0). ReferenceTransform:{ReferenceTransform.name}, AttachedObject:{AttachedObject.name}" , MessageType . Warning ) ;
}
2021-07-09 15:55:01 +01:00
}
2022-01-12 23:08:07 +00:00
if ( ReferenceTransform = = Locator . GetRootTransform ( ) )
2021-07-07 23:04:00 +01:00
{
2021-07-11 16:18:47 +01:00
base . Update ( ) ;
2021-07-07 23:04:00 +01:00
return ;
}
2021-07-11 16:18:47 +01:00
if ( ReferenceTransform = = null & & ! IgnoreNullReferenceTransform )
2021-07-07 23:04:00 +01:00
{
2021-11-10 21:51:14 -08:00
DebugLog . ToConsole ( $"Warning - {LogName}'s ReferenceTransform is null. AttachedObject:{AttachedObject.name}" , MessageType . Warning ) ;
2021-07-11 16:18:47 +01:00
base . Update ( ) ;
2021-07-07 23:04:00 +01:00
return ;
}
2021-12-18 14:42:15 -08:00
if ( ! HasAuthority & & UseInterpolation )
{
SmoothPosition = SmartSmoothDamp ( SmoothPosition , transform . position ) ;
SmoothRotation = SmartSmoothDamp ( SmoothRotation , transform . rotation ) ;
}
2021-09-13 19:21:40 +01:00
UpdateTransform ( ) ;
2021-07-09 15:55:01 +01:00
2021-07-07 23:04:00 +01:00
base . Update ( ) ;
}
2021-12-18 14:42:15 -08:00
private Vector3 SmartSmoothDamp ( Vector3 currentPosition , Vector3 targetPosition )
2021-08-14 14:45:52 +01:00
{
var distance = Vector3 . Distance ( currentPosition , targetPosition ) ;
if ( distance > _previousDistance + DistanceLeeway )
{
2021-08-19 16:32:18 +01:00
/ *
DebugLog . DebugWrite ( $"{_logName} moved too far!" +
$"\r\n CurrentPosition:{currentPosition}," +
$"\r\n TargetPosition:{targetPosition}" ) ;
* /
2021-08-14 14:45:52 +01:00
_previousDistance = distance ;
return targetPosition ;
}
_previousDistance = distance ;
return Vector3 . SmoothDamp ( currentPosition , targetPosition , ref _positionSmoothVelocity , SmoothTime ) ;
}
2021-12-18 14:42:15 -08:00
private Quaternion SmartSmoothDamp ( Quaternion currentRotation , Quaternion targetRotation )
2021-12-13 13:33:18 -08:00
{
return QuaternionHelper . SmoothDamp ( currentRotation , targetRotation , ref _rotationSmoothVelocity , SmoothTime ) ;
}
2021-11-19 00:28:36 -08:00
public void SetReferenceTransform ( Transform referenceTransform )
2021-12-18 14:42:15 -08:00
{
if ( ReferenceTransform = = referenceTransform )
{
return ;
}
ReferenceTransform = referenceTransform ;
if ( HasAuthority )
{
transform . position = ReferenceTransform . ToRelPos ( AttachedObject . transform . position ) ;
transform . rotation = ReferenceTransform . ToRelRot ( AttachedObject . transform . rotation ) ;
}
else if ( UseInterpolation )
{
2021-12-18 15:07:36 -08:00
SmoothPosition = ReferenceTransform . ToRelPos ( AttachedObject . transform . position ) ;
SmoothRotation = ReferenceTransform . ToRelRot ( AttachedObject . transform . rotation ) ;
2021-12-18 14:42:15 -08:00
}
}
2021-08-14 14:45:52 +01:00
2021-07-07 22:12:41 +01:00
protected virtual void OnRenderObject ( )
{
2021-12-28 21:25:25 -08:00
if ( ! QSBCore . ShowLinesInDebug
| | ! WorldObjectManager . AllObjectsReady
2021-07-07 22:12:41 +01:00
| | ! IsReady
2021-12-28 21:25:25 -08:00
| | AttachedObject = = null
2021-11-19 00:28:36 -08:00
| | ReferenceTransform = = null )
2021-07-07 22:12:41 +01:00
{
return ;
}
/ * Red Cube = Where visible object should be
2021-12-14 16:04:59 +00:00
* Green cube = Where visible object is
2021-07-09 15:55:01 +01:00
* Magenta cube = Reference transform
2021-12-13 16:05:34 +00:00
* Red Line = Connection between Red Cube and Green Cube
* Cyan Line = Connection between Green cube and reference transform
2021-07-07 22:12:41 +01:00
* /
2021-12-16 18:20:30 +00:00
Popcron . Gizmos . Cube ( ReferenceTransform . FromRelPos ( transform . position ) , ReferenceTransform . FromRelRot ( transform . rotation ) , Vector3 . one / 8 , Color . red ) ;
2021-12-13 16:02:31 -08:00
Popcron . Gizmos . Line ( ReferenceTransform . FromRelPos ( transform . position ) , AttachedObject . transform . position , Color . red ) ;
2021-12-13 16:05:34 +00:00
Popcron . Gizmos . Cube ( AttachedObject . transform . position , AttachedObject . transform . rotation , Vector3 . one / 6 , Color . green ) ;
Popcron . Gizmos . Cube ( ReferenceTransform . position , ReferenceTransform . rotation , Vector3 . one / 8 , Color . magenta ) ;
2021-07-07 22:12:41 +01:00
Popcron . Gizmos . Line ( AttachedObject . transform . position , ReferenceTransform . position , Color . cyan ) ;
}
2021-12-27 21:32:00 +00:00
2021-12-28 16:20:28 -08:00
private void OnGUI ( )
2021-12-27 21:32:00 +00:00
{
2021-12-28 22:24:52 -08:00
if ( ! QSBCore . ShowDebugLabels | |
Event . current . type ! = EventType . Repaint )
2021-12-28 21:25:25 -08:00
{
return ;
}
2021-12-28 18:06:34 +00:00
if ( AttachedObject ! = null )
2021-12-27 21:32:00 +00:00
{
2021-12-28 18:06:34 +00:00
DebugGUI . DrawLabel ( AttachedObject . transform , LogName ) ;
2021-12-27 21:32:00 +00:00
}
}
2021-07-07 22:12:41 +01:00
}
}