2021-03-09 19:45:00 +00:00
using OWML.Common ;
2021-04-21 11:02:17 +01:00
using OWML.Utils ;
2020-12-31 12:10:55 +00:00
using QSB.SectorSync.WorldObjects ;
2021-02-19 12:42:37 +00:00
using QSB.Utility ;
2021-03-09 19:45:00 +00:00
using QSB.WorldSync ;
2021-08-10 14:54:23 +01:00
using System ;
2021-03-09 19:45:00 +00:00
using System.Collections.Generic ;
2020-08-22 17:08:56 +01:00
using System.Linq ;
2020-08-21 14:04:13 +01:00
using UnityEngine ;
2020-02-13 20:23:26 +01:00
2020-11-03 22:29:23 +00:00
namespace QSB.SectorSync
2020-02-15 20:48:02 +01:00
{
2021-03-09 19:45:00 +00:00
public class SectorSync : MonoBehaviour
2020-12-02 21:23:01 +00:00
{
2021-08-12 14:20:59 +01:00
public bool IsReady { get ; private set ; }
2021-11-20 19:49:50 +00:00
public List < QSBSector > SectorList = new ( ) ;
2021-02-19 12:54:48 +00:00
2021-04-21 11:02:17 +01:00
private OWRigidbody _attachedOWRigidbody ;
2021-03-09 19:45:00 +00:00
private SectorDetector _sectorDetector ;
2021-05-15 14:10:51 +01:00
private TargetType _targetType ;
2021-03-09 19:45:00 +00:00
2021-03-22 16:03:00 +00:00
private void OnDestroy ( )
{
if ( _sectorDetector ! = null )
{
_sectorDetector . OnEnterSector - = AddSector ;
_sectorDetector . OnExitSector - = RemoveSector ;
}
2021-08-22 17:17:46 +01:00
2021-08-12 14:20:59 +01:00
IsReady = false ;
2021-03-22 16:03:00 +00:00
}
2021-08-21 19:53:37 +01:00
public void Init ( SectorDetector detector , TargetType type )
2020-12-02 21:23:01 +00:00
{
2021-03-09 19:45:00 +00:00
if ( _sectorDetector ! = null )
2020-12-02 21:23:01 +00:00
{
2021-03-09 19:45:00 +00:00
_sectorDetector . OnEnterSector - = AddSector ;
_sectorDetector . OnExitSector - = RemoveSector ;
2020-12-02 21:23:01 +00:00
}
2021-06-18 22:38:32 +01:00
2021-07-13 15:24:57 +01:00
if ( detector = = null )
{
DebugLog . ToConsole ( $"Error - Trying to init SectorSync with null SectorDetector." , MessageType . Error ) ;
return ;
}
2021-03-09 19:45:00 +00:00
_sectorDetector = detector ;
_sectorDetector . OnEnterSector + = AddSector ;
_sectorDetector . OnExitSector + = RemoveSector ;
2021-04-21 11:02:17 +01:00
_attachedOWRigidbody = _sectorDetector . GetValue < OWRigidbody > ( "_attachedRigidbody" ) ;
if ( _attachedOWRigidbody = = null )
{
DebugLog . ToConsole ( $"Warning - OWRigidbody for {_sectorDetector.name} is null!" , MessageType . Warning ) ;
}
2021-05-15 14:10:51 +01:00
2021-07-13 15:24:57 +01:00
PopulateSectorList ( ) ;
2021-08-21 19:53:37 +01:00
_targetType = type ;
2021-08-12 14:20:59 +01:00
IsReady = true ;
2020-12-02 21:23:01 +00:00
}
2020-02-15 20:48:02 +01:00
2021-07-13 15:24:57 +01:00
private void PopulateSectorList ( )
{
var currentList = _sectorDetector . GetValue < List < Sector > > ( "_sectorList" ) ;
SectorList . Clear ( ) ;
foreach ( var sector in currentList )
{
if ( sector = = null )
{
continue ;
}
AddSector ( sector ) ;
}
}
2021-03-09 19:45:00 +00:00
private void AddSector ( Sector sector )
2020-12-02 21:23:01 +00:00
{
2021-11-01 15:49:00 +00:00
var worldObject = QSBWorldSync . GetWorldFromUnity < QSBSector > ( sector ) ;
2021-03-09 19:45:00 +00:00
if ( worldObject = = null )
2020-12-02 21:23:01 +00:00
{
2021-03-09 19:45:00 +00:00
DebugLog . ToConsole ( $"Error - Can't find QSBSector for sector {sector.name}!" , MessageType . Error ) ;
}
2021-06-18 22:38:32 +01:00
2021-03-09 19:45:00 +00:00
if ( SectorList . Contains ( worldObject ) )
{
2021-03-12 21:46:02 +00:00
DebugLog . ToConsole ( $"Warning - Trying to add {sector.name} for {gameObject.name}, but is already in list" , MessageType . Warning ) ;
2020-12-02 21:23:01 +00:00
return ;
}
2021-06-18 22:38:32 +01:00
2021-03-09 19:45:00 +00:00
SectorList . Add ( worldObject ) ;
}
private void RemoveSector ( Sector sector )
{
2021-11-01 15:49:00 +00:00
var worldObject = QSBWorldSync . GetWorldFromUnity < QSBSector > ( sector ) ;
2021-03-09 19:45:00 +00:00
if ( worldObject = = null )
2021-02-28 15:35:01 +00:00
{
2021-03-09 19:45:00 +00:00
DebugLog . ToConsole ( $"Error - Can't find QSBSector for sector {sector.name}!" , MessageType . Error ) ;
2021-02-28 15:35:01 +00:00
return ;
}
2021-06-18 22:38:32 +01:00
2021-03-09 19:45:00 +00:00
if ( ! SectorList . Contains ( worldObject ) )
2020-12-02 21:23:01 +00:00
{
2021-03-12 21:46:02 +00:00
DebugLog . ToConsole ( $"Warning - Trying to remove {sector.name} for {gameObject.name}, but is not in list!" , MessageType . Warning ) ;
2020-12-02 21:23:01 +00:00
return ;
}
2021-06-18 22:38:32 +01:00
2021-03-09 19:45:00 +00:00
SectorList . Remove ( worldObject ) ;
2020-12-02 21:23:01 +00:00
}
2020-08-05 21:59:50 +02:00
2021-03-09 19:45:00 +00:00
public QSBSector GetClosestSector ( Transform trans ) // trans rights \o/
{
2021-07-17 09:53:29 +01:00
if ( QSBSectorManager . Instance = = null | | ! QSBSectorManager . Instance . IsReady )
2021-03-09 19:45:00 +00:00
{
return null ;
}
2021-08-12 14:20:59 +01:00
if ( ! IsReady )
2021-07-10 20:34:43 +01:00
{
2021-09-02 11:24:13 +01:00
DebugLog . ToConsole ( $"Warning - Tried to use GetClosestSector() before this SectorSync is ready. Transform:{trans.name} Stacktrace:\r\n{Environment.StackTrace}" , MessageType . Warning ) ;
2021-07-10 20:34:43 +01:00
return null ;
}
if ( _sectorDetector = = null | | _attachedOWRigidbody = = null | | _targetType = = TargetType . None )
{
2021-08-12 14:20:59 +01:00
IsReady = false ;
2021-07-10 20:34:43 +01:00
DebugLog . ToConsole ( $"Error - SectorSync is no longer ready. Detector Null : {_sectorDetector == null}, OWRigidbody Null : {_attachedOWRigidbody == null}, None TargetType : {_targetType == TargetType.None}" , MessageType . Error ) ;
return null ;
}
2021-10-24 10:47:25 +01:00
bool ShouldSyncTo ( QSBSector sector , TargetType type )
{
if ( sector = = null )
{
DebugLog . ToConsole ( $"Warning - Tried to check if we should sync to null sector!" , MessageType . Warning ) ;
return false ;
}
return sector . ShouldSyncTo ( type ) ;
}
var numSectorsCurrentlyIn = SectorList . Count ( x = > ShouldSyncTo ( x , _targetType ) ) ;
2021-06-19 11:26:05 +01:00
2021-05-26 20:43:25 +01:00
var listToCheck = numSectorsCurrentlyIn = = 0
2021-06-13 19:44:35 +01:00
? QSBWorldSync . GetWorldObjects < QSBSector > ( ) . Where ( x = > ! x . IsFakeSector & & x . Type ! = Sector . Name . Unnamed )
2021-03-09 19:45:00 +00:00
: SectorList ;
2021-03-09 21:56:20 +00:00
var activeNotNullNotBlacklisted = listToCheck . Where ( sector = > sector . AttachedObject ! = null
2021-05-15 14:10:51 +01:00
& & sector . ShouldSyncTo ( _targetType ) ) ;
2021-03-12 21:46:02 +00:00
if ( activeNotNullNotBlacklisted . Count ( ) = = 0 )
{
2021-03-31 15:43:55 +01:00
return default ;
2021-03-12 21:46:02 +00:00
}
2021-06-18 22:38:32 +01:00
2021-03-09 21:56:20 +00:00
var ordered = activeNotNullNotBlacklisted
2021-04-21 11:02:17 +01:00
. OrderBy ( sector = > CalculateSectorScore ( sector , trans , _attachedOWRigidbody ) ) ;
2021-03-11 20:02:23 +00:00
2021-05-26 20:43:25 +01:00
// TODO : clean up this shit???
2021-03-11 20:02:23 +00:00
if (
2021-05-26 20:43:25 +01:00
numSectorsCurrentlyIn ! = 0 & &
2021-03-12 20:49:48 +00:00
// if any fake sectors are *roughly* in the same place as other sectors - we want fake sectors to override other sectors
2021-03-11 20:02:23 +00:00
QSBSectorManager . Instance . FakeSectors . Any (
2021-03-13 10:19:02 +00:00
x = > OWMath . ApproxEquals ( Vector3 . Distance ( x . Position , trans . position ) , Vector3 . Distance ( ordered . FirstOrDefault ( ) . Position , trans . position ) , 0.01f )
2021-03-11 20:02:23 +00:00
& & activeNotNullNotBlacklisted . Any (
y = > y . AttachedObject = = ( x . AttachedObject as FakeSector ) . AttachedSector ) ) )
{
return QSBSectorManager . Instance . FakeSectors . First ( x = > OWMath . ApproxEquals ( Vector3 . Distance ( x . Position , trans . position ) , Vector3 . Distance ( ordered . FirstOrDefault ( ) . Position , trans . position ) , 0.01f ) ) ;
}
2021-03-13 10:19:02 +00:00
2021-03-09 21:56:20 +00:00
return ordered . FirstOrDefault ( ) ;
}
2021-04-21 11:02:17 +01:00
public static float CalculateSectorScore ( QSBSector sector , Transform trans , OWRigidbody rigidbody )
{
var distance = Vector3 . Distance ( sector . Position , trans . position ) ; // want to be small
var radius = GetRadius ( sector ) ; // want to be small
var velocity = GetRelativeVelocity ( sector , rigidbody ) ; // want to be small
2021-05-15 14:10:51 +01:00
return Mathf . Pow ( distance , 2 ) + Mathf . Pow ( radius , 2 ) + Mathf . Pow ( velocity , 2 ) ;
2021-04-21 11:02:17 +01:00
}
public static float GetRadius ( QSBSector sector )
2021-03-09 21:56:20 +00:00
{
if ( sector = = null )
{
return 0f ;
}
// TODO : make this work for other stuff, not just shaped triggervolumes
var trigger = sector . AttachedObject . GetTriggerVolume ( ) ;
if ( trigger ! = null )
{
if ( trigger . GetShape ( ) ! = null )
{
return trigger . GetShape ( ) . CalcWorldBounds ( ) . radius ;
}
}
2021-06-18 22:38:32 +01:00
2021-03-09 21:56:20 +00:00
return 0f ;
2021-03-09 19:45:00 +00:00
}
2021-06-19 11:26:05 +01:00
2021-04-21 11:02:17 +01:00
public static float GetRelativeVelocity ( QSBSector sector , OWRigidbody rigidbody )
{
var sectorRigidBody = sector . AttachedObject . GetOWRigidbody ( ) ;
if ( sectorRigidBody ! = null & & rigidbody ! = null )
{
var relativeVelocity = sectorRigidBody . GetRelativeVelocity ( rigidbody ) ;
var relativeVelocityMagnitude = relativeVelocity . sqrMagnitude ; // Remember this is squared for efficiency!
return relativeVelocityMagnitude ;
}
2021-06-18 22:38:32 +01:00
2021-04-21 11:02:17 +01:00
return 0 ;
}
2020-12-14 21:20:53 +00:00
}
2020-12-03 08:28:05 +00:00
}