2021-03-09 19:45:00 +00:00
using OWML.Common ;
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
{
2022-01-21 16:37:30 -08:00
public class QSBSectorDetector : MonoBehaviour
2020-12-02 21:23:01 +00:00
{
2021-08-12 14:20:59 +01:00
public bool IsReady { get ; private set ; }
2021-12-18 12:08:26 -08:00
public readonly List < QSBSector > SectorList = new ( ) ;
2021-02-19 12:54:48 +00:00
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-08-21 19:53:37 +01:00
public void Init ( SectorDetector detector , TargetType type )
2020-12-02 21:23:01 +00:00
{
2021-07-13 15:24:57 +01:00
if ( detector = = null )
{
2022-01-21 16:37:30 -08:00
DebugLog . ToConsole ( $"Error - Trying to init QSBSectorDetector with null SectorDetector." , MessageType . Error ) ;
2021-07-13 15:24:57 +01:00
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
2021-12-18 12:08:26 -08:00
_sectorDetector . _sectorList . ForEach ( AddSector ) ;
2021-07-13 15:24:57 +01:00
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
2022-01-21 16:37:30 -08:00
public void Uninit ( )
{
if ( ! IsReady )
{
return ;
}
_sectorDetector . OnEnterSector - = AddSector ;
_sectorDetector . OnExitSector - = RemoveSector ;
_sectorDetector = null ;
SectorList . Clear ( ) ;
IsReady = false ;
}
2021-03-09 19:45:00 +00:00
private void AddSector ( Sector sector )
2020-12-02 21:23:01 +00:00
{
2021-12-25 22:37:20 -08:00
var worldObject = sector . GetWorldObject < QSBSector > ( ) ;
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-12-18 12:08:26 -08:00
return ;
2021-03-09 19:45:00 +00:00
}
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-12-25 22:37:20 -08:00
var worldObject = sector . GetWorldObject < QSBSector > ( ) ;
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-12-18 12:08:26 -08:00
public QSBSector GetClosestSector ( )
2021-03-09 19:45:00 +00:00
{
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-12-18 12:08:26 -08:00
DebugLog . ToConsole ( $"Warning - Tried to use GetClosestSector() before this SectorSync is ready. Stacktrace:\r\n{Environment.StackTrace}" , MessageType . Warning ) ;
2021-07-10 20:34:43 +01:00
return null ;
}
2021-12-18 12:08:26 -08:00
if ( _sectorDetector = = null )
2021-07-10 20:34:43 +01:00
{
2021-08-12 14:20:59 +01:00
IsReady = false ;
2021-07-10 20:34:43 +01:00
return null ;
}
2021-12-18 12:08:26 -08:00
var inASector = SectorList . Any ( x = > x . ShouldSyncTo ( _targetType ) ) ;
2021-06-19 11:26:05 +01:00
2021-12-18 12:08:26 -08:00
var listToCheck = inASector
? SectorList
: QSBWorldSync . GetWorldObjects < QSBSector > ( ) . Where ( x = > ! x . IsFakeSector & & x . Type ! = Sector . Name . Unnamed ) ;
2021-03-09 21:56:20 +00:00
2021-12-18 12:08:26 -08:00
var goodSectors = listToCheck . Where ( sector = > sector . ShouldSyncTo ( _targetType ) ) . ToList ( ) ;
2021-12-18 10:33:18 +00:00
2021-12-18 12:08:26 -08:00
if ( goodSectors . Count = = 0 )
2021-03-12 21:46:02 +00:00
{
2022-01-16 05:38:06 -08:00
return null ;
2021-03-12 21:46:02 +00:00
}
2021-06-18 22:38:32 +01:00
2021-12-18 12:08:26 -08:00
var closest = goodSectors
. OrderBy ( sector = > CalculateSectorScore ( sector , _sectorDetector . _attachedRigidbody ) ) . First ( ) ;
2021-12-18 10:33:18 +00:00
2021-12-18 12:18:41 -08:00
if ( inASector )
2021-12-18 12:08:26 -08:00
{
var pos = _sectorDetector . _attachedRigidbody . GetPosition ( ) ;
2021-12-18 10:33:18 +00:00
2021-12-18 12:18:41 -08:00
bool IsApproxCloseToClosestSector ( QSBSector sectorToCheck )
2021-12-18 12:21:43 -08:00
= > OWMath . ApproxEquals ( Vector3 . Distance ( sectorToCheck . Position , pos ) ,
Vector3 . Distance ( closest . Position , pos ) ,
0.01f ) ;
2021-12-18 12:18:41 -08:00
bool IsFakeSectorActive ( QSBSector fakeSectorToCheck )
= > goodSectors . Any ( x = > fakeSectorToCheck . FakeSector . AttachedSector = = x . AttachedObject ) ;
2021-12-18 10:33:18 +00:00
2021-12-18 12:08:26 -08:00
var fakeToSyncTo = QSBSectorManager . Instance . FakeSectors . FirstOrDefault ( x = > IsApproxCloseToClosestSector ( x ) & & IsFakeSectorActive ( x ) ) ;
return fakeToSyncTo ? ? closest ;
2021-03-11 20:02:23 +00:00
}
2021-03-13 10:19:02 +00:00
2021-12-18 12:08:26 -08:00
return closest ;
2021-03-09 21:56:20 +00:00
}
2021-12-18 12:08:26 -08:00
private static float CalculateSectorScore ( QSBSector sector , OWRigidbody rigidbody )
2021-04-21 11:02:17 +01:00
{
2021-12-18 12:08:26 -08:00
var distance = ( sector . Position - rigidbody . GetPosition ( ) ) . sqrMagnitude ;
2021-12-18 10:33:18 +00:00
var radius = GetRadius ( sector ) ;
var velocity = GetRelativeVelocity ( sector , rigidbody ) ;
2021-04-21 11:02:17 +01:00
2021-12-18 10:33:18 +00:00
return distance + Mathf . Pow ( radius , 2 ) + velocity ;
2021-04-21 11:02:17 +01:00
}
2021-12-18 12:08:26 -08:00
private static float GetRadius ( QSBSector sector )
2021-03-09 21:56:20 +00:00
{
// 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-12-18 12:08:26 -08:00
private static float GetRelativeVelocity ( QSBSector sector , OWRigidbody rigidbody )
2021-04-21 11:02:17 +01:00
{
var sectorRigidBody = sector . AttachedObject . GetOWRigidbody ( ) ;
if ( sectorRigidBody ! = null & & rigidbody ! = null )
{
var relativeVelocity = sectorRigidBody . GetRelativeVelocity ( rigidbody ) ;
2021-12-18 10:33:18 +00:00
return relativeVelocity . sqrMagnitude ;
2021-04-21 11:02:17 +01:00
}
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
}