Merge pull request #626 from misternebula/dev

0.28.1
This commit is contained in:
_nebula 2023-06-22 20:45:13 +01:00 committed by GitHub
commit 03bcc607fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
71 changed files with 450 additions and 297 deletions

View File

@ -50,11 +50,14 @@ public static class Program
var log = new ConsoleLogger();
var weaver = new Weaver(log);
if (!weaver.Weave(assembly, resolver, out _))
if (!weaver.Weave(assembly, resolver, out var modified))
{
Environment.Exit(1);
}
assembly.Write(new WriterParameters { WriteSymbols = assembly.MainModule.HasSymbols });
if (modified)
{
assembly.Write(new WriterParameters { WriteSymbols = assembly.MainModule.HasSymbols });
}
}
}
}

View File

@ -14,7 +14,7 @@ public static class QSBReaderWriterProcessor
/// traverses from non generic classes up thru base types
/// in order to replace generic parameters with their corresponding generic arguments.
/// </summary>
public static void Process(ModuleDefinition module, Writers writers, Readers readers, ref bool weavingFailed)
public static bool Process(ModuleDefinition module, Writers writers, Readers readers, ref bool weavingFailed)
{
var sw = Stopwatch.StartNew();
@ -85,5 +85,6 @@ public static class QSBReaderWriterProcessor
}
Console.WriteLine($"got/generated {count} read/write funcs in {sw.ElapsedMilliseconds} ms");
return count > 0;
}
}

View File

@ -207,7 +207,7 @@ namespace Mirror.Weaver
Console.WriteLine($"Script Module: {moduleDefinition.Name}");
// CHANGED
QSBReaderWriterProcessor.Process(moduleDefinition, writers, readers, ref WeavingFailed);
modified |= QSBReaderWriterProcessor.Process(moduleDefinition, writers, readers, ref WeavingFailed);
modified |= WeaveModule(moduleDefinition);

View File

@ -1,5 +1,5 @@
using QSB.Anglerfish.WorldObjects;
using QSB.AuthoritySync;
using QSB.OwnershipSync;
using QSB.Syncs.Unsectored.Rigidbodies;
using QSB.Utility.LinkedWorldObject;
using QSB.WorldSync;
@ -22,7 +22,7 @@ public class AnglerTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBehavi
{
if (QSBCore.IsHost)
{
netIdentity.RegisterAuthQueue();
netIdentity.RegisterOwnerQueue();
}
base.OnStartClient();
@ -32,7 +32,7 @@ public class AnglerTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBehavi
{
if (QSBCore.IsHost)
{
netIdentity.UnregisterAuthQueue();
netIdentity.UnregisterOwnerQueue();
}
base.OnStopClient();
@ -48,7 +48,7 @@ public class AnglerTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBehavi
AttachedRigidbody.OnUnsuspendOWRigidbody += OnUnsuspend;
AttachedRigidbody.OnSuspendOWRigidbody += OnSuspend;
netIdentity.UpdateAuthQueue(AttachedRigidbody.IsSuspended() ? AuthQueueAction.Remove : AuthQueueAction.Add);
netIdentity.UpdateOwnerQueue(AttachedRigidbody.IsSuspended() ? OwnerQueueAction.Remove : OwnerQueueAction.Add);
}
protected override void Uninit()
@ -59,8 +59,8 @@ public class AnglerTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBehavi
AttachedRigidbody.OnSuspendOWRigidbody -= OnSuspend;
}
private void OnUnsuspend(OWRigidbody suspendedBody) => netIdentity.UpdateAuthQueue(AuthQueueAction.Add);
private void OnSuspend(OWRigidbody suspendedBody) => netIdentity.UpdateAuthQueue(AuthQueueAction.Remove);
private void OnUnsuspend(OWRigidbody suspendedBody) => netIdentity.UpdateOwnerQueue(OwnerQueueAction.Add);
private void OnSuspend(OWRigidbody suspendedBody) => netIdentity.UpdateOwnerQueue(OwnerQueueAction.Remove);
protected override void OnRenderObject()
{

View File

@ -16,7 +16,7 @@ public class QSBAngler : LinkedWorldObject<AnglerfishController, AnglerTransform
private Vector3 _lastTargetPosition;
protected override GameObject NetworkObjectPrefab => QSBNetworkManager.singleton.AnglerPrefab;
protected override bool SpawnWithServerAuthority => false;
protected override bool SpawnWithServerOwnership => false;
public override void SendInitialState(uint to) =>
this.SendMessage(new AnglerDataMessage(this) { To = to });

View File

@ -103,7 +103,7 @@ public class AnimationSync : PlayerSyncObject
private void InitAccelerationSync()
{
Player.JetpackAcceleration = GetComponent<JetpackAccelerationSync>();
var thrusterModel = hasAuthority ? Locator.GetPlayerBody().GetComponent<ThrusterModel>() : null;
var thrusterModel = isOwned ? Locator.GetPlayerBody().GetComponent<ThrusterModel>() : null;
Player.JetpackAcceleration.Init(thrusterModel);
}

Binary file not shown.

View File

@ -1,93 +0,0 @@
using Mirror;
using QSB.Messaging;
using QSB.Utility;
using System.Collections.Generic;
namespace QSB.AuthoritySync;
public static class AuthorityManager
{
#region host only
/// <summary>
/// whoever is first gets authority
/// </summary>
private static readonly Dictionary<NetworkIdentity, List<uint>> _authQueue = new();
public static void RegisterAuthQueue(this NetworkIdentity identity) => _authQueue.Add(identity, new List<uint>());
public static void UnregisterAuthQueue(this NetworkIdentity identity) => _authQueue.Remove(identity);
public static void ServerUpdateAuthQueue(this NetworkIdentity identity, uint id, AuthQueueAction action)
{
var authQueue = _authQueue[identity];
var oldOwner = authQueue.Count != 0 ? authQueue[0] : uint.MaxValue;
switch (action)
{
case AuthQueueAction.Add:
authQueue.SafeAdd(id);
break;
case AuthQueueAction.Remove:
authQueue.Remove(id);
break;
case AuthQueueAction.Force:
authQueue.Remove(id);
authQueue.Insert(0, id);
break;
}
var newOwner = authQueue.Count != 0 ? authQueue[0] : uint.MaxValue;
if (oldOwner != newOwner)
{
SetAuthority(identity, newOwner);
}
}
/// <summary>
/// transfer authority to a different client
/// </summary>
public static void OnDisconnect(NetworkConnectionToClient conn)
{
var id = conn.GetPlayerId();
foreach (var identity in _authQueue.Keys)
{
identity.ServerUpdateAuthQueue(id, AuthQueueAction.Remove);
}
}
public static void SetAuthority(this NetworkIdentity identity, uint id)
{
var oldConn = identity.connectionToClient;
var newConn = id != uint.MaxValue ? id.GetNetworkConnection() : null;
if (oldConn == newConn)
{
return;
}
identity.RemoveClientAuthority();
if (newConn != null)
{
identity.AssignClientAuthority(newConn);
}
}
#endregion
#region any client
public static void UpdateAuthQueue(this NetworkIdentity identity, AuthQueueAction action)
{
if (action == AuthQueueAction.Force && identity.hasAuthority)
{
return;
}
new AuthQueueMessage(identity.netId, action).Send();
}
#endregion
}

View File

@ -1,32 +0,0 @@
using QSB.Messaging;
using QSB.Player;
namespace QSB.AuthoritySync;
public static class IAuthWorldObject_Extensions
{
/// <summary>
/// try and gain authority over the object
/// </summary>
public static void RequestOwnership(this IAuthWorldObject @this)
{
if (@this.Owner != 0)
{
return;
}
@this.SendMessage(new AuthWorldObjectMessage(QSBPlayerManager.LocalPlayerId));
}
/// <summary>
/// release authority over the object,
/// potentially to giving it to someone else
/// </summary>
public static void ReleaseOwnership(this IAuthWorldObject @this)
{
if (@this.Owner != QSBPlayerManager.LocalPlayerId)
{
return;
}
@this.SendMessage(new AuthWorldObjectMessage(0));
}
}

View File

@ -1,8 +1,8 @@
using HarmonyLib;
using QSB.AuthoritySync;
using QSB.EchoesOfTheEye.AlarmTotemSync.Messages;
using QSB.EchoesOfTheEye.AlarmTotemSync.WorldObjects;
using QSB.Messaging;
using QSB.OwnershipSync;
using QSB.Patches;
using QSB.Player;
using QSB.Utility;

View File

@ -1,10 +1,10 @@
using QSB.AuthoritySync;
using QSB.EchoesOfTheEye.AlarmTotemSync.Messages;
using QSB.EchoesOfTheEye.AlarmTotemSync.Messages;
using QSB.Messaging;
using QSB.OwnershipSync;
namespace QSB.EchoesOfTheEye.AlarmTotemSync.WorldObjects;
public class QSBAlarmTotem : AuthWorldObject<AlarmTotem>
public class QSBAlarmTotem : OwnedWorldObject<AlarmTotem>
{
public override bool CanOwn => AttachedObject.enabled;

View File

@ -1,10 +1,10 @@
using HarmonyLib;
using QSB.AuthoritySync;
using QSB.EchoesOfTheEye.DreamCandles.Patches;
using QSB.EchoesOfTheEye.DreamObjectProjectors.WorldObject;
using QSB.EchoesOfTheEye.DreamRafts.Messages;
using QSB.EchoesOfTheEye.DreamRafts.WorldObjects;
using QSB.Messaging;
using QSB.OwnershipSync;
using QSB.Patches;
using QSB.WorldSync;
@ -75,10 +75,10 @@ public class DreamRaftPatches : QSBPatch
if (__instance._lastUsedRaftProjector)
{
// still release authority over the raft tho
// still release ownership over the raft tho
__instance._lastUsedRaftProjector
._dreamRaftProjection.GetComponent<DreamRaftController>().GetWorldObject<QSBDreamRaft>()
.NetworkBehaviour.netIdentity.UpdateAuthQueue(AuthQueueAction.Remove);
.NetworkBehaviour.netIdentity.UpdateOwnerQueue(OwnerQueueAction.Remove);
}
return false;

View File

@ -7,5 +7,5 @@ namespace QSB.EchoesOfTheEye.DreamRafts.WorldObjects;
public class QSBDreamRaft : LinkedWorldObject<DreamRaftController, RaftTransformSync>
{
protected override GameObject NetworkObjectPrefab => QSBNetworkManager.singleton.RaftPrefab;
protected override bool SpawnWithServerAuthority => false;
protected override bool SpawnWithServerOwnership => false;
}

View File

@ -7,5 +7,5 @@ namespace QSB.EchoesOfTheEye.DreamRafts.WorldObjects;
public class QSBSealRaft : LinkedWorldObject<SealRaftController, RaftTransformSync>
{
protected override GameObject NetworkObjectPrefab => QSBNetworkManager.singleton.RaftPrefab;
protected override bool SpawnWithServerAuthority => false;
protected override bool SpawnWithServerOwnership => false;
}

View File

@ -10,7 +10,7 @@ internal class QSBEclipseDoorController : QSBRotatingElements<EclipseDoorControl
protected override IEnumerable<SingleLightSensor> LightSensors => AttachedObject._lightSensors;
public override string ReturnLabel()
=> $"{base.ReturnLabel()}\r\n- SyncerValue:{NetworkBehaviour.Value?.Join()}\r\n- HasAuth:{NetworkBehaviour.hasAuthority}";
=> $"{base.ReturnLabel()}\r\n- SyncerValue:{NetworkBehaviour.Value?.Join()}\r\n- IsOwned:{NetworkBehaviour.isOwned}";
protected override GameObject NetworkObjectPrefab => QSBNetworkManager.singleton.DoorPrefab;
}

View File

@ -10,7 +10,7 @@ internal class QSBEclipseElevatorController : QSBRotatingElements<EclipseElevato
protected override IEnumerable<SingleLightSensor> LightSensors => AttachedObject._lightSensors;
public override string ReturnLabel()
=> $"{base.ReturnLabel()}\r\n- SyncerValue:{NetworkBehaviour.Value?.Join()}\r\n- HasAuth:{NetworkBehaviour.hasAuthority}";
=> $"{base.ReturnLabel()}\r\n- SyncerValue:{NetworkBehaviour.Value?.Join()}\r\n- IsOwned:{NetworkBehaviour.isOwned}";
protected override GameObject NetworkObjectPrefab => QSBNetworkManager.singleton.ElevatorPrefab;
}

