Merge branch 'dev' into join-leave-singularity

# Conflicts:
#	QSB/Player/QSBPlayerManager.cs
#	QSB/SectorSync/QSBSectorDetector.cs
#	QSB/Utility/Extensions.cs
This commit is contained in:
JohnCorby 2022-02-16 21:52:59 -08:00
commit b2d60eb024
38 changed files with 263 additions and 317 deletions

View File

@ -37,13 +37,8 @@ namespace QSB.Anglerfish.WorldObjects
}
}
public override void SendInitialState(uint to)
{
if (TransformSync.hasAuthority)
{
this.SendMessage(new AnglerDataMessage(this) { To = to });
}
}
public override void SendInitialState(uint to) =>
this.SendMessage(new AnglerDataMessage(this) { To = to });
public void UpdateTargetVelocity()
{

View File

@ -6,13 +6,8 @@ namespace QSB.CampfireSync.WorldObjects
{
public class QSBCampfire : WorldObject<Campfire>
{
public override void SendInitialState(uint to)
{
if (QSBCore.IsHost)
{
this.SendMessage(new CampfireStateMessage(GetState()) { To = to });
}
}
public override void SendInitialState(uint to) =>
this.SendMessage(new CampfireStateMessage(GetState()) { To = to });
public void StartRoasting()
=> AttachedObject.StartRoasting();

View File

@ -6,13 +6,8 @@ namespace QSB.ConversationSync.WorldObjects
{
internal class QSBRemoteDialogueTrigger : WorldObject<RemoteDialogueTrigger>
{
public override void SendInitialState(uint to)
{
if (QSBCore.IsHost)
{
this.SendMessage(new RemoteDialogueInitialStateMessage(AttachedObject) { To = to });
}
}
public override void SendInitialState(uint to) =>
this.SendMessage(new RemoteDialogueInitialStateMessage(AttachedObject) { To = to });
public void RemoteEnterDialogue(int dialogueIndex)
{

View File

@ -22,13 +22,8 @@ namespace QSB.ElevatorSync.WorldObjects
_elevatorTrigger = AttachedObject.gameObject.GetAddComponent<OWTriggerVolume>();
}
public override void SendInitialState(uint to)
{
if (QSBCore.IsHost)
{
this.SendMessage(new ElevatorMessage(AttachedObject._goingToTheEnd));
}
}
public override void SendInitialState(uint to) =>
this.SendMessage(new ElevatorMessage(AttachedObject._goingToTheEnd));
public void RemoteCall(bool isGoingUp)
{

View File

@ -26,13 +26,8 @@ namespace QSB.GeyserSync.WorldObjects
}
}
public override void SendInitialState(uint to)
{
if (QSBCore.IsHost)
{
this.SendMessage(new GeyserMessage(AttachedObject._isActive));
}
}
public override void SendInitialState(uint to) =>
this.SendMessage(new GeyserMessage(AttachedObject._isActive));
private void OnActivate() => this.SendMessage(new GeyserMessage(true));
private void OnDeactivate() => this.SendMessage(new GeyserMessage(false));

View File

@ -95,8 +95,8 @@ namespace QSB.JellyfishSync.TransformSync
var pos = ReferenceTransform.FromRelPos(transform.position);
AttachedRigidbody.SetPosition(pos);
AttachedRigidbody.SetRotation(ReferenceTransform.FromRelRot(transform.rotation));
AttachedRigidbody.SetVelocity(ReferenceTransform.GetAttachedOWRigidbody().FromRelVel(_relativeVelocity, pos));
AttachedRigidbody.SetAngularVelocity(ReferenceTransform.GetAttachedOWRigidbody().FromRelAngVel(_relativeAngularVelocity));
AttachedRigidbody.SetVelocity(ReferenceRigidbody.FromRelVel(Velocity, pos));
AttachedRigidbody.SetAngularVelocity(ReferenceRigidbody.FromRelAngVel(AngularVelocity));
_qsbJellyfish.SetIsRising(_isRising);
}

View File

@ -33,13 +33,8 @@ namespace QSB.JellyfishSync.WorldObjects
}
}
public override void SendInitialState(uint to)
{
if (TransformSync.hasAuthority)
{
this.SendMessage(new JellyfishRisingMessage(AttachedObject._isRising) { To = to });
}
}
public override void SendInitialState(uint to) =>
this.SendMessage(new JellyfishRisingMessage(AttachedObject._isRising) { To = to });
public void SetIsRising(bool value)
{

View File

@ -19,13 +19,8 @@ namespace QSB.MeteorSync.WorldObjects
}
}
public override void SendInitialState(uint to)
{
if (QSBCore.IsHost)
{
this.SendMessage(new FragmentInitialStateMessage(this) { To = to });
}
}
public override void SendInitialState(uint to) =>
this.SendMessage(new FragmentInitialStateMessage(this) { To = to });
public DetachableFragment DetachableFragment;
public bool IsDetached => DetachableFragment != null && DetachableFragment._isDetached;

View File

@ -16,7 +16,7 @@ namespace QSB.OrbSync.TransformSync
protected override bool CheckValid() => AttachedTransform && base.CheckValid();
protected override bool UseInterpolation => true;
protected override float DistanceLeeway => 1f;
protected override float DistanceChangeThreshold => 1f;
protected override Transform InitLocalTransform() => _qsbOrb.AttachedObject.transform;
protected override Transform InitRemoteTransform() => _qsbOrb.AttachedObject.transform;

