2022-01-16 06:53:45 -08:00
using Mirror ;
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-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
{
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-16 08:15:50 -08:00
/// valid if IsPlayerObject, otherwise null <br/>
2022-01-14 20:59:42 -08:00
/// </summary>
2022-01-16 08:15:50 -08:00
public PlayerInfo Player
{
get
{
if ( _player = = null )
{
2022-01-18 10:30:34 -08:00
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
2022-01-21 17:24:22 -08:00
private bool IsInitialized ;
2022-01-21 17:12:24 -08:00
protected virtual bool CheckReady ( )
2022-01-14 20:59:42 -08:00
{
2022-01-21 17:12:24 -08:00
if ( netId is uint . MaxValue or 0 )
2022-01-14 20:59:42 -08:00
{
2022-01-21 17:12:24 -08:00
return false ;
}
if ( ! QSBWorldSync . AllObjectsAdded )
{
return false ;
}
2022-01-14 20:59:42 -08:00
2022-01-21 17:12:24 -08:00
if ( IsPlayerObject )
{
if ( _player = = null )
2022-01-14 20:59:42 -08:00
{
return false ;
}
2022-01-21 17:12:24 -08:00
if ( ! isLocalPlayer & & ! _player . IsReady )
2022-01-14 20:59:42 -08:00
{
2022-01-21 17:12:24 -08:00
return false ;
2022-01-14 20:59:42 -08:00
}
}
2022-01-21 17:12:24 -08:00
return true ;
2022-01-14 20:59:42 -08:00
}
2022-01-21 17:24:22 -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 )
{
DebugLog . ToConsole ( $"Error - AttachedObject {LogName} is null!" , MessageType . Error ) ;
return false ;
}
if ( ! AllowDisabledAttachedObject & & ! AttachedTransform . gameObject . activeInHierarchy )
{
return false ;
}
if ( ! AllowNullReferenceTransform & & ! ReferenceTransform )
{
DebugLog . ToConsole ( $"Warning - {LogName}'s ReferenceTransform is null. AttachedObject:{AttachedTransform.name}" , MessageType . Warning ) ;
return false ;
}
if ( ReferenceTransform = = Locator . GetRootTransform ( ) )
{
return false ;
}
return true ;
}
2022-01-16 06:11:44 -08:00
protected abstract bool UseInterpolation { get ; }
2022-01-16 07:56:08 -08:00
protected virtual bool AllowDisabledAttachedObject = > 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!>" ;
public string LogName = > ( IsPlayerObject ? $"{Player.PlayerId}." : string . Empty )
+ $"{netId}:{GetType().Name} ({Name})" ;
2022-01-16 08:04:15 -08:00
protected virtual float DistanceLeeway = > 5f ;
private float _previousDistance ;
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 )
. OrderBy ( x = > x . PlayerId ) . Last ( ) ;
}
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 16:26:21 -08:00
if ( IsInitialized )
2022-01-14 20:59:42 -08:00
{
2022-01-21 16:26:21 -08:00
Uninit ( ) ;
2022-01-14 20:59:42 -08:00
}
QSBSceneManager . OnSceneLoaded - = OnSceneLoaded ;
}
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
{
2022-01-21 16:26:21 -08:00
Uninit ( ) ;
2022-01-14 20:59:42 -08:00
}
2022-01-21 16:26:21 -08:00
}
protected virtual void Init ( )
{
AttachedTransform = InitAttachedTransform ( ) ;
IsInitialized = true ;
}
2022-01-14 20:59:42 -08:00
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-21 17:51:26 -08:00
AttachedTransform = null ;
ReferenceTransform = null ;
2022-01-21 16:26:21 -08:00
IsInitialized = false ;
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
2022-01-16 07:23:35 -08:00
protected override void Deserialize ( NetworkReader reader , bool initialState )
2022-01-16 06:53:45 -08:00
{
2022-01-16 07:23:35 -08:00
base . Deserialize ( reader , initialState ) ;
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
{
2022-01-21 17:12:24 -08:00
if ( ! IsInitialized & & CheckReady ( ) )
2022-01-14 20:59:42 -08:00
{
2022-01-21 16:26:21 -08:00
Init ( ) ;
2022-01-14 20:59:42 -08:00
}
2022-01-21 17:12:24 -08:00
else if ( IsInitialized & & ! CheckReady ( ) )
2022-01-14 20:59:42 -08:00
{
2022-01-21 16:26:21 -08:00
Uninit ( ) ;
2022-01-21 17:24:22 -08:00
IsValid = false ;
2022-01-21 16:26:21 -08:00
base . Update ( ) ;
2022-01-14 20:59:42 -08:00
return ;
}
2022-01-21 17:24:22 -08:00
IsValid = CheckValid ( ) ;
if ( ! IsValid )
2022-01-14 20:59:42 -08:00
{
2022-01-21 16:26:21 -08:00
base . Update ( ) ;
2022-01-20 22:36:23 -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-20 22:36:23 -08:00
DebugLog . ToConsole ( $"Warning - {LogName}'s ReferenceTransform is at (0,0,0). ReferenceTransform:{ReferenceTransform.name}, AttachedObject:{AttachedTransform.name}" , MessageType . Warning ) ;
2022-01-14 20:59:42 -08:00
}
2022-01-16 07:23:35 -08:00
if ( UseInterpolation )
2022-01-14 20:59:42 -08:00
{
2022-01-16 08:04:15 -08:00
SmoothPosition = SmartSmoothDamp ( SmoothPosition , transform . position ) ;
2022-01-16 07:56:55 -08:00
SmoothRotation = QuaternionHelper . SmoothDamp ( SmoothRotation , transform . rotation , ref _rotationSmoothVelocity , SmoothTime ) ;
2022-01-14 20:59:42 -08:00
}
2022-01-16 06:53:45 -08:00
if ( hasAuthority )
{
GetFromAttached ( ) ;
}
2022-01-16 08:15:50 -08:00
else if ( ! OnlyApplyOnDeserialize | | _shouldApply )
2022-01-16 06:53:45 -08:00
{
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
base . Update ( ) ;
}
2022-01-16 08:04:15 -08:00
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 ) ;
}
2022-01-14 20:59:42 -08:00
public void SetReferenceTransform ( Transform referenceTransform )
{
if ( ReferenceTransform = = referenceTransform )
{
return ;
}
ReferenceTransform = referenceTransform ;
if ( hasAuthority )
{
transform . position = ReferenceTransform . ToRelPos ( AttachedTransform . position ) ;
transform . rotation = ReferenceTransform . ToRelRot ( AttachedTransform . rotation ) ;
}
else if ( UseInterpolation )
{
SmoothPosition = ReferenceTransform . ToRelPos ( AttachedTransform . position ) ;
SmoothRotation = ReferenceTransform . ToRelRot ( AttachedTransform . rotation ) ;
}
}
protected virtual void OnRenderObject ( )
{
if ( ! QSBCore . ShowLinesInDebug
2022-01-21 17:24:22 -08:00
| | ! IsValid
| | ! ReferenceTransform
| | ! AttachedTransform . gameObject . activeInHierarchy )
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-01-21 17:24:22 -08:00
if ( ! QSBCore . ShowDebugLabels
| | Event . current . type ! = EventType . Repaint
| | ! IsValid
| | ! ReferenceTransform
| | ! AttachedTransform . gameObject . activeInHierarchy )
2022-01-14 20:59:42 -08:00
{
return ;
}
2022-01-21 17:44:12 -08:00
DebugGUI . DrawLabel ( AttachedTransform . transform , LogName ) ;
2022-01-14 20:59:42 -08:00
}
}
2021-07-07 22:12:41 +01:00
}