View File

@ -1,8 +1,8 @@
using HarmonyLib;
using QSB.AuthoritySync;
using QSB.EchoesOfTheEye.LightSensorSync.Messages;
using QSB.EchoesOfTheEye.LightSensorSync.WorldObjects;
using QSB.Messaging;
using QSB.OwnershipSync;
using QSB.Patches;
using QSB.Player;
using QSB.Tools.FlashlightTool;

View File

@ -16,7 +16,7 @@ namespace QSB.EchoesOfTheEye.LightSensorSync;
/// only purpose is to handle initial state sync.
///
/// we don't have to worry about start illuminated or sectors.
/// authority is always given to local player light sensor.
/// ownership is always given to local player light sensor.
///
/// 2 uses:
/// - AlarmTotem.CheckPlayerVisible

View File

@ -1,7 +1,7 @@
using Cysharp.Threading.Tasks;
using QSB.AuthoritySync;
using QSB.EchoesOfTheEye.LightSensorSync.Messages;
using QSB.Messaging;
using QSB.OwnershipSync;
using QSB.Utility;
using QSB.WorldSync;
using System;
@ -14,7 +14,7 @@ using System.Threading;
namespace QSB.EchoesOfTheEye.LightSensorSync.WorldObjects;
internal class QSBLightSensor : AuthWorldObject<SingleLightSensor>
internal class QSBLightSensor : OwnedWorldObject<SingleLightSensor>
{
internal bool _locallyIlluminated;

View File

@ -1,7 +1,7 @@
using Cysharp.Threading.Tasks;
using Mirror;
using QSB.AuthoritySync;
using QSB.EchoesOfTheEye.LightSensorSync.WorldObjects;
using QSB.OwnershipSync;
using QSB.Utility.LinkedWorldObject;
using QSB.WorldSync;
using System.Collections.Generic;
@ -52,7 +52,7 @@ internal abstract class QSBRotatingElements<T, U> : LinkedWorldObject<T, U>
_litSensors++;
if (_litSensors == 1)
{
NetworkBehaviour.netIdentity.UpdateAuthQueue(AuthQueueAction.Add);
NetworkBehaviour.netIdentity.UpdateOwnerQueue(OwnerQueueAction.Add);
}
}
@ -61,9 +61,9 @@ internal abstract class QSBRotatingElements<T, U> : LinkedWorldObject<T, U>
_litSensors--;
if (_litSensors == 0)
{
NetworkBehaviour.netIdentity.UpdateAuthQueue(AuthQueueAction.Remove);
NetworkBehaviour.netIdentity.UpdateOwnerQueue(OwnerQueueAction.Remove);
}
}
protected override bool SpawnWithServerAuthority => false;
protected override bool SpawnWithServerOwnership => false;
}

View File