View File

@ -36,12 +36,9 @@ namespace QSB.OrbSync.WorldObjects
public override void SendInitialState(uint to)
{
if (TransformSync.hasAuthority)
{
this.SendMessage(new OrbDragMessage(AttachedObject._isBeingDragged) { To = to });
var slotIndex = AttachedObject._slots.IndexOf(AttachedObject._occupiedSlot);
this.SendMessage(new OrbSlotMessage(slotIndex, false) { To = to });
}
this.SendMessage(new OrbDragMessage(AttachedObject._isBeingDragged) { To = to });
var slotIndex = AttachedObject._slots.IndexOf(AttachedObject._occupiedSlot);
this.SendMessage(new OrbSlotMessage(slotIndex, false) { To = to });
}
public void SetDragging(bool value)

View File

@ -94,8 +94,8 @@ namespace QSB.Player
=> PlayerList.ForEach(x => x.SetVisible(false, 2));
public static PlayerInfo GetClosestPlayerToWorldPoint(Vector3 worldPoint, bool includeLocalPlayer) => includeLocalPlayer
? GetClosestPlayerToWorldPoint(PlayerList, worldPoint)
: GetClosestPlayerToWorldPoint(PlayerList.Where(x => x != LocalPlayer).ToList(), worldPoint);
? GetClosestPlayerToWorldPoint(PlayerList, worldPoint)
: GetClosestPlayerToWorldPoint(PlayerList.Where(x => x != LocalPlayer).ToList(), worldPoint);
public static PlayerInfo GetClosestPlayerToWorldPoint(List<PlayerInfo> playerList, Vector3 worldPoint)
{
@ -105,16 +105,18 @@ namespace QSB.Player
return null;
}
playerList = playerList.Where(x => x.IsReady && x.Body != null).ToList();
if (playerList.Count == 0)
{
DebugLog.ToConsole($"Error - Cannot get closest player from empty player list.", MessageType.Error);
DebugLog.ToConsole($"Error - Cannot get closest player from empty (ready) player list.", MessageType.Error);
return null;
}
return playerList.Where(x => x.IsReady && x.Body != null).MinBy(x => Vector3.Distance(x.Body.transform.position, worldPoint));
return playerList.MinBy(x => Vector3.Distance(x.Body.transform.position, worldPoint));
}
public static IEnumerable<Tuple<PlayerInfo, IQSBItem>> GetPlayerCarryItems()
=> PlayerList.Select(x => new Tuple<PlayerInfo, IQSBItem>(x, x.HeldItem));
}
}
}

View File

@ -22,7 +22,7 @@ namespace QSB.PlayerBodySetup.Local
{
DebugLog.DebugWrite($"CREATE PLAYER");
sectorDetector.Init(Locator.GetPlayerSectorDetector(), TargetType.Player);
sectorDetector.Init(Locator.GetPlayerSectorDetector());
// player body
var playerBody = Locator.GetPlayerTransform();

View File

@ -73,13 +73,8 @@ namespace QSB.QuantumSync.WorldObjects
}
}
public override void SendInitialState(uint to)
{
if (QSBCore.IsHost)
{
((IQSBQuantumObject)this).SendMessage(new QuantumAuthorityMessage(ControllingPlayer) { To = to });
}
}
public override void SendInitialState(uint to) =>
((IQSBQuantumObject)this).SendMessage(new QuantumAuthorityMessage(ControllingPlayer) { To = to });
public List<Shape> GetAttachedShapes()
{

View File

@ -13,9 +13,8 @@ namespace QSB.SectorSync
public readonly List<QSBSector> SectorList = new();
private SectorDetector _sectorDetector;
private TargetType _targetType;
public void Init(SectorDetector detector, TargetType type)
public void Init(SectorDetector detector)
{
if (_sectorDetector)
{
@ -33,8 +32,6 @@ namespace QSB.SectorSync
_sectorDetector.OnExitSector += RemoveSector;
_sectorDetector._sectorList.ForEach(AddSector);
_targetType = type;
}
public void Uninit()
@ -106,35 +103,41 @@ namespace QSB.SectorSync
/// </summary>
public QSBSector GetClosestSector()
{
var inASector = SectorList.Any(x => x.ShouldSyncTo(_targetType));
var type = _sectorDetector._occupantType;
var listToCheck = inASector
? SectorList
: QSBWorldSync.GetWorldObjects<QSBSector>().Where(x => !x.IsFakeSector && x.Type != Sector.Name.Unnamed);
var validSectors = SectorList.Where(x => x.ShouldSyncTo(type)).ToList();
var inASector = validSectors.Count > 0;
var goodSectors = listToCheck.Where(sector => sector.ShouldSyncTo(_targetType)).ToList();
if (!inASector)
{
validSectors = QSBWorldSync.GetWorldObjects<QSBSector>()
.Where(x => !x.IsFakeSector && x.Type != Sector.Name.Unnamed && x.ShouldSyncTo(type))
.ToList();
}
if (goodSectors.Count == 0)
if (validSectors.Count == 0)
{
return null;
}
var closest = goodSectors
var closest = validSectors
.MinBy(sector => CalculateSectorScore(sector, _sectorDetector._attachedRigidbody));
if (inASector)
{
var pos = _sectorDetector._attachedRigidbody.GetPosition();
bool IsApproxCloseToClosestSector(QSBSector sectorToCheck)
=> OWMath.ApproxEquals(Vector3.Distance(sectorToCheck.Position, pos),
Vector3.Distance(closest.Position, pos),
0.01f);
bool IsSameDistanceAsClosest(QSBSector fakeSector)
=> OWMath.ApproxEquals(
Vector3.Distance(fakeSector.Position, pos),
Vector3.Distance(closest.Position, pos),
0.01f);
bool IsFakeSectorActive(QSBSector fakeSectorToCheck)
=> goodSectors.Any(x => fakeSectorToCheck.FakeSector.AttachedSector == x.AttachedObject);
bool IsAttachedValid(QSBSector fakeSector)
=> validSectors.Any(x => x.AttachedObject == fakeSector.FakeSector.AttachedSector);
var fakeToSyncTo = QSBSectorManager.Instance.FakeSectors.FirstOrDefault(x => IsApproxCloseToClosestSector(x) && IsFakeSectorActive(x));
var fakeToSyncTo = QSBSectorManager.Instance.FakeSectors
.FirstOrDefault(x => IsSameDistanceAsClosest(x) && IsAttachedValid(x));
return fakeToSyncTo ?? closest;
}
@ -174,4 +177,4 @@ namespace QSB.SectorSync
return 0;
}
}
}
}

