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-14 22:41:36 -08:00
* Rewrite number : 10
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 set = > _player = value ;
}
private PlayerInfo _player ;
2022-01-14 20:59:42 -08:00
private bool _baseIsReady
{
get
{
if ( netId is uint . MaxValue or 0 )
{
return false ;
}
2022-01-18 00:27:32 -08:00
if ( ! QSBWorldSync . AllObjectsAdded )
2022-01-14 20:59:42 -08:00
{
return false ;
}
if ( IsPlayerObject )
{
2022-01-18 12:54:19 -08:00
if ( _player = = null )
{
return false ;
}
if ( ! isLocalPlayer & & ! Player . IsReady )
2022-01-14 20:59:42 -08:00
{
return false ;
}
}
return true ;
}
}
2022-01-16 06:11:44 -08:00
protected abstract bool IsReady { get ; }
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
public string LogName = > ( IsPlayerObject ? $"{Player.PlayerId}." : string . Empty ) + $"{netId}:{GetType().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-16 05:38:06 -08:00
public bool IsInitialized { get ; private set ; }
2022-01-14 20:59:42 -08:00
protected Vector3 SmoothPosition ;
protected Quaternion SmoothRotation ;
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
Player = QSBPlayerManager . PlayerList
. 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-16 07:56:08 -08:00
if ( IsPlayerObject & & ! hasAuthority & & AttachedTransform ! = null )
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
}
QSBSceneManager . OnSceneLoaded - = OnSceneLoaded ;
}
protected virtual void Init ( )
{
if ( ! QSBSceneManager . IsInUniverse )
{
DebugLog . ToConsole ( $"Error - {LogName} is being init-ed when not in the universe!" , MessageType . Error ) ;
}
2022-01-16 07:56:08 -08:00
if ( IsPlayerObject & & ! hasAuthority & & AttachedTransform ! = null )
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 04:34:52 -08:00
AttachedTransform = InitAttachedTransform ( ) ;
IsInitialized = true ;
2022-01-14 20:59:42 -08:00
}
2022-01-16 04:34:52 -08:00
protected virtual void OnSceneLoaded ( OWScene oldScene , OWScene newScene , bool isInUniverse ) = > 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-16 04:34:52 -08:00
if ( ! IsInitialized & & IsReady & & _baseIsReady )
2022-01-14 20:59:42 -08:00
{
try
{
Init ( ) ;
}
catch ( Exception ex )
{
DebugLog . ToConsole ( $"Exception when initializing {name} : {ex}" , MessageType . Error ) ;
2022-01-16 02:36:39 -08:00
return ;
2022-01-14 20:59:42 -08:00
}
}
2022-01-16 04:34:52 -08:00
else if ( IsInitialized & & ( ! IsReady | | ! _baseIsReady ) )
2022-01-14 20:59:42 -08:00
{
2022-01-16 04:34:52 -08:00
IsInitialized = false ;
2022-01-14 20:59:42 -08:00
return ;
}
2022-01-16 04:34:52 -08:00
if ( ! IsInitialized )
2022-01-14 20:59:42 -08:00
{
return ;
}
if ( AttachedTransform = = null )
{
2022-01-20 22:36:23 -08:00
DebugLog . ToConsole ( $"Error - AttachedObject {LogName} is null!" , MessageType . Error ) ;
2022-01-14 20:59:42 -08:00
return ;
}
2022-01-16 04:52:48 -08:00
if ( ! AttachedTransform . gameObject . activeInHierarchy & & ! AllowDisabledAttachedObject )
2022-01-14 20:59:42 -08:00
{
return ;
}
2022-01-16 02:36:39 -08:00
2022-01-16 04:52:48 -08:00
if ( ReferenceTransform = = null & & ! AllowNullReferenceTransform )
2022-01-14 20:59:42 -08:00
{
2022-01-16 04:34:52 -08:00
DebugLog . ToConsole ( $"Warning - {LogName}'s ReferenceTransform is null. AttachedObject:{AttachedTransform.name}" , MessageType . Warning ) ;
return ;
2022-01-14 20:59:42 -08:00
}
2022-01-20 22:36:23 -08:00
if ( ReferenceTransform = = Locator . GetRootTransform ( ) )
2022-01-14 20:59:42 -08:00
{
2022-01-20 22:36:23 -08:00
return ;
2022-01-14 20:59:42 -08:00
}
2022-01-20 22:36:23 -08:00
if ( ReferenceTransform ! = null & & 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-16 04:34:52 -08:00
| | ! IsInitialized
2022-01-14 20:59:42 -08:00
| | AttachedTransform = = null
| | ReferenceTransform = = null )
{
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 ( )
{
if ( ! QSBCore . ShowDebugLabels | |
Event . current . type ! = EventType . Repaint )
{
return ;
}
if ( AttachedTransform ! = null )
{
DebugGUI . DrawLabel ( AttachedTransform . transform , LogName ) ;
}
}
}
2021-07-07 22:12:41 +01:00
}