@ -1,8 +1,8 @@
using HarmonyLib;
using QSB.AuthoritySync;
using QSB.EchoesOfTheEye.RaftSync.Messages;
using QSB.EchoesOfTheEye.RaftSync.WorldObjects;
using QSB.Messaging;
using QSB.OwnershipSync;
using QSB.Patches;
using QSB.Utility;
using QSB.WorldSync;
@ -21,8 +21,8 @@ public class RaftPatches : QSBPatch
__instance._interactReceiver.SetInteractionEnabled(false);
var qsbRaft = __instance.GetWorldObject<QSBRaft>();
qsbRaft.NetworkBehaviour.netIdentity.UpdateAuthQueue(AuthQueueAction.Force);
Delay.RunWhen(() => qsbRaft.NetworkBehaviour.hasAuthority, () =>
qsbRaft.NetworkBehaviour.netIdentity.UpdateOwnerQueue(OwnerQueueAction.Force);
Delay.RunWhen(() => qsbRaft.NetworkBehaviour.isOwned, () =>
{
var normalized = Vector3.ProjectOnPlane(Locator.GetPlayerCamera().transform.forward, __instance.transform.up).normalized;
__instance._raftBody.AddVelocityChange(normalized * 5f);

View File

@ -1,4 +1,4 @@
using QSB.AuthoritySync;
using QSB.OwnershipSync;
using QSB.Syncs.Unsectored.Rigidbodies;
using QSB.Utility;
using QSB.Utility.LinkedWorldObject;
@ -33,7 +33,7 @@ public class RaftTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBehaviou
{
if (QSBCore.IsHost)
{
netIdentity.RegisterAuthQueue();
netIdentity.RegisterOwnerQueue();
}
base.OnStartClient();
@ -43,7 +43,7 @@ public class RaftTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBehaviou
{
if (QSBCore.IsHost)
{
netIdentity.UnregisterAuthQueue();
netIdentity.UnregisterOwnerQueue();
}
base.OnStopClient();
@ -56,7 +56,7 @@ public class RaftTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBehaviou
AttachedRigidbody.OnUnsuspendOWRigidbody += OnUnsuspend;
AttachedRigidbody.OnSuspendOWRigidbody += OnSuspend;
netIdentity.UpdateAuthQueue(AttachedRigidbody.IsSuspended() ? AuthQueueAction.Remove : AuthQueueAction.Add);
netIdentity.UpdateOwnerQueue(AttachedRigidbody.IsSuspended() ? OwnerQueueAction.Remove : OwnerQueueAction.Add);
}
protected override void Uninit()
@ -67,12 +67,12 @@ public class RaftTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBehaviou
AttachedRigidbody.OnSuspendOWRigidbody -= OnSuspend;
}
private void OnUnsuspend(OWRigidbody suspendedBody) => netIdentity.UpdateAuthQueue(AuthQueueAction.Add);
private void OnSuspend(OWRigidbody suspendedBody) => netIdentity.UpdateAuthQueue(AuthQueueAction.Remove);
private void OnUnsuspend(OWRigidbody suspendedBody) => netIdentity.UpdateOwnerQueue(OwnerQueueAction.Add);
private void OnSuspend(OWRigidbody suspendedBody) => netIdentity.UpdateOwnerQueue(OwnerQueueAction.Remove);
public override void OnStartAuthority() => DebugLog.DebugWrite($"{this} + AUTH");
public override void OnStopAuthority() => DebugLog.DebugWrite($"{this} - AUTH");
public override void OnStartAuthority() => DebugLog.DebugWrite($"{this} + OWN");
public override void OnStopAuthority() => DebugLog.DebugWrite($"{this} - OWN");
/// <summary>
/// replacement for base method

View File

@ -1,8 +1,8 @@
using Cysharp.Threading.Tasks;
using QSB.AuthoritySync;
using QSB.EchoesOfTheEye.LightSensorSync.WorldObjects;
using QSB.EchoesOfTheEye.RaftSync.TransformSync;
using QSB.ItemSync.WorldObjects;
using QSB.OwnershipSync;
using QSB.Utility.LinkedWorldObject;
using QSB.WorldSync;
using System.Linq;
@ -18,7 +18,7 @@ public class QSBRaft : LinkedWorldObject<RaftController, RaftTransformSync>, IQS
public override bool ShouldDisplayDebug() => false;
protected override GameObject NetworkObjectPrefab => QSBNetworkManager.singleton.RaftPrefab;
protected override bool SpawnWithServerAuthority => false;
protected override bool SpawnWithServerOwnership => false;
private QSBLightSensor[] _lightSensors;
@ -49,7 +49,7 @@ public class QSBRaft : LinkedWorldObject<RaftController, RaftTransformSync>, IQS
{
if (AttachedObject.IsPlayerRiding())
{
NetworkBehaviour.netIdentity.UpdateAuthQueue(AuthQueueAction.Force);
NetworkBehaviour.netIdentity.UpdateOwnerQueue(OwnerQueueAction.Force);
}
}
}

View File

@ -1,5 +1,5 @@
using Mirror;
using QSB.AuthoritySync;
using QSB.OwnershipSync;
using QSB.Utility.LinkedWorldObject;
using QSB.Utility.VariableSync;
using QSB.WorldSync;
@ -15,7 +15,7 @@ internal abstract class RotatingElementsVariableSyncer<TWorldObject> : BaseVaria
{
if (QSBCore.IsHost)
{
netIdentity.RegisterAuthQueue();
netIdentity.RegisterOwnerQueue();
}
base.OnStartClient();
@ -25,7 +25,7 @@ internal abstract class RotatingElementsVariableSyncer<TWorldObject> : BaseVaria
{
if (QSBCore.IsHost)
{
netIdentity.UnregisterAuthQueue();
netIdentity.UnregisterOwnerQueue();
}
base.OnStopClient();

View File

@ -67,11 +67,14 @@ internal class MultiplayerHUDManager : MonoBehaviour, IAddComponentOnStart
private const int LINE_COUNT = 11;
private const int CHAR_COUNT = 41;
private const float FADE_DELAY = 5f;
private const float FADE_TIME = 2f;
private bool _writingMessage;
private readonly string[] _lines = new string[LINE_COUNT];
// this should really be a deque, but eh
private readonly ListStack<string> _messages = new(false);
private float _lastMessageTime;
public void WriteMessage(string message)
{
@ -85,6 +88,8 @@ internal class MultiplayerHUDManager : MonoBehaviour, IAddComponentOnStart
* and set the lines correctly bottom-up.
*/
_lastMessageTime = Time.time;
_messages.Push(message);
if (_messages.Count > LINE_COUNT)
@ -145,6 +150,8 @@ internal class MultiplayerHUDManager : MonoBehaviour, IAddComponentOnStart
audioController.PlayNotificationTextScrolling();
Delay.RunFramesLater(10, () => audioController.StopNotificationTextScrolling());
}
_textChat.GetComponent<CanvasGroup>().alpha = 1;
}
private void Update()
@ -158,11 +165,12 @@ internal class MultiplayerHUDManager : MonoBehaviour, IAddComponentOnStart
var inSuit = Locator.GetPlayerSuit().IsWearingHelmet();
if (OWInput.IsNewlyPressed(InputLibrary.enter, InputMode.Character) && !_writingMessage && inSuit)
if (OWInput.IsNewlyPressed(InputLibrary.enter, InputMode.Character) && !_writingMessage && inSuit && QSBCore.TextChatInput)
{
OWInput.ChangeInputMode(InputMode.KeyboardInput);
_writingMessage = true;
_inputField.ActivateInputField();
_textChat.GetComponent<CanvasGroup>().alpha = 1;
}
if (OWInput.IsNewlyPressed(InputLibrary.enter, InputMode.KeyboardInput) && _writingMessage)
@ -183,6 +191,20 @@ internal class MultiplayerHUDManager : MonoBehaviour, IAddComponentOnStart
OWInput.RestorePreviousInputs();
_writingMessage = false;
}
if (_writingMessage)
{
_lastMessageTime = Time.time;
}
if (!_writingMessage
&& Time.time > _lastMessageTime + FADE_DELAY
&& Time.time < _lastMessageTime + FADE_DELAY + FADE_TIME + 1)
{
var difference = Time.time - (_lastMessageTime + FADE_DELAY);
var alpha = Mathf.Lerp(1, 0, difference / FADE_TIME);
_textChat.GetComponent<CanvasGroup>().alpha = alpha;
}
}
private void OnWakeUp()
@ -243,6 +265,7 @@ internal class MultiplayerHUDManager : MonoBehaviour, IAddComponentOnStart
_textChat.Find("Messages").Find("Message").GetComponent<Text>().text = "";
_lines.Clear();
_messages.Clear();
_textChat.GetComponent<CanvasGroup>().alpha = 0;
}
public void UpdateMinimapMarkers(Minimap minimap)

View File

@ -28,7 +28,9 @@ public class PlayerBox : MonoBehaviour
if (player.Name != null)
{
PlayerName.text = player.Name.ToUpper();
Delay.RunWhen(
() => player.Name != null,
() => PlayerName.text = player.Name.ToUpper());
}
InfoImage.sprite = MultiplayerHUDManager.UnknownSprite;

View File