View File

@ -1,9 +0,0 @@
namespace QSB.SectorSync
{
public enum TargetType
{
Player,
Probe,
Ship
}
}

View File

@ -26,6 +26,7 @@ namespace QSB.SectorSync.WorldObjects
}
}
public Vector3 Position => Transform.position;
public bool IsFakeSector => AttachedObject is FakeSector;
public FakeSector FakeSector => (FakeSector)AttachedObject;
@ -47,7 +48,7 @@ namespace QSB.SectorSync.WorldObjects
public override void SendInitialState(uint to) { }
public bool ShouldSyncTo(TargetType targetType)
public bool ShouldSyncTo(DynamicOccupant occupantType)
{
if (AttachedObject == null)
{
@ -60,7 +61,7 @@ namespace QSB.SectorSync.WorldObjects
return false;
}
if (targetType == TargetType.Ship && Type == Sector.Name.Ship)
if (occupantType == DynamicOccupant.Ship && Type == Sector.Name.Ship)
{
return false;
}

View File

@ -1,4 +1,3 @@
using QSB.SectorSync;
using QSB.Syncs.Sectored.Rigidbodies;
using QSB.Utility;
using UnityEngine;
@ -23,7 +22,7 @@ namespace QSB.ShipSync.TransformSync
protected override OWRigidbody InitAttachedRigidbody()
{
SectorDetector.Init(Locator.GetShipDetector().GetComponent<SectorDetector>(), TargetType.Ship);
SectorDetector.Init(Locator.GetShipDetector().GetComponent<SectorDetector>());
return Locator.GetShipBody();
}
@ -49,8 +48,8 @@ namespace QSB.ShipSync.TransformSync
AttachedRigidbody.SetRotation(targetRot);
}
var targetVelocity = ReferenceTransform.GetAttachedOWRigidbody().FromRelVel(_relativeVelocity, targetPos);
var targetAngularVelocity = ReferenceTransform.GetAttachedOWRigidbody().FromRelAngVel(_relativeAngularVelocity);
var targetVelocity = ReferenceRigidbody.FromRelVel(Velocity, targetPos);
var targetAngularVelocity = ReferenceRigidbody.FromRelAngVel(AngularVelocity);
SetVelocity(AttachedRigidbody, targetVelocity);
AttachedRigidbody.SetAngularVelocity(targetAngularVelocity);

View File

