quantum-space-buddies/QSB/SectorSync/QSBSectorDetector.cs

177 lines
4.5 KiB
C#
Raw Normal View History

2021-03-09 19:45:00 +00:00
using OWML.Common;
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;
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
{
public class QSBSectorDetector : MonoBehaviour
2020-12-02 21:23:01 +00:00
{
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
public void Init(SectorDetector detector, TargetType type)
2020-12-02 21:23:01 +00:00
{
2022-01-21 17:27:31 -08:00
if (_sectorDetector)
{
2022-01-21 17:27:31 -08:00
return;
}
if (!detector)
{
DebugLog.ToConsole("Error - Trying to init QSBSectorDetector 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
2021-12-18 12:08:26 -08:00
_sectorDetector._sectorList.ForEach(AddSector);
_targetType = type;
2020-12-02 21:23:01 +00:00
}
2020-02-15 20:48:02 +01:00
public void Uninit()
{
2022-01-21 17:27:31 -08:00
if (!_sectorDetector)
{
return;
}
_sectorDetector.OnEnterSector -= AddSector;
_sectorDetector.OnExitSector -= RemoveSector;
_sectorDetector = null;
SectorList.Clear();
}
2021-03-09 19:45:00 +00:00
private void AddSector(Sector sector)
2020-12-02 21:23:01 +00:00
{
2022-01-21 19:23:29 -08:00
if (!sector)
{
// wtf
DebugLog.ToConsole($"Warning - Trying to add {sector.name} for {gameObject.name}, but it is null", MessageType.Warning);
return;
}
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)
{
2022-01-21 19:23:29 -08:00
if (!sector)
{
// wtf
DebugLog.ToConsole($"Warning - Trying to remove {sector.name} for {gameObject.name}, but it is null", MessageType.Warning);
return;
}
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
2022-01-21 16:52:30 -08:00
/// <summary>
/// called only by the sector manager
/// </summary>
2021-12-18 12:08:26 -08:00
public QSBSector GetClosestSector()
2021-03-09 19:45:00 +00:00
{
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();
2022-01-21 17:27:31 -08:00
if (trigger && trigger.GetShape())
2021-03-09 21:56:20 +00:00
{
2022-01-21 17:27:31 -08:00
return trigger.GetShape().CalcWorldBounds().radius;
2021-03-09 21:56:20 +00:00
}
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();
2022-01-21 17:27:31 -08:00
if (sectorRigidBody && rigidbody)
2021-04-21 11:02:17 +01:00
{
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
}