@ -1,6 +1,6 @@
using Mirror;
using QSB.AuthoritySync;
using QSB.JellyfishSync.WorldObjects;
using QSB.OwnershipSync;
using QSB.Syncs.Unsectored.Rigidbodies;
using QSB.Utility;
using QSB.Utility.LinkedWorldObject;
@ -24,7 +24,7 @@ public class JellyfishTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBeh
{
if (QSBCore.IsHost)
{
netIdentity.RegisterAuthQueue();
netIdentity.RegisterOwnerQueue();
}
base.OnStartClient();
@ -34,7 +34,7 @@ public class JellyfishTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBeh
{
if (QSBCore.IsHost)
{
netIdentity.UnregisterAuthQueue();
netIdentity.UnregisterOwnerQueue();
}
base.OnStopClient();
@ -50,7 +50,7 @@ public class JellyfishTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBeh
AttachedRigidbody.OnUnsuspendOWRigidbody += OnUnsuspend;
AttachedRigidbody.OnSuspendOWRigidbody += OnSuspend;
netIdentity.UpdateAuthQueue(AttachedRigidbody.IsSuspended() ? AuthQueueAction.Remove : AuthQueueAction.Add);
netIdentity.UpdateOwnerQueue(AttachedRigidbody.IsSuspended() ? OwnerQueueAction.Remove : OwnerQueueAction.Add);
}
protected override void Uninit()
@ -61,8 +61,8 @@ public class JellyfishTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBeh
AttachedRigidbody.OnSuspendOWRigidbody -= OnSuspend;
}
private void OnUnsuspend(OWRigidbody suspendedBody) => netIdentity.UpdateAuthQueue(AuthQueueAction.Add);
private void OnSuspend(OWRigidbody suspendedBody) => netIdentity.UpdateAuthQueue(AuthQueueAction.Remove);
private void OnUnsuspend(OWRigidbody suspendedBody) => netIdentity.UpdateOwnerQueue(OwnerQueueAction.Add);
private void OnSuspend(OWRigidbody suspendedBody) => netIdentity.UpdateOwnerQueue(OwnerQueueAction.Remove);
protected override void Serialize(NetworkWriter writer)
{

View File

@ -11,7 +11,7 @@ public class QSBJellyfish : LinkedWorldObject<JellyfishController, JellyfishTran
public override bool ShouldDisplayDebug() => false;
protected override GameObject NetworkObjectPrefab => QSBNetworkManager.singleton.JellyfishPrefab;
protected override bool SpawnWithServerAuthority => false;
protected override bool SpawnWithServerOwnership => false;
public override void SendInitialState(uint to) =>
this.SendMessage(new JellyfishRisingMessage(AttachedObject._isRising) { To = to });

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using Mirror;
using System.Collections.Generic;
namespace QSB.Localization;
@ -28,6 +29,7 @@ public class Translation
public string OK;
public string ServerRefusedConnection;
public string ClientDisconnectWithError;
public Dictionary<TransportError, string> TransportErrors;
public string QSBVersionMismatch;
public string OWVersionMismatch;
public string DLCMismatch;

View File

@ -736,7 +736,7 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
}
};
OpenInfoPopup(string.Format(QSBLocalization.Current.ClientDisconnectWithError, reason), QSBLocalization.Current.OK);
OpenInfoPopup(string.Format(QSBLocalization.Current.ClientDisconnectWithError, QSBLocalization.Current.TransportErrors[error], reason), QSBLocalization.Current.OK);
}
SetButtonActive(DisconnectButton, false);

View File

@ -1,6 +1,6 @@
using QSB.AuthoritySync;
using QSB.Messaging;
using QSB.Messaging;
using QSB.ModelShip.TransformSync;
using QSB.OwnershipSync;
using QSB.Player;
using QSB.Player.TransformSync;
using QSB.Utility;
@ -66,9 +66,9 @@ internal class UseFlightConsoleMessage : QSBMessage<bool>
if (QSBCore.IsHost)
{
ModelShipTransformSync.LocalInstance.netIdentity.SetAuthority(isFlying
ModelShipTransformSync.LocalInstance.netIdentity.SetOwner(isFlying
? flyer
: QSBPlayerManager.LocalPlayerId); // Host gets authority when its not in use
: QSBPlayerManager.LocalPlayerId); // Host gets ownership when its not in use
}
// Client messes up its position when they start flying it

View File

@ -46,7 +46,7 @@ internal class ModelShipManager : WorldObjectManager
if (QSBCore.IsHost)
{
Instantiate(QSBNetworkManager.singleton.ModelShipPrefab).SpawnWithServerAuthority();
Instantiate(QSBNetworkManager.singleton.ModelShipPrefab).SpawnWithServerOwnership();
}
// Is 0 by default -> 2D (bad)

View File