@ -9,19 +9,16 @@ namespace QSB.ShipSync.WorldObjects
{
public override void SendInitialState(uint to)
{
if (QSBCore.IsHost)
if (AttachedObject._damaged)
{
if (AttachedObject._damaged)
{
this.SendMessage(new ComponentDamagedMessage());
}
else
{
this.SendMessage(new ComponentRepairedMessage());
}
this.SendMessage(new ComponentRepairTickMessage(AttachedObject._repairFraction));
this.SendMessage(new ComponentDamagedMessage());
}
else
{
this.SendMessage(new ComponentRepairedMessage());
}
this.SendMessage(new ComponentRepairTickMessage(AttachedObject._repairFraction));
}
public void SetDamaged()

View File

@ -9,19 +9,16 @@ namespace QSB.ShipSync.WorldObjects
{
public override void SendInitialState(uint to)
{
if (QSBCore.IsHost)
if (AttachedObject._damaged)
{
if (AttachedObject._damaged)
{
this.SendMessage(new HullDamagedMessage());
}
else
{
this.SendMessage(new HullRepairedMessage());
}
this.SendMessage(new HullChangeIntegrityMessage(AttachedObject._integrity));
this.SendMessage(new HullDamagedMessage());
}
else
{
this.SendMessage(new HullRepairedMessage());
}
this.SendMessage(new HullChangeIntegrityMessage(AttachedObject._integrity));
}
public void SetDamaged()

View File

@ -72,8 +72,8 @@ namespace QSB.Syncs.Occasional
var pos = ReferenceTransform.FromRelPos(transform.position);
AttachedRigidbody.SetPosition(pos);
AttachedRigidbody.SetRotation(ReferenceTransform.FromRelRot(transform.rotation));
AttachedRigidbody.SetVelocity(ReferenceTransform.GetAttachedOWRigidbody().FromRelVel(_relativeVelocity, pos));
AttachedRigidbody.SetAngularVelocity(ReferenceTransform.GetAttachedOWRigidbody().FromRelAngVel(_relativeAngularVelocity));
AttachedRigidbody.SetVelocity(ReferenceRigidbody.FromRelVel(Velocity, pos));
AttachedRigidbody.SetAngularVelocity(ReferenceRigidbody.FromRelAngVel(AngularVelocity));
Move();
}

View File

@ -8,8 +8,11 @@ namespace QSB.Syncs
{
protected override float SendInterval => 0.05f;
protected Vector3 _prevPosition;
protected Quaternion _prevRotation;
private const float PositionChangeThreshold = 0.05f;
private const float RotationChangeThreshold = 0.05f;
private Vector3 _prevPosition;
private Quaternion _prevRotation;
protected override void UpdatePrevData()
{
@ -18,8 +21,8 @@ namespace QSB.Syncs
}
protected override bool HasChanged() =>
Vector3.Distance(transform.position, _prevPosition) > 1E-05f ||
Quaternion.Angle(transform.rotation, _prevRotation) > 1E-05f;
Vector3.Distance(transform.position, _prevPosition) > PositionChangeThreshold ||
Quaternion.Angle(transform.rotation, _prevRotation) > RotationChangeThreshold;
protected override void Serialize(NetworkWriter writer)
{

View File

@ -10,8 +10,11 @@ namespace QSB.Syncs
protected override float SendInterval => 0.05f;
protected Vector3 _prevPosition;
protected Quaternion _prevRotation;
private const float PositionChangeThreshold = 0.05f;
private const float RotationChangeThreshold = 0.05f;
private Vector3 _prevPosition;
private Quaternion _prevRotation;
protected override void UpdatePrevData()
{
@ -20,8 +23,8 @@ namespace QSB.Syncs
}
protected override bool HasChanged() =>
Vector3.Distance(Target.localPosition, _prevPosition) > 1E-05f ||
Quaternion.Angle(Target.localRotation, _prevRotation) > 1E-05f;
Vector3.Distance(Target.localPosition, _prevPosition) > PositionChangeThreshold ||
Quaternion.Angle(Target.localRotation, _prevRotation) > RotationChangeThreshold;
protected override void Serialize(NetworkWriter writer)
{

View File

@ -60,6 +60,9 @@ namespace QSB.Syncs.Sectored
SetReferenceSector(_sectorId.GetWorldObject<QSBSector>());
}
/// <summary>
/// use this instead of SetReferenceTransform
/// </summary>
public void SetReferenceSector(QSBSector sector)
{
if (ReferenceSector == sector)

View File

@ -6,17 +6,16 @@ namespace QSB.Syncs.Sectored.Rigidbodies
{
public abstract class SectoredRigidbodySync : BaseSectoredSync
{
private const float PositionMovedThreshold = 0.05f;
private const float AngleRotatedThreshold = 0.05f;
private const float VelocityChangeThreshold = 0.05f;
private const float AngVelocityChangeThreshold = 0.05f;
private const float AngularVelocityChangeThreshold = 0.05f;
protected Vector3 _relativeVelocity;
protected Vector3 _relativeAngularVelocity;
protected Vector3 Velocity;
protected Vector3 AngularVelocity;
private Vector3 _prevVelocity;
private Vector3 _prevAngularVelocity;
public OWRigidbody AttachedRigidbody { get; private set; }
public OWRigidbody ReferenceRigidbody { get; private set; }
protected abstract OWRigidbody InitAttachedRigidbody();
@ -26,25 +25,36 @@ namespace QSB.Syncs.Sectored.Rigidbodies
return AttachedRigidbody ? AttachedRigidbody.transform : null;
}
public override void SetReferenceTransform(Transform referenceTransform)
{
if (ReferenceTransform == referenceTransform)
{
return;
}
base.SetReferenceTransform(referenceTransform);
ReferenceRigidbody = ReferenceTransform ? ReferenceTransform.GetAttachedOWRigidbody() : null;
}
protected override void UpdatePrevData()
{
base.UpdatePrevData();
_prevVelocity = _relativeVelocity;
_prevAngularVelocity = _relativeAngularVelocity;
_prevVelocity = Velocity;
_prevAngularVelocity = AngularVelocity;
}
protected override void Serialize(NetworkWriter writer)
{
base.Serialize(writer);
writer.Write(_relativeVelocity);
writer.Write(_relativeAngularVelocity);
writer.Write(Velocity);
writer.Write(AngularVelocity);
}
protected override void Deserialize(NetworkReader reader)
{
base.Deserialize(reader);
_relativeVelocity = reader.ReadVector3();
_relativeAngularVelocity = reader.ReadVector3();
Velocity = reader.ReadVector3();
AngularVelocity = reader.ReadVector3();
}
protected override void GetFromAttached()
@ -57,8 +67,8 @@ namespace QSB.Syncs.Sectored.Rigidbodies
transform.position = ReferenceTransform.ToRelPos(AttachedRigidbody.GetPosition());
transform.rotation = ReferenceTransform.ToRelRot(AttachedRigidbody.GetRotation());
_relativeVelocity = ReferenceTransform.GetAttachedOWRigidbody().ToRelVel(AttachedRigidbody.GetVelocity(), AttachedRigidbody.GetPosition());
_relativeAngularVelocity = ReferenceTransform.GetAttachedOWRigidbody().ToRelAngVel(AttachedRigidbody.GetAngularVelocity());
Velocity = ReferenceRigidbody.ToRelVel(AttachedRigidbody.GetVelocity(), AttachedRigidbody.GetPosition());
AngularVelocity = ReferenceRigidbody.ToRelAngVel(AttachedRigidbody.GetAngularVelocity());
}
protected override void ApplyToAttached()
@ -84,36 +94,16 @@ namespace QSB.Syncs.Sectored.Rigidbodies
AttachedRigidbody.MoveToPosition(positionToSet);
AttachedRigidbody.MoveToRotation(rotationToSet);
var targetVelocity = ReferenceTransform.GetAttachedOWRigidbody().FromRelVel(_relativeVelocity, targetPos);
var targetAngularVelocity = ReferenceTransform.GetAttachedOWRigidbody().FromRelAngVel(_relativeAngularVelocity);
var targetVelocity = ReferenceRigidbody.FromRelVel(Velocity, targetPos);
var targetAngularVelocity = ReferenceRigidbody.FromRelAngVel(AngularVelocity);
AttachedRigidbody.SetVelocity(targetVelocity);
AttachedRigidbody.SetAngularVelocity(targetAngularVelocity);
}
protected override bool HasChanged()
{
if (Vector3.Distance(transform.position, _prevPosition) > PositionMovedThreshold)
{
return true;
}
if (Quaternion.Angle(transform.rotation, _prevRotation) > AngleRotatedThreshold)
{
return true;
}
if (Vector3.Distance(_relativeVelocity, _prevVelocity) > VelocityChangeThreshold)
{
return true;
}
if (Vector3.Distance(_relativeAngularVelocity, _prevAngularVelocity) > AngVelocityChangeThreshold)
{
return true;
}
return false;
}
protected override bool HasChanged() =>
base.HasChanged() ||
Vector3.Distance(Velocity, _prevVelocity) > VelocityChangeThreshold ||
Vector3.Distance(AngularVelocity, _prevAngularVelocity) > AngularVelocityChangeThreshold;
}
}

View File

@ -118,8 +118,8 @@ namespace QSB.Syncs
public override string ToString() => (IsPlayerObject ? $"{Player.PlayerId}." : string.Empty)
+ $"{netId}:{GetType().Name} ({Name})";
protected virtual float DistanceLeeway => 5f;
private float _previousDistance;
protected virtual float DistanceChangeThreshold => 5f;
private float _prevDistance;
protected const float SmoothTime = 0.1f;
private Vector3 _positionSmoothVelocity;
private Quaternion _rotationSmoothVelocity;
@ -219,7 +219,6 @@ namespace QSB.Syncs
if (_pauseTimer > 0)
{
_pauseTimer = Mathf.Max(0, _pauseTimer - Time.unscaledDeltaTime);
base.Update();
return;
}
@ -230,14 +229,11 @@ namespace QSB.Syncs
else if (IsInitialized && !CheckReady())
{
SafeUninit();
base.Update();
return;
}
IsValid = CheckValid();
if (!IsValid)
{
base.Update();
return;
}
@ -248,8 +244,7 @@ namespace QSB.Syncs
if (!hasAuthority && UseInterpolation)
{
SmoothPosition = SmartSmoothDamp(SmoothPosition, transform.position);
SmoothRotation = QuaternionHelper.SmoothDamp(SmoothRotation, transform.rotation, ref _rotationSmoothVelocity, SmoothTime);
Interpolate();
}
if (hasAuthority)
@ -265,20 +260,24 @@ namespace QSB.Syncs
base.Update();
}
private Vector3 SmartSmoothDamp(Vector3 currentPosition, Vector3 targetPosition)
private void Interpolate()
{
var distance = Vector3.Distance(currentPosition, targetPosition);
if (Mathf.Abs(distance - _previousDistance) > DistanceLeeway)
var distance = Vector3.Distance(SmoothPosition, transform.position);
if (Mathf.Abs(distance - _prevDistance) > DistanceChangeThreshold)
{
_previousDistance = distance;
return targetPosition;
SmoothPosition = transform.position;
SmoothRotation = transform.rotation;
}
else
{
SmoothPosition = Vector3.SmoothDamp(SmoothPosition, transform.position, ref _positionSmoothVelocity, SmoothTime);
SmoothRotation = QuaternionHelper.SmoothDamp(SmoothRotation, transform.rotation, ref _rotationSmoothVelocity, SmoothTime);
}
_previousDistance = distance;
return Vector3.SmoothDamp(currentPosition, targetPosition, ref _positionSmoothVelocity, SmoothTime);
_prevDistance = distance;
}
public void SetReferenceTransform(Transform referenceTransform)
public virtual void SetReferenceTransform(Transform referenceTransform)
{
if (ReferenceTransform == referenceTransform)
{
@ -287,7 +286,7 @@ namespace QSB.Syncs
ReferenceTransform = referenceTransform;
if (!hasAuthority && UseInterpolation)
if (!hasAuthority && UseInterpolation && AttachedTransform)
{
if (IsPlayerObject)
{

View File

@ -6,17 +6,16 @@ namespace QSB.Syncs.Unsectored.Rigidbodies
{
public abstract class UnsectoredRigidbodySync : BaseUnsectoredSync
{
private const float PositionMovedThreshold = 0.05f;
private const float AngleRotatedThreshold = 0.05f;
private const float VelocityChangeThreshold = 0.05f;
private const float AngVelocityChangeThreshold = 0.05f;
private const float AngularVelocityChangeThreshold = 0.05f;
protected Vector3 _relativeVelocity;
protected Vector3 _relativeAngularVelocity;
protected Vector3 Velocity;
protected Vector3 AngularVelocity;
private Vector3 _prevVelocity;
private Vector3 _prevAngularVelocity;
protected OWRigidbody AttachedRigidbody { get; private set; }
public OWRigidbody AttachedRigidbody { get; private set; }
public OWRigidbody ReferenceRigidbody { get; private set; }
protected abstract OWRigidbody InitAttachedRigidbody();
@ -26,33 +25,44 @@ namespace QSB.Syncs.Unsectored.Rigidbodies
return AttachedRigidbody ? AttachedRigidbody.transform : null;
}
public override void SetReferenceTransform(Transform referenceTransform)
{
if (ReferenceTransform == referenceTransform)
{
return;
}
base.SetReferenceTransform(referenceTransform);
ReferenceRigidbody = ReferenceTransform ? ReferenceTransform.GetAttachedOWRigidbody() : null;
}
protected override void UpdatePrevData()
{
base.UpdatePrevData();
_prevVelocity = _relativeVelocity;
_prevAngularVelocity = _relativeAngularVelocity;
_prevVelocity = Velocity;
_prevAngularVelocity = AngularVelocity;
}
protected override void Serialize(NetworkWriter writer)
{
base.Serialize(writer);
writer.Write(_relativeVelocity);
writer.Write(_relativeAngularVelocity);
writer.Write(Velocity);
writer.Write(AngularVelocity);
}
protected override void Deserialize(NetworkReader reader)
{
base.Deserialize(reader);
_relativeVelocity = reader.ReadVector3();
_relativeAngularVelocity = reader.ReadVector3();
Velocity = reader.ReadVector3();
AngularVelocity = reader.ReadVector3();
}
protected override void GetFromAttached()
{
transform.position = ReferenceTransform.ToRelPos(AttachedRigidbody.GetPosition());
transform.rotation = ReferenceTransform.ToRelRot(AttachedRigidbody.GetRotation());
_relativeVelocity = ReferenceTransform.GetAttachedOWRigidbody().ToRelVel(AttachedRigidbody.GetVelocity(), AttachedRigidbody.GetPosition());
_relativeAngularVelocity = ReferenceTransform.GetAttachedOWRigidbody().ToRelAngVel(AttachedRigidbody.GetAngularVelocity());
Velocity = ReferenceRigidbody.ToRelVel(AttachedRigidbody.GetVelocity(), AttachedRigidbody.GetPosition());
AngularVelocity = ReferenceRigidbody.ToRelAngVel(AttachedRigidbody.GetAngularVelocity());
}
protected override void ApplyToAttached()
@ -72,36 +82,16 @@ namespace QSB.Syncs.Unsectored.Rigidbodies
AttachedRigidbody.MoveToPosition(positionToSet);
AttachedRigidbody.MoveToRotation(rotationToSet);
var targetVelocity = ReferenceTransform.GetAttachedOWRigidbody().FromRelVel(_relativeVelocity, targetPos);
var targetAngularVelocity = ReferenceTransform.GetAttachedOWRigidbody().FromRelAngVel(_relativeAngularVelocity);
var targetVelocity = ReferenceRigidbody.FromRelVel(Velocity, targetPos);
var targetAngularVelocity = ReferenceRigidbody.FromRelAngVel(AngularVelocity);
AttachedRigidbody.SetVelocity(targetVelocity);
AttachedRigidbody.SetAngularVelocity(targetAngularVelocity);
}
protected override bool HasChanged()
{
if (Vector3.Distance(transform.position, _prevPosition) > PositionMovedThreshold)
{
return true;
}
if (Quaternion.Angle(transform.rotation, _prevRotation) > AngleRotatedThreshold)
{
return true;
}
if (Vector3.Distance(_relativeVelocity, _prevVelocity) > VelocityChangeThreshold)
{
return true;
}
if (Vector3.Distance(_relativeAngularVelocity, _prevAngularVelocity) > AngVelocityChangeThreshold)
{
return true;
}
return false;
}
protected override bool HasChanged() =>
base.HasChanged() ||
Vector3.Distance(Velocity, _prevVelocity) > VelocityChangeThreshold ||
Vector3.Distance(AngularVelocity, _prevAngularVelocity) > AngularVelocityChangeThreshold;
}
}

View File

@ -16,16 +16,13 @@ namespace QSB.Tools.ProbeLauncherTool.WorldObjects
public override void SendInitialState(uint to)
{
if (QSBCore.IsHost)
if (AttachedObject._preLaunchProbeProxy.activeSelf)
{
if (AttachedObject._preLaunchProbeProxy.activeSelf)
{
this.SendMessage(new RetrieveProbeMessage(false));
}
else
{
this.SendMessage(new LaunchProbeMessage(false));
}
this.SendMessage(new RetrieveProbeMessage(false));
}
else
{
this.SendMessage(new LaunchProbeMessage(false));
}
}

View File

@ -1,5 +1,4 @@
using OWML.Common;
using QSB.SectorSync;
using QSB.Syncs.Sectored.Transforms;
using QSB.Tools.ProbeLauncherTool;
using QSB.Utility;
@ -15,7 +14,7 @@ namespace QSB.Tools.ProbeTool.TransformSync
/// </summary>
protected override bool CheckValid() => AttachedTransform && base.CheckValid();
protected override float DistanceLeeway => 10f;
protected override float DistanceChangeThreshold => 10f;
protected override bool UseInterpolation => true;
protected override bool AllowInactiveAttachedObject => true;
protected override bool IsPlayerObject => true;
@ -26,7 +25,7 @@ namespace QSB.Tools.ProbeTool.TransformSync
protected override Transform InitLocalTransform()
{
SectorDetector.Init(Locator.GetProbe().GetSectorDetector(), TargetType.Probe);
SectorDetector.Init(Locator.GetProbe().GetSectorDetector());
var body = Locator.GetProbe().transform;
Player.ProbeBody = body.gameObject;

View File

@ -10,14 +10,9 @@ namespace QSB.Tools.TranslatorTool.TranslationSync.WorldObjects
{
internal class QSBNomaiText : WorldObject<NomaiText>
{
public override void SendInitialState(uint to)
{
if (QSBCore.IsHost)
{
GetTranslatedIds().ForEach(id =>
this.SendMessage(new SetAsTranslatedMessage(id) { To = to }));
}
}
public override void SendInitialState(uint to) =>
GetTranslatedIds().ForEach(id =>
this.SendMessage(new SetAsTranslatedMessage(id) { To = to }));
public void SetAsTranslated(int id) => AttachedObject.SetAsTranslated(id);

View File

@ -6,13 +6,8 @@ namespace QSB.TornadoSync.WorldObjects
{
public class QSBTornado : WorldObject<TornadoController>
{
public override void SendInitialState(uint to)
{
if (QSBCore.IsHost)
{
this.SendMessage(new TornadoFormStateMessage(FormState) { To = to });
}
}
public override void SendInitialState(uint to) =>
this.SendMessage(new TornadoFormStateMessage(FormState) { To = to });
public bool FormState
{

View File

@ -52,13 +52,8 @@ namespace QSB.TriggerSync.WorldObjects
QSBPlayerManager.OnRemovePlayer -= OnPlayerLeave;
}
public override void SendInitialState(uint to)
{
if (QSBCore.IsHost)
{
((IQSBTrigger)this).SendMessage(new TriggerInitialStateMessage(Occupants) { To = to });
}
}
public override void SendInitialState(uint to) =>
((IQSBTrigger)this).SendMessage(new TriggerInitialStateMessage(Occupants) { To = to });
protected void OnEnterEvent(GameObject hitObj)
{

View File

@ -99,16 +99,28 @@ namespace QSB.Utility
public static TSource MinBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
var comparer = Comparer<TKey>.Default;
var y = default(TSource);
var yk = default(TKey);
var y = default(TSource);
var hasValue = false;
foreach (var x in source)
{
var xk = keySelector(x);
if (xk != null && (yk == null || comparer.Compare(xk, yk) < 0))
if (!hasValue)
{
y = x;
hasValue = true;
yk = xk;
y = x;
}
else if (comparer.Compare(xk, yk) < 0)
{
yk = xk;
y = x;
}
}
if (!hasValue)
{
throw new InvalidOperationException("Sequence contains no elements");
}
return y;
@ -117,17 +129,30 @@ namespace QSB.Utility
public static TSource MaxBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
var comparer = Comparer<TKey>.Default;
var y = default(TSource);
var yk = default(TKey);
var y = default(TSource);
var hasValue = false;
foreach (var x in source)
{
var xk = keySelector(x);
if (xk != null && (yk == null || comparer.Compare(xk, yk) > 0))
if (!hasValue)
{
hasValue = true;
yk = xk;
y = x;
}
else if (comparer.Compare(xk, yk) > 0)
{
yk = xk;
y = x;
}
}
if (!hasValue)
{
throw new InvalidOperationException("Sequence contains no elements");
}
return y;
}

View File

@ -9,6 +9,7 @@ namespace QSB.Utility
protected virtual bool UseReliableRpc => false;
private double _lastSendTime;
private byte[] _lastKnownData;
protected abstract bool HasChanged();
protected abstract void UpdatePrevData();
@ -22,11 +23,6 @@ namespace QSB.Utility
return;
}
if (!NetworkClient.ready)
{
return;
}
if (NetworkTime.localTime >= _lastSendTime + SendInterval)
{
_lastSendTime = NetworkTime.localTime;
@ -49,29 +45,24 @@ namespace QSB.Utility
{
CmdSendDataUnreliable(data);
}
if (QSBCore.IsHost)
{
_lastKnownData ??= new byte[data.Count];
Array.Copy(data.Array!, data.Offset, _lastKnownData, 0, data.Count);
}
}
}
public void SendInitialState(uint to)
/// <summary>
/// called on the host to send the last known data to a new client
/// </summary>
public void SendInitialState(NetworkConnectionToClient target)
{
if (!hasAuthority)
if (_lastKnownData != null)
{
return;
TargetSendInitialData(target, new ArraySegment<byte>(_lastKnownData));
}
if (!NetworkClient.ready)
{
return;
}
_lastSendTime = NetworkTime.localTime;
using var writer = NetworkWriterPool.GetWriter();
Serialize(writer);
UpdatePrevData();
var data = writer.ToArraySegment();
CmdSendInitialData(to, data);
}
[Command(channel = Channels.Reliable, requiresAuthority = true)]
@ -86,14 +77,17 @@ namespace QSB.Utility
[ClientRpc(channel = Channels.Unreliable, includeOwner = false)]
private void RpcSendDataUnreliable(ArraySegment<byte> data) => OnData(data);
[Command(channel = Channels.Reliable, requiresAuthority = true)]
private void CmdSendInitialData(uint to, ArraySegment<byte> data) => TargetSendInitialData(to.GetNetworkConnection(), data);
[TargetRpc(channel = Channels.Reliable)]
private void TargetSendInitialData(NetworkConnection target, ArraySegment<byte> data) => OnData(data);
private void OnData(ArraySegment<byte> data)
{
if (QSBCore.IsHost)
{
_lastKnownData ??= new byte[data.Count];
Array.Copy(data.Array!, data.Offset, _lastKnownData, 0, data.Count);
}
using var reader = NetworkReaderPool.GetReader(data);
UpdatePrevData();
Deserialize(reader);

View File

@ -11,6 +11,7 @@ namespace QSB.Utility
{
return rot;
}
// account for double-cover
var dot = Quaternion.Dot(rot, target);
var multi = dot > 0f ? 1f : -1f;
@ -36,4 +37,4 @@ namespace QSB.Utility
return new Quaternion(result.x, result.y, result.z, result.w);
}
}
}
}

View File

@ -13,6 +13,9 @@ namespace QSB.WorldSync
string ReturnLabel();
void DisplayLines();
/// <summary>
/// called on the host to send over initial state messages
/// </summary>
void SendInitialState(uint to);
}
}

