228 lines
4.9 KiB
C#
Raw Normal View History

2022-01-28 20:49:07 -08:00
using Cysharp.Threading.Tasks;
using OWML.Common;
2021-12-23 17:07:29 -08:00
using QSB.Messaging;
2021-01-26 14:07:17 +00:00
using QSB.Player;
2021-12-23 17:07:29 -08:00
using QSB.QuantumSync.Messages;
2021-02-19 09:40:46 +00:00
using QSB.Utility;
2021-01-26 14:07:17 +00:00
using QSB.WorldSync;
using System.Collections.Generic;
using System.Linq;
2022-01-28 20:49:07 -08:00
using System.Threading;
using UnityEngine;
2021-01-26 14:07:17 +00:00
namespace QSB.QuantumSync.WorldObjects
{
2021-01-29 15:30:40 +00:00
internal abstract class QSBQuantumObject<T> : WorldObject<T>, IQSBQuantumObject
where T : QuantumObject
2021-01-26 14:07:17 +00:00
{
/// <summary>
/// whether the controlling player is always the host <br/>
/// also means this object is considered always enabled
/// </summary>
protected virtual bool HostControls => false;
public uint ControllingPlayer { get; set; }
public bool IsEnabled { get; private set; }
2021-01-26 14:07:17 +00:00
2021-02-19 09:40:46 +00:00
public override void OnRemoval()
{
if (HostControls)
{
return;
}
foreach (var shape in GetAttachedShapes())
{
2021-12-02 12:38:38 +00:00
shape.OnShapeActivated -= OnEnable;
shape.OnShapeDeactivated -= OnDisable;
}
2021-02-19 09:40:46 +00:00
}
2022-01-28 20:50:34 -08:00
public override async UniTask Init(CancellationToken ct)
2021-02-19 09:40:46 +00:00
{
2022-01-28 20:57:17 -08:00
await UniTask.DelayFrame(5, cancellationToken: ct);
if (HostControls)
{
// smallest player id is the host
ControllingPlayer = QSBPlayerManager.PlayerList.Min(x => x.PlayerId);
IsEnabled = true;
return;
}
var attachedShapes = GetAttachedShapes();
if (attachedShapes.Count == 0)
{
IsEnabled = false;
return;
}
2021-12-02 12:38:38 +00:00
2022-01-06 14:57:53 -08:00
foreach (var shape in attachedShapes)
{
shape.OnShapeActivated += OnEnable;
shape.OnShapeDeactivated += OnDisable;
}
if (attachedShapes.All(x => x.enabled && x.gameObject.activeInHierarchy && x.active))
2021-03-17 17:04:57 +00:00
{
IsEnabled = true;
}
2021-12-02 12:38:38 +00:00
else
{
ControllingPlayer = 0u;
IsEnabled = false;
2021-12-02 12:38:38 +00:00
}
2021-02-19 09:40:46 +00:00
}
public override void SendInitialState(uint to)
2022-01-21 15:13:16 -08:00
{
if (QSBCore.IsHost)
{
((IQSBQuantumObject)this).SendMessage(new QuantumAuthorityMessage(ControllingPlayer) { To = to });
}
}
2021-12-02 12:38:38 +00:00
public List<Shape> GetAttachedShapes()
{
2021-02-28 15:06:11 +00:00
if (AttachedObject == null)
{
return new List<Shape>();
}
2021-06-18 22:38:32 +01:00
2021-12-02 12:38:38 +00:00
var visibilityTrackers = AttachedObject._visibilityTrackers;
if (visibilityTrackers == null || visibilityTrackers.Length == 0)
{
return new List<Shape>();
}
2021-06-18 22:38:32 +01:00
if (visibilityTrackers.Any(x => x.GetType() == typeof(RendererVisibilityTracker)))
{
2021-02-28 15:06:11 +00:00
DebugLog.ToConsole($"Warning - {AttachedObject.name} has a RendererVisibilityTracker!", MessageType.Warning);
return new List<Shape>();
}
2021-06-18 22:38:32 +01:00
var totalShapes = new List<Shape>();
2021-12-02 12:38:38 +00:00
foreach (ShapeVisibilityTracker tracker in visibilityTrackers)
{
2021-12-02 12:38:38 +00:00
if (tracker == null)
{
2022-01-23 00:31:15 -08:00
DebugLog.ToConsole($"Warning - a ShapeVisibilityTracker in {this} is null!", MessageType.Warning);
2021-12-02 12:38:38 +00:00
continue;
}
2022-01-07 21:24:39 -08:00
// if the tracker is not active, this won't have been set, so just do it ourselves
tracker._shapes ??= tracker.GetComponents<Shape>();
totalShapes.AddRange(tracker._shapes.Where(x => x != null));
}
2021-06-18 22:38:32 +01:00
return totalShapes;
}
2022-01-11 21:16:34 -08:00
public void SetIsQuantum(bool isQuantum) => AttachedObject._isQuantum = isQuantum;
2021-03-17 17:04:57 +00:00
private void OnEnable(Shape s)
2021-01-26 14:07:17 +00:00
{
2021-12-02 12:38:38 +00:00
if (IsEnabled)
{
return;
}
2021-01-30 10:09:27 +00:00
IsEnabled = true;
if (!QSBWorldSync.AllObjectsReady && !QSBCore.IsHost)
{
return;
}
2021-06-18 22:38:32 +01:00
if (ControllingPlayer != 0)
2021-01-26 14:07:17 +00:00
{
2021-01-26 23:41:53 +00:00
// controlled by another player, dont care that we activate it
2021-01-26 14:07:17 +00:00
return;
}
2021-06-18 22:38:32 +01:00
2021-01-26 23:41:53 +00:00
// no one is controlling this object right now, request authority
((IQSBQuantumObject)this).SendMessage(new QuantumAuthorityMessage(QSBPlayerManager.LocalPlayerId));
2021-01-26 14:07:17 +00:00
}
2022-01-03 00:15:57 -08:00
private void OnDisable(Shape s) =>
// we wait a frame here in case the shapes get disabled as we switch from 1 visibility tracker to another
2022-01-29 01:29:02 -08:00
Delay.RunNextFrame(() =>
{
2022-01-03 00:15:57 -08:00
if (!IsEnabled)
{
return;
}
2021-06-18 22:38:32 +01:00
2022-01-03 00:15:57 -08:00
if (GetAttachedShapes().Any(x => x.isActiveAndEnabled))
{
return;
}
2021-06-18 22:38:32 +01:00
2022-01-03 00:15:57 -08:00
IsEnabled = false;
if (!QSBWorldSync.AllObjectsReady && !QSBCore.IsHost)
2022-01-03 00:15:57 -08:00
{
return;
}
2021-06-18 22:38:32 +01:00
2022-01-03 00:15:57 -08:00
if (ControllingPlayer != QSBPlayerManager.LocalPlayerId)
{
// not being controlled by us, don't care if we leave area
return;
}
2021-06-18 22:38:32 +01:00
2022-01-03 00:15:57 -08:00
// send event to other players that we're releasing authority
((IQSBQuantumObject)this).SendMessage(new QuantumAuthorityMessage(0u));
});
public override void DisplayLines()
{
2022-01-07 20:46:58 +00:00
if (AttachedObject == null)
{
return;
}
var localPlayer = QSBPlayerManager.LocalPlayer;
if (localPlayer == null)
{
return;
}
var body = localPlayer.Body;
if (body == null)
{
return;
}
if (ControllingPlayer == 0)
{
if (IsEnabled)
{
Popcron.Gizmos.Line(AttachedObject.transform.position,
2022-01-07 20:46:58 +00:00
body.transform.position,
Color.magenta * 0.25f);
}
return;
}
2022-01-07 20:46:58 +00:00
var player = QSBPlayerManager.GetPlayer(ControllingPlayer);
if (player == null)
{
return;
}
var playerBody = player.Body;
2022-01-07 20:46:58 +00:00
if (playerBody == null)
{
return;
}
Popcron.Gizmos.Line(AttachedObject.transform.position,
2022-01-07 20:46:58 +00:00
playerBody.transform.position,
Color.magenta);
}
2021-01-26 14:07:17 +00:00
}
}