mirror of
https://github.com/misternebula/quantum-space-buddies.git
synced 2025-02-21 00:39:53 +00:00
commit
03bcc607fe
@ -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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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 });
|
||||
|
@ -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.
@ -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
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 });
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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; }
|
||||
}
|
32
QSB/OwnershipSync/IOwnedWorldObject_Extensions.cs
Normal file
32
QSB/OwnershipSync/IOwnedWorldObject_Extensions.cs
Normal 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));
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
93
QSB/OwnershipSync/OwnershipManager.cs
Normal file
93
QSB/OwnershipSync/OwnershipManager.cs
Normal 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
|
||||
}
|
@ -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))
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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))]
|
||||
|
@ -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>();
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -48,7 +48,7 @@ internal class OccasionalManager : WorldObjectManager
|
||||
|
||||
if (QSBCore.IsHost)
|
||||
{
|
||||
Instantiate(QSBNetworkManager.singleton.OccasionalPrefab).SpawnWithServerAuthority();
|
||||
Instantiate(QSBNetworkManager.singleton.OccasionalPrefab).SpawnWithServerOwnership();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ public class QSBNetworkTransformChild : QSBNetworkBehaviour
|
||||
{
|
||||
if (AttachedTransform)
|
||||
{
|
||||
if (hasAuthority)
|
||||
if (isOwned)
|
||||
{
|
||||
Target.localPosition = AttachedTransform.localPosition;
|
||||
Target.localRotation = AttachedTransform.localRotation;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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));
|
||||
|
@ -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)
|
||||
|
@ -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
127
QSB/Translations/tr.json
Normal 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ı"
|
||||
]
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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."
|
||||
}
|
||||
}
|
||||
}
|
@ -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" ],
|
||||
|
Loading…
x
Reference in New Issue
Block a user