@ -1,8 +1,8 @@
using HarmonyLib;
using QSB.AuthoritySync;
using QSB.Messaging;
using QSB.OrbSync.Messages;
using QSB.OrbSync.WorldObjects;
using QSB.OwnershipSync;
using QSB.Patches;
using QSB.WorldSync;
using UnityEngine;
@ -48,7 +48,7 @@ public class OrbPatches : QSBPatch
var qsbOrb = __instance.GetWorldObject<QSBOrb>();
qsbOrb.SendMessage(new OrbDragMessage(true));
qsbOrb.NetworkBehaviour.netIdentity.UpdateAuthQueue(AuthQueueAction.Force);
qsbOrb.NetworkBehaviour.netIdentity.UpdateOwnerQueue(OwnerQueueAction.Force);
}
}
else
@ -75,7 +75,7 @@ public class OrbPatches : QSBPatch
}
var qsbOrb = __instance.GetWorldObject<QSBOrb>();
if (!qsbOrb.NetworkBehaviour.hasAuthority)
if (!qsbOrb.NetworkBehaviour.isOwned)
{
return false;
}
@ -95,7 +95,7 @@ public class OrbPatches : QSBPatch
}
var qsbOrb = __instance.GetWorldObject<QSBOrb>();
if (qsbOrb.NetworkBehaviour.hasAuthority)
if (qsbOrb.NetworkBehaviour.isOwned)
{
if (__instance._occupiedSlot == null)
{

View File

@ -1,5 +1,5 @@
using QSB.AuthoritySync;
using QSB.OrbSync.WorldObjects;
using QSB.OrbSync.WorldObjects;
using QSB.OwnershipSync;
using QSB.Syncs.Unsectored.Transforms;
using QSB.Utility.LinkedWorldObject;
using QSB.WorldSync;
@ -28,7 +28,7 @@ public class NomaiOrbTransformSync : UnsectoredTransformSync, ILinkedNetworkBeha
{
if (QSBCore.IsHost)
{
netIdentity.RegisterAuthQueue();
netIdentity.RegisterOwnerQueue();
}
base.OnStartClient();
@ -38,7 +38,7 @@ public class NomaiOrbTransformSync : UnsectoredTransformSync, ILinkedNetworkBeha
{
if (QSBCore.IsHost)
{
netIdentity.UnregisterAuthQueue();
netIdentity.UnregisterOwnerQueue();
}
base.OnStopClient();
@ -52,7 +52,7 @@ public class NomaiOrbTransformSync : UnsectoredTransformSync, ILinkedNetworkBeha
body.OnUnsuspendOWRigidbody += OnUnsuspend;
body.OnSuspendOWRigidbody += OnSuspend;
netIdentity.UpdateAuthQueue(body.IsSuspended() ? AuthQueueAction.Remove : AuthQueueAction.Add);
netIdentity.UpdateOwnerQueue(body.IsSuspended() ? OwnerQueueAction.Remove : OwnerQueueAction.Add);
}
protected override void Uninit()
@ -64,8 +64,8 @@ public class NomaiOrbTransformSync : UnsectoredTransformSync, ILinkedNetworkBeha
body.OnSuspendOWRigidbody -= OnSuspend;
}
private void OnUnsuspend(OWRigidbody suspendedBody) => netIdentity.UpdateAuthQueue(AuthQueueAction.Add);
private void OnSuspend(OWRigidbody suspendedBody) => netIdentity.UpdateAuthQueue(AuthQueueAction.Remove);
private void OnUnsuspend(OWRigidbody suspendedBody) => netIdentity.UpdateOwnerQueue(OwnerQueueAction.Add);
private void OnSuspend(OWRigidbody suspendedBody) => netIdentity.UpdateOwnerQueue(OwnerQueueAction.Remove);
protected override void ApplyToAttached()
{

View File

@ -13,7 +13,7 @@ public class QSBOrb : LinkedWorldObject<NomaiInterfaceOrb, NomaiOrbTransformSync
public override bool ShouldDisplayDebug() => false;
protected override GameObject NetworkObjectPrefab => QSBNetworkManager.singleton.OrbPrefab;
protected override bool SpawnWithServerAuthority => false;
protected override bool SpawnWithServerOwnership => false;
public override void SendInitialState(uint to)
{

View File

@ -1,18 +1,18 @@
using QSB.WorldSync;
namespace QSB.AuthoritySync;
namespace QSB.OwnershipSync;
/// <summary>
/// a world object that has an owner
/// </summary>
public interface IAuthWorldObject : IWorldObject
public interface IOwnedWorldObject : IWorldObject
{
/// <summary>
/// 0 = owned by no one
/// </summary>
public uint Owner { get; set; }
/// <summary>
/// can the world object have authority
/// can the world object be owned by this client
/// </summary>
public bool CanOwn { get; }
}

View File

@ -0,0 +1,32 @@
using QSB.Messaging;
using QSB.Player;
namespace QSB.OwnershipSync;
public static class IOwnedWorldObject_Extensions
{
/// <summary>
/// try and gain ownership over the object
/// </summary>
public static void RequestOwnership(this IOwnedWorldObject @this)
{
if (@this.Owner != 0)
{
return;
}
@this.SendMessage(new OwnedWorldObjectMessage(QSBPlayerManager.LocalPlayerId));
}
/// <summary>
/// release ownership over the object,
/// potentially to giving it to someone else
/// </summary>
public static void ReleaseOwnership(this IOwnedWorldObject @this)
{
if (@this.Owner != QSBPlayerManager.LocalPlayerId)
{
return;
}
@this.SendMessage(new OwnedWorldObjectMessage(0));
}
}

View File

@ -5,19 +5,19 @@ using QSB.WorldSync;
using System.Threading;
using UnityEngine;
namespace QSB.AuthoritySync;
namespace QSB.OwnershipSync;
/// <summary>
/// helper implementation of the interface
/// </summary>
public abstract class AuthWorldObject<T> : WorldObject<T>, IAuthWorldObject
public abstract class OwnedWorldObject<T> : WorldObject<T>, IOwnedWorldObject
where T : MonoBehaviour
{
public uint Owner { get; set; }
public abstract bool CanOwn { get; }
public override void SendInitialState(uint to) =>
((IAuthWorldObject)this).SendMessage(new AuthWorldObjectMessage(Owner) { To = to });
((IOwnedWorldObject)this).SendMessage(new OwnedWorldObjectMessage(Owner) { To = to });
public override async UniTask Init(CancellationToken ct) =>
QSBPlayerManager.OnRemovePlayer += OnPlayerLeave;
@ -33,7 +33,7 @@ public abstract class AuthWorldObject<T> : WorldObject<T>, IAuthWorldObject
}
if (Owner == player.PlayerId)
{
((IAuthWorldObject)this).SendMessage(new AuthWorldObjectMessage(CanOwn ? QSBPlayerManager.LocalPlayerId : 0));
((IOwnedWorldObject)this).SendMessage(new OwnedWorldObjectMessage(CanOwn ? QSBPlayerManager.LocalPlayerId : 0));
}
}
}

View File

@ -1,14 +1,14 @@
using QSB.Messaging;
using QSB.Player;
namespace QSB.AuthoritySync;
namespace QSB.OwnershipSync;
/// <summary>
/// request or release ownership of a world object
/// </summary>
public class AuthWorldObjectMessage : QSBWorldObjectMessage<IAuthWorldObject, uint>
public class OwnedWorldObjectMessage : QSBWorldObjectMessage<IOwnedWorldObject, uint>
{
public AuthWorldObjectMessage(uint owner) : base(owner) { }
public OwnedWorldObjectMessage(uint owner) : base(owner) { }
public override bool ShouldReceive
{
@ -39,7 +39,7 @@ public class AuthWorldObjectMessage : QSBWorldObjectMessage<IAuthWorldObject, ui
if (WorldObject.Owner == 0 && WorldObject.CanOwn)
{
// object has no owner, but is still active for this player. request ownership
WorldObject.SendMessage(new AuthWorldObjectMessage(QSBPlayerManager.LocalPlayerId));
WorldObject.SendMessage(new OwnedWorldObjectMessage(QSBPlayerManager.LocalPlayerId));
}
}
}

View File

@ -2,22 +2,22 @@
using QSB.Messaging;
using QSB.WorldSync;
namespace QSB.AuthoritySync;
namespace QSB.OwnershipSync;
/// <summary>
/// always sent to host
/// </summary>
public class AuthQueueMessage : QSBMessage<(uint NetId, AuthQueueAction Action)>
public class OwnerQueueMessage : QSBMessage<(uint NetId, OwnerQueueAction Action)>
{
public AuthQueueMessage(uint netId, AuthQueueAction action) : base((netId, action)) =>
public OwnerQueueMessage(uint netId, OwnerQueueAction action) : base((netId, action)) =>
To = 0;
public override bool ShouldReceive => QSBWorldSync.AllObjectsReady;
public override void OnReceiveLocal() => OnReceiveRemote();
public override void OnReceiveRemote() => NetworkServer.spawned[Data.NetId].ServerUpdateAuthQueue(From, Data.Action);
public override void OnReceiveRemote() => NetworkServer.spawned[Data.NetId].ServerUpdateOwnerQueue(From, Data.Action);
}
public enum AuthQueueAction
public enum OwnerQueueAction
{
/// <summary>
/// add player to the queue

View File

@ -0,0 +1,93 @@
using Mirror;
using QSB.Messaging;
using QSB.Utility;
using System.Collections.Generic;
namespace QSB.OwnershipSync;
public static class OwnershipManager
{
#region host only
/// <summary>
/// whoever is first gets ownership
/// </summary>
private static readonly Dictionary<NetworkIdentity, List<uint>> _ownerQueue = new();
public static void RegisterOwnerQueue(this NetworkIdentity identity) => _ownerQueue.Add(identity, new List<uint>());
public static void UnregisterOwnerQueue(this NetworkIdentity identity) => _ownerQueue.Remove(identity);
public static void ServerUpdateOwnerQueue(this NetworkIdentity identity, uint id, OwnerQueueAction action)
{
var ownerQueue = _ownerQueue[identity];
var oldOwner = ownerQueue.Count != 0 ? ownerQueue[0] : uint.MaxValue;
switch (action)
{
case OwnerQueueAction.Add:
ownerQueue.SafeAdd(id);
break;
case OwnerQueueAction.Remove:
ownerQueue.Remove(id);
break;
case OwnerQueueAction.Force:
ownerQueue.Remove(id);
ownerQueue.Insert(0, id);
break;
}
var newOwner = ownerQueue.Count != 0 ? ownerQueue[0] : uint.MaxValue;
if (oldOwner != newOwner)
{
SetOwner(identity, newOwner);
}
}
/// <summary>
/// transfer ownership to a different client
/// </summary>
public static void OnDisconnect(NetworkConnectionToClient conn)
{
var id = conn.GetPlayerId();
foreach (var identity in _ownerQueue.Keys)
{
identity.ServerUpdateOwnerQueue(id, OwnerQueueAction.Remove);
}
}
public static void SetOwner(this NetworkIdentity identity, uint id)
{
var oldConn = identity.connectionToClient;
var newConn = id != uint.MaxValue ? id.GetNetworkConnection() : null;
if (oldConn == newConn)
{
return;
}
identity.RemoveClientAuthority();
if (newConn != null)
{
identity.AssignClientAuthority(newConn);
}
}
#endregion
#region any client
public static void UpdateOwnerQueue(this NetworkIdentity identity, OwnerQueueAction action)
{
if (action == OwnerQueueAction.Force && identity.isOwned)
{
return;
}
new OwnerQueueMessage(identity.netId, action).Send();
}
#endregion
}

View File

@ -516,6 +516,9 @@ internal class CustomNomaiRemoteCameraPlatform : NomaiShared
private void SwitchToPlayerCamera()
{
// does nothing except run CCU's prefix
_oldPlatform.SwitchToPlayerCamera();
if (_slavePlatform._visualSector != null)
{
if (!_alreadyOccupiedSectors.Contains(_slavePlatform._visualSector))

View File

@ -28,6 +28,10 @@ internal class PoolPatches : QSBPatch
[HarmonyPatch(typeof(NomaiRemoteCameraPlatform), nameof(NomaiRemoteCameraPlatform.OnPedestalContact))]
public static bool NomaiRemoteCameraPlatform_OnPedestalContact() => false;
[HarmonyPrefix]
[HarmonyPatch(typeof(NomaiRemoteCameraPlatform), nameof(NomaiRemoteCameraPlatform.SwitchToPlayerCamera))]
public static bool NomaiRemoteCameraPlatform_SwitchToPlayerCamera() => false;
[HarmonyPrefix]
[HarmonyPatch(typeof(NomaiRemoteCameraStreaming), nameof(NomaiRemoteCameraStreaming.FixedUpdate))]
public static bool NomaiRemoteCameraStreaming_FixedUpdate() => false;

View File

@ -63,6 +63,7 @@ public class QSBCore : ModBehaviour
public static bool ShowPlayerNames { get; private set; }
public static bool ShipDamage { get; private set; }
public static bool ShowExtraHUDElements { get; private set; }
public static bool TextChatInput { get; private set; }
public static GameVendor GameVendor { get; private set; } = GameVendor.None;
public static bool IsStandalone => GameVendor is GameVendor.Epic or GameVendor.Steam;
public static IProfileManager ProfileManager => IsStandalone
@ -263,6 +264,7 @@ public class QSBCore : ModBehaviour
ShowPlayerNames = config.GetSettingsValue<bool>("showPlayerNames");
ShipDamage = config.GetSettingsValue<bool>("shipDamage");
ShowExtraHUDElements = config.GetSettingsValue<bool>("showExtraHud");
TextChatInput = config.GetSettingsValue<bool>("textChatInput");
if (IsHost)
{

View File

@ -4,7 +4,6 @@ using Mirror;
using OWML.Common;
using OWML.Utils;
using QSB.Anglerfish.TransformSync;
using QSB.AuthoritySync;
using QSB.ClientServerStateSync;
using QSB.DeathSync;
using QSB.EchoesOfTheEye.AirlockSync.VariableSync;
@ -19,6 +18,7 @@ using QSB.ModelShip.TransformSync;
using QSB.OrbSync.Messages;
using QSB.OrbSync.TransformSync;
using QSB.OrbSync.WorldObjects;
using QSB.OwnershipSync;
using QSB.Patches;
using QSB.Player;
using QSB.Player.Messages;
@ -354,27 +354,27 @@ public class QSBNetworkManager : NetworkManager, IAddComponentOnStart
// local conn = we are host, so skip
if (conn is not LocalConnectionToClient)
{
// revert authority from ship
// revert ownership from ship
if (ShipTransformSync.LocalInstance != null)
{
var identity = ShipTransformSync.LocalInstance.netIdentity;
if (identity != null && identity.connectionToClient == conn)
{
identity.SetAuthority(QSBPlayerManager.LocalPlayerId);
identity.SetOwner(QSBPlayerManager.LocalPlayerId);
}
}
// revert authority from model ship
// revert ownership from model ship
if (ModelShipTransformSync.LocalInstance != null)
{
var identity = ModelShipTransformSync.LocalInstance.netIdentity;
if (identity != null && identity.connectionToClient == conn)
{
identity.SetAuthority(QSBPlayerManager.LocalPlayerId);
identity.SetOwner(QSBPlayerManager.LocalPlayerId);
}
}
// stop dragging for the orbs this player was dragging
// i THINK this is here because orb authority is in network behavior, which may not work properly in OnPlayerLeave
// i THINK this is here because orb ownership is in network behavior, which may not work properly in OnPlayerLeave
foreach (var qsbOrb in QSBWorldSync.GetWorldObjects<QSBOrb>())
{
if (qsbOrb.NetworkBehaviour == null)
@ -391,7 +391,7 @@ public class QSBNetworkManager : NetworkManager, IAddComponentOnStart
}
}
AuthorityManager.OnDisconnect(conn);
OwnershipManager.OnDisconnect(conn);
}
base.OnServerDisconnect(conn);

View File

@ -4,9 +4,9 @@ using QSB.QuantumSync.WorldObjects;
namespace QSB.QuantumSync.Messages;
public class QuantumAuthorityMessage : QSBWorldObjectMessage<IQSBQuantumObject, uint>
public class QuantumOwnershipMessage : QSBWorldObjectMessage<IQSBQuantumObject, uint>
{
public QuantumAuthorityMessage(uint authorityOwner) : base(authorityOwner) { }
public QuantumOwnershipMessage(uint owner) : base(owner) { }
public override bool ShouldReceive
{
@ -38,7 +38,7 @@ public class QuantumAuthorityMessage : QSBWorldObjectMessage<IQSBQuantumObject,
if (WorldObject.ControllingPlayer == 00 && WorldObject.IsEnabled)
{
// object has no owner, but is still active for this player. request ownership
WorldObject.SendMessage(new QuantumAuthorityMessage(QSBPlayerManager.LocalPlayerId));
WorldObject.SendMessage(new QuantumOwnershipMessage(QSBPlayerManager.LocalPlayerId));
}
}
}

View File

@ -56,6 +56,7 @@ public class QuantumObjectPatches : QSBPatch
}
var worldObject = __instance.GetWorldObject<IQSBQuantumObject>();
// TODO: this should just be equal to _visibleinprobesnapshot. check if theyre in sync and just go back to using that like we did before
var visibleToProbePlayers = worldObject.GetVisibleToProbePlayers();
__result = visibleToProbePlayers.Any();
return false;

View File

@ -51,7 +51,7 @@ internal class QuantumManager : WorldObjectManager
{
if (obj.ControllingPlayer == player.PlayerId)
{
obj.SendMessage(new QuantumAuthorityMessage(obj.IsEnabled ? QSBPlayerManager.LocalPlayerId : 0u));
obj.SendMessage(new QuantumOwnershipMessage(obj.IsEnabled ? QSBPlayerManager.LocalPlayerId : 0u));
}
}
}

View File

@ -88,7 +88,7 @@ internal abstract class QSBQuantumObject<T> : WorldObject<T>, IQSBQuantumObject
}
public override void SendInitialState(uint to) =>
((IQSBQuantumObject)this).SendMessage(new QuantumAuthorityMessage(ControllingPlayer) { To = to });
((IQSBQuantumObject)this).SendMessage(new QuantumOwnershipMessage(ControllingPlayer) { To = to });
public List<Shape> GetAttachedShapes()
{
@ -149,8 +149,8 @@ internal abstract class QSBQuantumObject<T> : WorldObject<T>, IQSBQuantumObject
return;
}
// no one is controlling this object right now, request authority
((IQSBQuantumObject)this).SendMessage(new QuantumAuthorityMessage(QSBPlayerManager.LocalPlayerId));
// no one is controlling this object right now, request ownership
((IQSBQuantumObject)this).SendMessage(new QuantumOwnershipMessage(QSBPlayerManager.LocalPlayerId));
}
private void OnDisable(Shape s) =>
@ -179,8 +179,8 @@ internal abstract class QSBQuantumObject<T> : WorldObject<T>, IQSBQuantumObject
return;
}
// send event to other players that we're releasing authority
((IQSBQuantumObject)this).SendMessage(new QuantumAuthorityMessage(0u));
// send event to other players that we're releasing ownership
((IQSBQuantumObject)this).SendMessage(new QuantumOwnershipMessage(0u));
});
public void OnTakeProbeSnapshot(PlayerInfo player, ProbeCamera.ID cameraId)