View File

@ -75,10 +75,20 @@ namespace QSB.WorldSync
}
await _managersBuilding.Values;
if (_cts == null)
{
return;
}
AllObjectsAdded = true;
DebugLog.DebugWrite("World Objects added.", MessageType.Success);
await _objectsIniting.Values;
if (_cts == null)
{
return;
}
AllObjectsReady = true;
DebugLog.DebugWrite("World Objects ready.", MessageType.Success);

View File

@ -6,10 +6,12 @@ using QSB.Utility;
namespace QSB.WorldSync
{
/// <summary>
/// sent by non-host clients to get object states
/// sent to the host to get initial object states
/// </summary>
public class RequestInitialStatesMessage : QSBMessage
{
public RequestInitialStatesMessage() => To = 0;
public override void OnReceiveRemote() =>
Delay.RunWhen(() => QSBWorldSync.AllObjectsReady,
() => SendInitialStates(From));
@ -18,24 +20,22 @@ namespace QSB.WorldSync
{
DebugLog.DebugWrite($"sending initial states to {to}");
if (QSBCore.IsHost)
{
QSBWorldSync.DialogueConditions.ForEach(condition
=> new DialogueConditionMessage(condition.Key, condition.Value) { To = to }.Send());
QSBWorldSync.DialogueConditions.ForEach(condition
=> new DialogueConditionMessage(condition.Key, condition.Value) { To = to }.Send());
QSBWorldSync.ShipLogFacts.ForEach(fact
=> new RevealFactMessage(fact.Id, fact.SaveGame, false) { To = to }.Send());
QSBWorldSync.ShipLogFacts.ForEach(fact
=> new RevealFactMessage(fact.Id, fact.SaveGame, false) { To = to }.Send());
var target = to.GetNetworkConnection();
foreach (var qsbNetworkBehaviour in QSBWorldSync.GetUnityObjects<QSBNetworkBehaviour>())
{
qsbNetworkBehaviour.SendInitialState(target);
}
foreach (var worldObject in QSBWorldSync.GetWorldObjects())
{
worldObject.SendInitialState(to);
}
foreach (var qsbNetworkBehaviour in QSBWorldSync.GetUnityObjects<QSBNetworkBehaviour>())
{
qsbNetworkBehaviour.SendInitialState(to);
}
}
}
}

View File

@ -9,15 +9,12 @@ namespace QSB.ZeroGCaveSync.WorldObjects
{
public override void SendInitialState(uint to)
{
if (QSBCore.IsHost)
if (!AttachedObject._damaged)
{
if (!AttachedObject._damaged)
{
this.SendMessage(new SatelliteNodeRepairedMessage());
}
this.SendMessage(new SatelliteNodeRepairTickMessage(AttachedObject._repairFraction));
this.SendMessage(new SatelliteNodeRepairedMessage());
}
this.SendMessage(new SatelliteNodeRepairTickMessage(AttachedObject._repairFraction));
}
public void SetRepaired()