2021-08-14 14:45:52 +01:00
using Harmony ;
using OWML.Common ;
2021-07-07 22:12:41 +01:00
using QSB.Player ;
2021-08-14 14:45:52 +01:00
using QSB.Player.TransformSync ;
2021-07-07 22:12:41 +01:00
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.Collections.Generic ;
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-07-07 23:54:09 +01:00
public abstract class SyncBase : QNetworkTransform
2021-07-07 22:12:41 +01:00
{
2021-08-14 14:45:52 +01:00
private static readonly Dictionary < PlayerInfo , Dictionary < Type , SyncBase > > _storedTransformSyncs = new Dictionary < PlayerInfo , Dictionary < Type , SyncBase > > ( ) ;
public static T GetPlayers < T > ( PlayerInfo player )
where T : SyncBase
{
var dictOfOwnedSyncs = _storedTransformSyncs [ player ] ;
var wantedSync = dictOfOwnedSyncs [ typeof ( T ) ] ;
if ( wantedSync = = default )
{
DebugLog . ToConsole ( $"Error - _storedTransformSyncs does not contain type:{typeof(T)} under player {player.PlayerId}. Attempting to find manually..." , MessageType . Error ) ;
var allSyncs = Resources . FindObjectsOfTypeAll < T > ( ) ;
wantedSync = allSyncs . First ( x = > x . Player = = player ) ;
if ( wantedSync = = default )
{
DebugLog . ToConsole ( $"Error - Could not find type:{typeof(T)} for player {player.PlayerId} manually!" , MessageType . Error ) ;
return default ;
}
}
return ( T ) wantedSync ;
}
2021-07-07 22:12:41 +01:00
public uint AttachedNetId
{
get
{
if ( NetIdentity = = null )
{
DebugLog . ToConsole ( $"Error - Trying to get AttachedNetId with null NetIdentity! Type:{GetType().Name} GrandType:{GetType().GetType().Name}" , MessageType . Error ) ;
return uint . MaxValue ;
}
return NetIdentity . NetId . Value ;
}
}
public uint PlayerId
{
get
{
if ( NetIdentity = = null )
{
DebugLog . ToConsole ( $"Error - Trying to get PlayerId with null NetIdentity! Type:{GetType().Name} GrandType:{GetType().GetType().Name}" , MessageType . Error ) ;
return uint . MaxValue ;
}
return NetIdentity . RootIdentity ! = null
? NetIdentity . RootIdentity . NetId . Value
: AttachedNetId ;
}
}
public PlayerInfo Player = > QSBPlayerManager . GetPlayer ( PlayerId ) ;
2021-07-17 09:51:47 +01:00
private bool _baseIsReady = > QSBPlayerManager . PlayerExists ( PlayerId )
& & Player ! = null
& & Player . PlayerStates . IsReady
& & NetId . Value ! = uint . MaxValue
& & NetId . Value ! = 0 U
& & WorldObjectManager . AllReady ;
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-08-14 14:45:52 +01:00
public abstract bool ShouldReparentAttachedObject { get ; }
2021-07-07 22:12:41 +01:00
2021-07-07 23:54:09 +01:00
public Component AttachedObject { get ; set ; }
2021-07-07 22:12:41 +01:00
public Transform ReferenceTransform { get ; set ; }
protected string _logName = > $"{PlayerId}.{GetType().Name}" ;
protected virtual float DistanceLeeway { get ; } = 5f ;
private float _previousDistance ;
protected const float SmoothTime = 0.1f ;
protected Vector3 _positionSmoothVelocity ;
protected Quaternion _rotationSmoothVelocity ;
protected IntermediaryTransform _intermediaryTransform ;
protected bool _isInitialized ;
2021-08-14 14:45:52 +01:00
protected abstract Component 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-08-14 14:45:52 +01:00
var lowestBound = Resources . FindObjectsOfTypeAll < PlayerTransformSync > ( )
. 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 ;
if ( Player = = null )
2021-07-07 22:12:41 +01:00
{
2021-08-14 14:45:52 +01:00
DebugLog . ToConsole ( $"Error - Player in start of {_logName} was null!" , MessageType . Error ) ;
return ;
2021-07-07 22:12:41 +01:00
}
2021-08-14 14:45:52 +01:00
if ( ! _storedTransformSyncs . ContainsKey ( Player ) )
{
_storedTransformSyncs . Add ( Player , new Dictionary < Type , SyncBase > ( ) ) ;
}
var playerDict = _storedTransformSyncs [ Player ] ;
playerDict [ GetType ( ) ] = this ;
}
protected virtual void OnDestroy ( )
{
if ( ShouldReparentAttachedObject )
{
if ( ! HasAuthority & & AttachedObject ! = null )
{
Destroy ( AttachedObject . gameObject ) ;
}
}
QSBSceneManager . OnSceneLoaded - = OnSceneLoaded ;
if ( ! QSBPlayerManager . PlayerExists ( PlayerId ) )
{
return ;
}
var playerDict = _storedTransformSyncs [ Player ] ;
playerDict . Remove ( GetType ( ) ) ;
}
protected virtual void Init ( )
{
if ( ! QSBSceneManager . IsInUniverse )
{
DebugLog . ToConsole ( $"Error - {_logName} is being init-ed when not in the universe!" , MessageType . Error ) ;
}
// TODO : maybe make it's own option
if ( ShouldReparentAttachedObject )
{
if ( ! HasAuthority & & AttachedObject ! = null )
{
Destroy ( AttachedObject . gameObject ) ;
}
}
AttachedObject = SetAttachedObject ( ) ;
_isInitialized = true ;
}
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
{
Init ( ) ;
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 )
{
DebugLog . ToConsole ( $"Warning - AttachedObject {_logName} is null." , MessageType . Warning ) ;
_isInitialized = false ;
2021-07-11 16:18:47 +01:00
base . Update ( ) ;
2021-07-07 23:04:00 +01:00
return ;
}
2021-07-09 15:55:01 +01:00
if ( ReferenceTransform ! = null & & ReferenceTransform . position = = Vector3 . zero )
{
DebugLog . ToConsole ( $"Warning - {_logName}'s ReferenceTransform is at (0,0,0). ReferenceTransform:{ReferenceTransform.name}, AttachedObject:{AttachedObject.name}" , MessageType . Warning ) ;
}
2021-07-11 16:18:47 +01:00
if ( ! AttachedObject . gameObject . activeInHierarchy & & ! IgnoreDisabledAttachedObject )
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-07-09 15:55:01 +01: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-07-11 16:18:47 +01:00
if ( ReferenceTransform ! = _intermediaryTransform . GetReferenceTransform ( ) )
{
DebugLog . ToConsole ( $"Warning - {_logName}'s ReferenceTransform does not match the reference transform set for the intermediary. ReferenceTransform null : {ReferenceTransform == null}, Intermediary reference null : {_intermediaryTransform.GetReferenceTransform() == null}" ) ;
base . Update ( ) ;
return ;
}
var state = UpdateTransform ( ) ;
if ( ! state )
{
DebugLog . ToConsole ( $"{_logName} UpdateTransform() fail." , MessageType . Error ) ;
base . Update ( ) ;
return ;
}
2021-07-07 23:04:00 +01:00
2021-07-12 22:02:50 +01:00
/ *
2021-07-09 15:55:01 +01:00
var expectedPosition = _intermediaryTransform . GetTargetPosition_Unparented ( ) ;
var actualPosition = AttachedObject . transform . position ;
var distance = Vector3 . Distance ( expectedPosition , actualPosition ) ;
if ( distance > 20 )
{
2021-07-11 16:18:47 +01:00
var intermediaryReference = _intermediaryTransform . GetReferenceTransform ( ) ;
DebugLog . ToConsole ( $"Warning - {_logName}'s AttachedObject ({AttachedObject?.name}) is far away from it's expected position! Info:" +
$"\r\n AttachedObject's parent : {AttachedObject?.transform.parent?.name}" +
2021-07-09 15:55:01 +01:00
$"\r\n Distance : {distance}" +
2021-07-11 16:18:47 +01:00
$"\r\n ReferenceTransform : {(ReferenceTransform == null ? " NULL " : ReferenceTransform.name)}" +
$"\r\n Intermediary's ReferenceTransform : {(intermediaryReference == null ? " NULL " : intermediaryReference.name)}" , MessageType . Warning ) ;
2021-07-09 15:55:01 +01:00
}
2021-07-12 22:02:50 +01:00
* /
2021-07-09 15:55:01 +01:00
2021-07-07 23:04:00 +01:00
base . Update ( ) ;
}
2021-08-14 14:45:52 +01:00
protected Vector3 SmartSmoothDamp ( Vector3 currentPosition , Vector3 targetPosition )
{
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 ) ;
}
public void SetReferenceTransform ( Transform transform )
{
if ( ReferenceTransform = = transform )
{
return ;
}
ReferenceTransform = transform ;
_intermediaryTransform . SetReferenceTransform ( transform ) ;
if ( ShouldReparentAttachedObject )
{
if ( AttachedObject = = null )
{
DebugLog . ToConsole ( $"Warning - AttachedObject was null for {_logName} 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 ) ;
}
}
if ( HasAuthority )
{
_intermediaryTransform . EncodePosition ( AttachedObject . transform . position ) ;
_intermediaryTransform . EncodeRotation ( AttachedObject . transform . rotation ) ;
}
}
private void ReparentAttachedObject ( Transform newParent )
{
if ( AttachedObject . transform . parent ! = null & & AttachedObject . transform . parent . GetComponent < Sector > ( ) = = null )
{
DebugLog . ToConsole ( $"Warning - Trying to reparent AttachedObject {AttachedObject.name} which wasnt attached to sector!" , MessageType . Warning ) ;
}
AttachedObject . transform . SetParent ( newParent , true ) ;
AttachedObject . transform . localScale = Vector3 . one ;
}
2021-07-07 22:12:41 +01:00
protected virtual void OnRenderObject ( )
{
if ( ! QSBCore . WorldObjectsReady
| | ! QSBCore . DebugMode
| | ! QSBCore . ShowLinesInDebug
| | ! IsReady
2021-07-11 16:18:47 +01:00
| | ReferenceTransform = = null
| | _intermediaryTransform . GetReferenceTransform ( ) = = null )
2021-07-07 22:12:41 +01:00
{
return ;
}
/ * Red Cube = Where visible object should be
* Green / Yellow Cube = Where visible object is
2021-07-09 15:55:01 +01:00
* Magenta cube = Reference transform
2021-07-07 22:12:41 +01:00
* Red Line = Connection between Red Cube and Green / Yellow Cube
* Cyan Line = Connection between Green / Yellow cube and reference transform
* /
2021-07-19 14:58:59 +01:00
Popcron . Gizmos . Cube ( _intermediaryTransform . GetTargetPosition_Unparented ( ) , _intermediaryTransform . GetTargetRotation_Unparented ( ) , Vector3 . one / 4 , Color . red ) ;
2021-07-07 22:12:41 +01:00
Popcron . Gizmos . Line ( _intermediaryTransform . GetTargetPosition_Unparented ( ) , AttachedObject . transform . position , Color . red ) ;
var color = HasMoved ( ) ? Color . green : Color . yellow ;
2021-07-19 14:58:59 +01:00
Popcron . Gizmos . Cube ( AttachedObject . transform . position , AttachedObject . transform . rotation , Vector3 . one / 4 , color ) ;
Popcron . Gizmos . Cube ( ReferenceTransform . position , ReferenceTransform . rotation , Vector3 . one / 4 , Color . magenta ) ;
2021-07-07 22:12:41 +01:00
Popcron . Gizmos . Line ( AttachedObject . transform . position , ReferenceTransform . position , Color . cyan ) ;
}
}
}