View File

@ -44,7 +44,7 @@ public class QSBSectorManager : WorldObjectManager
foreach (var sync in SectoredSyncs)
{
if (sync.hasAuthority
if (sync.isOwned
&& sync.IsValid
&& sync.AttachedTransform.gameObject.activeInHierarchy)
{

View File

@ -1,5 +1,5 @@
using QSB.AuthoritySync;
using QSB.Messaging;
using QSB.Messaging;
using QSB.OwnershipSync;
using QSB.Player;
using QSB.Player.TransformSync;
using QSB.ShipSync.TransformSync;
@ -57,7 +57,7 @@ internal class FlyShipMessage : QSBMessage<bool>
if (QSBCore.IsHost)
{
ShipTransformSync.LocalInstance.netIdentity.SetAuthority(isFlying
ShipTransformSync.LocalInstance.netIdentity.SetOwner(isFlying
? id
: QSBPlayerManager.LocalPlayerId);
}

View File

@ -215,7 +215,7 @@ internal class ShipPatches : QSBPatch
[HarmonyPrefix]
[HarmonyPatch(typeof(ShipDamageController), nameof(ShipDamageController.OnImpact))]
public static bool ShipDamageController_OnImpact()
=> ShipTransformSync.LocalInstance == null || ShipTransformSync.LocalInstance.hasAuthority;
=> ShipTransformSync.LocalInstance == null || ShipTransformSync.LocalInstance.isOwned;
[HarmonyPostfix]
[HarmonyPatch(typeof(ShipComponent), nameof(ShipComponent.RepairTick))]

View File

@ -114,7 +114,7 @@ internal class ShipManager : WorldObjectManager
DebugLog.ToConsole($"Error - Tried to spawn ship, but LocalPlayer's TransformSync is null!", MessageType.Error);
}
Instantiate(QSBNetworkManager.singleton.ShipPrefab).SpawnWithServerAuthority();
Instantiate(QSBNetworkManager.singleton.ShipPrefab).SpawnWithServerOwnership();
}
QSBWorldSync.Init<QSBShipComponent, ShipComponent>();

View File

@ -12,7 +12,7 @@ namespace QSB.ShipSync.WorldObjects;
internal class QSBShipDetachableLeg : LinkedWorldObject<ShipDetachableLeg, ShipLegTransformSync>
{
protected override GameObject NetworkObjectPrefab => QSBNetworkManager.singleton.ShipLegPrefab;
protected override bool SpawnWithServerAuthority => true;
protected override bool SpawnWithServerOwnership => true;
public override void SendInitialState(uint to)
{

View File

@ -12,7 +12,7 @@ namespace QSB.ShipSync.WorldObjects;
internal class QSBShipDetachableModule : LinkedWorldObject<ShipDetachableModule, ShipModuleTransformSync>
{
protected override GameObject NetworkObjectPrefab => QSBNetworkManager.singleton.ShipModulePrefab;
protected override bool SpawnWithServerAuthority => true;
protected override bool SpawnWithServerOwnership => true;
public override void SendInitialState(uint to)
{

View File

@ -48,7 +48,7 @@ internal class OccasionalManager : WorldObjectManager
if (QSBCore.IsHost)
{
Instantiate(QSBNetworkManager.singleton.OccasionalPrefab).SpawnWithServerAuthority();
Instantiate(QSBNetworkManager.singleton.OccasionalPrefab).SpawnWithServerOwnership();
}
}

View File

@ -49,7 +49,7 @@ public class QSBNetworkTransformChild : QSBNetworkBehaviour
{
if (AttachedTransform)
{
if (hasAuthority)
if (isOwned)
{
Target.localPosition = AttachedTransform.localPosition;
Target.localRotation = AttachedTransform.localRotation;

View File

@ -63,7 +63,7 @@ public abstract class BaseSectoredSync : SyncBase
/// <summary>
/// use this instead of SetReferenceTransform
/// <para/>
/// called by QSBSectorManager (authority) and ApplyToSector (non authority)
/// called by QSBSectorManager (owner) and ApplyToSector (non owner)
/// </summary>
public void SetReferenceSector(QSBSector sector)
{

View File

@ -9,7 +9,7 @@ public abstract class SectoredTransformSync : BaseSectoredSync
protected abstract Transform InitRemoteTransform();
protected sealed override Transform InitAttachedTransform()
=> hasAuthority ? InitLocalTransform() : InitRemoteTransform();
=> isOwned ? InitLocalTransform() : InitRemoteTransform();
protected override void GetFromAttached()
{

View File

@ -189,7 +189,7 @@ public abstract class SyncBase : QSBNetworkTransform
protected virtual void Uninit()
{
if (IsPlayerObject && !hasAuthority && AttachedTransform)
if (IsPlayerObject && !isOwned && AttachedTransform)
{
Destroy(AttachedTransform.gameObject);
}
@ -255,7 +255,7 @@ public abstract class SyncBase : QSBNetworkTransform
if (IsValid && _interpolating)
{
if (hasAuthority)
if (isOwned)
{
_interpolating = false;
return;
@ -294,13 +294,13 @@ public abstract class SyncBase : QSBNetworkTransform
}
ReferenceTransform = referenceTransform;
if (IsPlayerObject && !hasAuthority && AttachedTransform)
if (IsPlayerObject && !isOwned && AttachedTransform)
{
AttachedTransform.parent = ReferenceTransform;
AttachedTransform.localScale = Vector3.one;
}
if (UseInterpolation && !hasAuthority && AttachedTransform && ReferenceTransform)
if (UseInterpolation && !isOwned && AttachedTransform && ReferenceTransform)
{
SmoothPosition = ReferenceTransform.ToRelPos(AttachedTransform.position);
SmoothRotation = ReferenceTransform.ToRelRot(AttachedTransform.rotation);

View File

@ -9,7 +9,7 @@ public abstract class UnsectoredTransformSync : BaseUnsectoredSync
protected abstract Transform InitRemoteTransform();
protected sealed override Transform InitAttachedTransform()
=> hasAuthority ? InitLocalTransform() : InitRemoteTransform();
=> isOwned ? InitLocalTransform() : InitRemoteTransform();
protected override void GetFromAttached()
{

View File

@ -1,7 +1,7 @@
using Cysharp.Threading.Tasks;
using Mirror;
using QSB.AuthoritySync;
using QSB.Messaging;
using QSB.OwnershipSync;
using QSB.Player;
using QSB.Tools.ProbeLauncherTool.Messages;
using QSB.Tools.ProbeLauncherTool.VariableSync;
@ -74,10 +74,10 @@ public class QSBStationaryProbeLauncher : QSBProbeLauncher, ILinkedWorldObject<S
_currentUser = isInUse ? user : uint.MaxValue;
// Whoever is using it needs authority to be able to rotate it
// Whoever is using it needs ownership to be able to rotate it
if (QSBCore.IsHost)
{
NetworkBehaviour.netIdentity.SetAuthority(_currentUser);
NetworkBehaviour.netIdentity.SetOwner(_currentUser);
}
UpdateUse();
@ -89,10 +89,10 @@ public class QSBStationaryProbeLauncher : QSBProbeLauncher, ILinkedWorldObject<S
_currentUser = isInUse ? QSBPlayerManager.LocalPlayerId : uint.MaxValue;
// Whoever is using it needs authority to be able to rotate it
// Whoever is using it needs ownership to be able to rotate it
if (QSBCore.IsHost)
{
NetworkBehaviour.netIdentity.SetAuthority(_currentUser);
NetworkBehaviour.netIdentity.SetOwner(_currentUser);
}
this.SendMessage(new StationaryProbeLauncherMessage(isInUse, _currentUser));

View File

@ -11,37 +11,6 @@ internal class ProbeToolPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
/*
* This patch is just to avoid error spam when testing probe destruction in SolarSystem
*/
[HarmonyPrefix]
[HarmonyPatch(typeof(NomaiWarpStreaming), nameof(NomaiWarpStreaming.FixedUpdate))]
public static bool FixedUpdateOverride(NomaiWarpStreaming __instance)
{
if (__instance._warpTransmitter != null)
{
var ableToBeWarped = __instance._warpTransmitter.GetViewAngleToTarget() < __instance._streamingAngle;
var probeAbove = __instance._probe != null && __instance._probe.IsLaunched() && (!__instance._probe.IsAnchored() || __instance._warpTransmitter.IsProbeOnPlatform());
var shouldBeLoadingRequiredAssets = ableToBeWarped && (__instance._playerInVolume || (__instance._probeInVolume && probeAbove));
var shouldBeLoadingGeneralAssets = ableToBeWarped && __instance._warpTransmitter.IsPlayerOnPlatform();
__instance.UpdatePreloadingState(shouldBeLoadingRequiredAssets, shouldBeLoadingGeneralAssets);
}
if (__instance._warpReceiver != null)
{
var ableToBeWarped = __instance._warpReceiver.IsReturnWarpEnabled() || __instance._warpReceiver.IsBlackHoleOpen();
var probeAbove = __instance._probe != null && __instance._probe.IsLaunched() && (!__instance._probe.IsAnchored() || __instance._warpReceiver.IsProbeOnPlatform());
var shouldBeLoadingRequiredAssets = ableToBeWarped && (__instance._playerInVolume || (__instance._probeInVolume && probeAbove));
var shouldBeLoadingGeneralAssets = ableToBeWarped && __instance._playerInVolume;
__instance.UpdatePreloadingState(shouldBeLoadingRequiredAssets, shouldBeLoadingGeneralAssets);
}
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ProbeCamera), nameof(ProbeCamera.RotateHorizontal))]
public static bool RotateHorizontal(ProbeCamera __instance, float degrees)

View File

@ -22,7 +22,17 @@
"Connecting": "CONNECTING...",
"OK": "OK",
"ServerRefusedConnection": "Server refused connection.\n{0}",
"ClientDisconnectWithError": "Client disconnected with error!\n{0}",
"ClientDisconnectWithError": "Client disconnected with error!\n{0}\nMore info: {1}",
"TransportErrors": {
"DnsResolve": "Failed to resolve host name.",
"Refused": "Connection refused.",
"Timeout": "Connection timed out.",
"Congestion": "Congestion on transport.",
"InvalidReceive": "Error receiving message.",
"InvalidSend": "Error sending message.",
"ConnectionClosed": "Connection closed.",
"Unexpected": "Unexpected error."
},
"QSBVersionMismatch": "QSB version does not match. (Client:{0}, Server:{1})",
"OWVersionMismatch": "Outer Wilds version does not match. (Client:{0}, Server:{1})",
"DLCMismatch": "DLC installation state does not match. (Client:{0}, Server:{1})",

127
QSB/Translations/tr.json Normal file
View File

@ -0,0 +1,127 @@
{
"Language": "TURKISH",
"MainMenuHost": "ÇOK OYUNCULU PAYLAŞ",
"MainMenuConnect": "ÇOK OYUNCULU BAĞLAN",
"PauseMenuDisconnect": "BAGLANTIYI KES",
"PauseMenuStopHosting": "PAYLAŞMAYI DURDUR",
"PublicIPAddress": "Genel IP Adresi\n\n(ÇOK OYUNCULU İLERLEMENİZ SİLİNECEKTİR)",
"ProductUserID": "Kullanıcı Kimliği\n\n(ÇOK OYUNCULU İLERLEMENİZ SİLİNECEKTİR)",
"Connect": "BAĞLAN",
"Cancel": "İPTAL",
"HostExistingOrNewOrCopy": "Mevcut bir tek oyunculu keşfi çok oyunculu olarak mı paylaşmak (çok oyunculuya kopyalamak), yoksa mevcut olan veya yeni bir çok oyunculu keşfi mi paylaşmak istiyorsun?",
"HostNewOrCopy": "Mevcut bir tek oyunculu keşfi çok oyunculu olarak mı paylaşmak, yoksa yeni bir çok oyunculu keşif mi paylaşmak istiyorsun?",
"HostExistingOrNew": "Yeni bir çok oyunculu keşif mi, yoksa mevcut olan bir çok oyunculu keşif mi paylaşmak istiyorsun?",
"ExistingSave": "MEVCUT KEŞİF",
"NewSave": "YENİ KEŞİF",
"CopySave": "KEŞFİ KOPYALA",
"DisconnectAreYouSure": "Baglantıyı kesmek istediginden emin misin?\nBu seni ana menüye döndürecektir.",
"Yes": "EVET",
"No": "HAYIR",
"StopHostingAreYouSure": "Paylaşmayı durdurmak istediğinden emin misin?\nBu tüm oyuncuların bağlantısını kesip onları ana menüye döndürecektir.",
"CopyProductUserIDToClipboard": "Keşif paylaşılıyor\nDiğer oyuncular senin aşağıdaki kullanıcı kimliğini girerek bağlanabilirler.\n{0}\nBunu panoya kopyalamak ister misin?",
"Connecting": "BAĞLANIYOR...",
"OK": "TAMAM",
"ServerRefusedConnection": "Sunucu bağlantıyı reddetti.\n{0}",
"ClientDisconnectWithError": "Bir hata nedeniyle istemcinin bağlantısı kesildi!\n{0}",
"QSBVersionMismatch": "QSB sürümü uyumlu değil. (İstemci:{0}, Sunucu:{1})",
"OWVersionMismatch": "Outer Wilds sürümü uyumlu değil. (İstemci:{0}, Sunucu:{1})",
"DLCMismatch": "DLC yüklenme durumu uyumlu değil. (İstemci:{0}, Sunucu:{1})",
"GameProgressLimit": "Oyun çok fazla ilerlemiş.",
"AddonMismatch": "Yüklü eklentiler uyumsuz. (İstemci:{0} eklentileri, Sunucu:{1} eklentileri)",
"IncompatibleMod": "İzin verilmeyen veya uyumsuz mod kullanılıyor. İlk bulunan mod {0}",
"PlayerJoinedTheGame": "{0} katıldı!",
"PlayerLeftTheGame": "{0} ayrıldı.",
"PlayerWasKicked": "{0} atıldı.",
"KickedFromServer": "Sunucudan atıldın. Sebep : {0}",
"RespawnPlayer": "Oyuncuyu yeniden canlandır",
"TimeSyncTooFarBehind": "{0}\nSunucu vaktine uymak için ileri sarılıyor...",
"TimeSyncWaitingForStartOfServer": "Sunucunun başlaması bekleniyor...",
"TimeSyncTooFarAhead": "{0}\nSunucu vaktine uymak için duraklatılıyor...",
"TimeSyncWaitForAllToReady": "Döngünün başlaması bekleniyor...",
"TimeSyncWaitForAllToDie": "Döngünün bitmesi bekleniyor...",
"GalaxyMapEveryoneNotPresent": "Henüz vakti değil. Buna şahitlik etmesi için herkesin burda olması gerek.",
"YouAreDead": "Öldün.",
"WaitingForRespawn": "Birinin seni yeniden canlandırması bekleniyor...",
"WaitingForAllToDie": "{0} oyuncunun daha ölmesi bekleniyor...",
"AttachToShip": "Gemiye tutun",
"DetachFromShip": "Gemiyi bırak",
"DeathMessages": {
"Default": [
"{0} öldü",
"{0} öldürüldü"
],
"Impact": [
"{0} retro-iticilerini kullanmayı unuttu",
"{0} yere yapıştı",
"{0} yere çakıldı",
"{0} çok sert bir iniş yaptı",
"{0} çarpışma nedeniyle öldü",
"{0} kütleçekimini keşfetti"
],
"Asphyxiation": [
"{0} nefes almayı unuttu",
"{0} boğuldu",
"{0} boğularak öldü",
"{0} nasıl nefes alınacağını unuttu",
"{0} oksijenini kontrol etmeyi unuttu",
"{0} nefessiz kaldı",
"{0} oksijensiz kaldı",
"{0} için zaten nefes almaya gerek yoktu"
],
"Energy": [
"{0} pişirildi"
],
"Supernova": [
"{0} için vakit doldu",
"{0} yandı",
"{0} pişti",
"{0} buharlaştı",
"{0} zamanın akışında kayboldu"
],
"Digestion": [
"{0} canlı canlı yenildi",
"{0} balık buldu",
"{0} kötü bir yaratıkla karşılaştı",
"{0} yanlış balığa bulaştı",
"{0} sindirildi",
"{0} sindirilerek öldü"
],
"Crushed": [
"{0} ezildi",
"{0} sıkıştırıldı",
"{0} gömüldü",
"{0} zamanında çıkamadı",
"{0} kumda yüzmeye gitti",
"{0} kumu hafife aldı",
"{0} kumun altında sıkıştı"
],
"Lava": [
"{0} lavın içinde öldü",
"{0} eritildi",
"{0} lavda yüzmeye çalıştı",
"{0} lava düştü",
"{0} lava düşerek öldü",
"{0} lavda yüzdü",
"{0} lavda kızartıldı"
],
"BlackHole": [
"{0} anılarını kovaladı"
],
"DreamExplosion": [
"{0} patladı",
"{0} ilk kullanıcı oldu",
"{0} bom diye patladı",
"{0} kızartıldı",
"{0} patlama nedeniyle öldü",
"{0} yanlış eseri kullandı"
],
"CrushedByElevator": [
"{0} ezildi",
"{0} sıkıştırıldı",
"{0} asansör tarafından ezildi",
"{0} asansör altında durdu",
"{0} dümdüz oldu",
"{0} asansör tarafından sıkıştırıldı"
]
}
}

View File

@ -62,7 +62,7 @@ public static class Extensions
return conn;
}
public static void SpawnWithServerAuthority(this GameObject go) =>
public static void SpawnWithServerOwnership(this GameObject go) =>
NetworkServer.Spawn(go, NetworkServer.localConnection);
#endregion

View File

@ -20,16 +20,16 @@ public static class ILinkedWorldObject_Extensions
/// link a world object and network object, then spawn it.
/// (host only)
/// </summary>
public static void SpawnLinked(this ILinkedWorldObject<NetworkBehaviour> @this, GameObject prefab, bool spawnWithServerAuthority)
public static void SpawnLinked(this ILinkedWorldObject<NetworkBehaviour> @this, GameObject prefab, bool spawnWithServerOwnership)
{
var go = Object.Instantiate(prefab);
var networkBehaviour = go.GetComponent<ILinkedNetworkBehaviour>();
@this.LinkTo(networkBehaviour);
if (spawnWithServerAuthority)
if (spawnWithServerOwnership)
{
go.SpawnWithServerAuthority();
go.SpawnWithServerOwnership();
}
else
{

View File

@ -17,13 +17,13 @@ public abstract class LinkedWorldObject<T, TNetworkBehaviour> : WorldObject<T>,
public void SetNetworkBehaviour(NetworkBehaviour networkBehaviour) => NetworkBehaviour = (TNetworkBehaviour)networkBehaviour;
protected abstract GameObject NetworkObjectPrefab { get; }
protected abstract bool SpawnWithServerAuthority { get; }
protected abstract bool SpawnWithServerOwnership { get; }
public override async UniTask Init(CancellationToken ct)
{
if (QSBCore.IsHost)
{
this.SpawnLinked(NetworkObjectPrefab, SpawnWithServerAuthority);
this.SpawnLinked(NetworkObjectPrefab, SpawnWithServerOwnership);
}
else
{

View File

@ -45,7 +45,7 @@ public abstract class QSBNetworkBehaviour : NetworkBehaviour
return;
}
if (!hasAuthority)
if (!isOwned)
{
return;
}
@ -116,7 +116,7 @@ public abstract class QSBNetworkBehaviour : NetworkBehaviour
return;
}
if (hasAuthority)
if (isOwned)
{
return;
}

View File

@ -37,6 +37,12 @@
"type": "toggle",
"value": true,
"tooltip": "Show extra HUD elements, like player status and minimap icons."
},
"textChatInput": {
"title": "Text Chat Input",
"type": "toggle",
"value": true,
"tooltip": "Disable this if using NomaiVR, or any other mod with conflicting inputs."
}
}
}

View File

@ -7,7 +7,7 @@
"body": "- Disable *all* other mods. (Can heavily affect performance)\n- Make sure you are not running any other network-intensive applications."
},
"uniqueName": "Raicuparta.QuantumSpaceBuddies",
"version": "0.28.0",
"version": "0.28.1",
"owmlVersion": "2.9.0",
"dependencies": [ "_nebula.MenuFramework", "JohnCorby.VanillaFix" ],
"pathsToPreserve": [ "debugsettings.json" ],