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

121 lines
4.0 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 16:08:56 +00:00
using System.Linq;
2020-08-21 13:04:13 +00:00
using UnityEngine;
2020-02-13 19:23:26 +00:00
2020-11-03 22:29:23 +00:00
namespace QSB.SectorSync
2020-02-15 19:48:02 +00:00
{
2021-03-09 19:45:00 +00:00
public class SectorSync : MonoBehaviour
2020-12-02 21:23:01 +00:00
{
2021-03-09 19:45:00 +00:00
public List<QSBSector> SectorList = new List<QSBSector>();
2021-02-19 12:54:48 +00:00
2021-03-09 19:45:00 +00:00
private SectorDetector _sectorDetector;
private readonly Sector.Name[] _sectorBlacklist = { Sector.Name.Ship };
public void SetSectorDetector(SectorDetector detector)
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-03-09 19:45:00 +00:00
_sectorDetector = detector;
_sectorDetector.OnEnterSector += AddSector;
_sectorDetector.OnExitSector += RemoveSector;
2020-12-02 21:23:01 +00:00
}
2020-02-15 19:48:02 +00:00
2021-03-09 19:45:00 +00:00
private void AddSector(Sector sector)
2020-12-02 21:23:01 +00:00
{
2021-03-09 19:45:00 +00:00
var worldObject = QSBWorldSync.GetWorldFromUnity<QSBSector, Sector>(sector);
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);
}
if (SectorList.Contains(worldObject))
{
DebugLog.ToConsole($"Warning - Trying to add {sector.name}, but is already in list", MessageType.Warning);
2020-12-02 21:23:01 +00:00
return;
}
2021-03-09 19:45:00 +00:00
SectorList.Add(worldObject);
}
private void RemoveSector(Sector sector)
{
var worldObject = QSBWorldSync.GetWorldFromUnity<QSBSector, Sector>(sector);
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-03-09 19:45:00 +00:00
if (!SectorList.Contains(worldObject))
2020-12-02 21:23:01 +00:00
{
2021-03-09 19:45:00 +00:00
DebugLog.ToConsole($"Warning - Trying to remove {sector.name}, but is not in list!", MessageType.Warning);
2020-12-02 21:23:01 +00:00
return;
}
2021-03-09 19:45:00 +00:00
SectorList.Remove(worldObject);
2020-12-02 21:23:01 +00:00
}
2020-08-05 19:59:50 +00:00
2021-03-09 19:45:00 +00:00
public QSBSector GetClosestSector(Transform trans) // trans rights \o/
{
if (!QSBSectorManager.Instance.IsReady)
{
DebugLog.ToConsole($"Warning - Tried to get closest sector to {trans.name} before QSBSectorManager was ready.", MessageType.Warning);
return null;
}
var listToCheck = SectorList.Count == 0
? QSBWorldSync.GetWorldObjects<QSBSector>()
: SectorList;
2021-03-09 21:56:20 +00:00
2021-03-09 22:07:14 +00:00
/* Explanation of working out which sector to sync to :
* A) Closer sectors are best
* B) Smaller sub-sectors are preferred
* So, get all non-null sectors that aren't blacklisted and are active
* (They need to be active otherwise it'll sync to disabled sectors, like the eye shuttle - which makes the player invisible)
* Then, sort that list also by the radius of the sector.
* We want smaller subsectors (e.g. Starting_Camp) to be preferred over general sectors (e.g. Village)
* TL;DR : Sync to the smallest, closest sector
*/
2021-03-09 21:56:20 +00:00
var activeNotNullNotBlacklisted = listToCheck.Where(sector => sector.AttachedObject != null
&& !_sectorBlacklist.Contains(sector.Type)
&& sector.Transform.gameObject.activeInHierarchy);
var ordered = activeNotNullNotBlacklisted
2021-03-09 19:45:00 +00:00
.OrderBy(sector => Vector3.Distance(sector.Position, trans.position))
2021-03-09 21:56:52 +00:00
.ThenBy(sector => GetRadius(sector));
2021-03-11 20:02:23 +00:00
if (
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(
x => OWMath.ApproxEquals(Vector3.Distance(x.Position, trans.position), Vector3.Distance(ordered.FirstOrDefault().Position, trans.position), 0.01f)
&& 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-09 21:56:20 +00:00
return ordered.FirstOrDefault();
}
private float GetRadius(QSBSector sector)
{
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;
}
}
return 0f;
2021-03-09 19:45:00 +00:00
}
2020-12-14 21:20:53 +00:00
}
2020-12-03 08:28:05 +00:00
}