mirror of
https://github.com/misternebula/quantum-space-buddies.git
synced 2025-02-21 00:39:53 +00:00
commit
419f91bbb5
1
.gitignore
vendored
1
.gitignore
vendored
@ -361,3 +361,4 @@ QSB.csproj.user
|
||||
GameAssets/
|
||||
Chert/
|
||||
Riebeck/
|
||||
OWML.Config.json
|
||||
|
@ -12,7 +12,6 @@ namespace QSB.Animation
|
||||
public class AnimationSync : PlayerSyncObject
|
||||
{
|
||||
private Animator _anim;
|
||||
private Animator _bodyAnim;
|
||||
private QNetworkAnimator _netAnim;
|
||||
|
||||
private RuntimeAnimatorController _suitedAnimController;
|
||||
@ -30,7 +29,7 @@ namespace QSB.Animation
|
||||
|
||||
public AnimatorMirror Mirror { get; private set; }
|
||||
public AnimationType CurrentType { get; set; }
|
||||
public Animator VisibleAnimator => _bodyAnim;
|
||||
public Animator VisibleAnimator { get; private set; }
|
||||
|
||||
protected void Awake()
|
||||
{
|
||||
@ -73,15 +72,15 @@ namespace QSB.Animation
|
||||
LoadControllers();
|
||||
}
|
||||
_netAnim.enabled = true;
|
||||
_bodyAnim = body.GetComponent<Animator>();
|
||||
VisibleAnimator = body.GetComponent<Animator>();
|
||||
Mirror = body.gameObject.AddComponent<AnimatorMirror>();
|
||||
if (IsLocalPlayer)
|
||||
{
|
||||
Mirror.Init(_bodyAnim, _anim);
|
||||
Mirror.Init(VisibleAnimator, _anim);
|
||||
}
|
||||
else
|
||||
{
|
||||
Mirror.Init(_anim, _bodyAnim);
|
||||
Mirror.Init(_anim, VisibleAnimator);
|
||||
}
|
||||
|
||||
for (var i = 0; i < _anim.parameterCount; i++)
|
||||
@ -138,7 +137,7 @@ namespace QSB.Animation
|
||||
private void InitCrouchSync()
|
||||
{
|
||||
_crouchSync = gameObject.AddComponent<CrouchSync>();
|
||||
_crouchSync.Init(this, _playerController, _bodyAnim);
|
||||
_crouchSync.Init(this, _playerController, VisibleAnimator);
|
||||
}
|
||||
|
||||
private void OnJump() => _netAnim.SetTrigger("Jump");
|
||||
@ -165,7 +164,7 @@ namespace QSB.Animation
|
||||
|
||||
public void SetSuitState(bool state)
|
||||
{
|
||||
if (!Player.IsReady)
|
||||
if (!Player.PlayerStates.IsReady)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -228,16 +227,16 @@ namespace QSB.Animation
|
||||
break;
|
||||
}
|
||||
_anim.runtimeAnimatorController = controller;
|
||||
_bodyAnim.runtimeAnimatorController = controller;
|
||||
VisibleAnimator.runtimeAnimatorController = controller;
|
||||
if (type != AnimationType.PlayerSuited && type != AnimationType.PlayerUnsuited)
|
||||
{
|
||||
_bodyAnim.SetTrigger("Playing");
|
||||
VisibleAnimator.SetTrigger("Playing");
|
||||
_anim.SetTrigger("Playing");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Avoids "jumping" when exiting instrument and putting on suit
|
||||
_bodyAnim.SetTrigger("Grounded");
|
||||
VisibleAnimator.SetTrigger("Grounded");
|
||||
_anim.SetTrigger("Grounded");
|
||||
}
|
||||
_netAnim.animator = _anim; // Probably not needed.
|
||||
|
@ -22,7 +22,7 @@ namespace QSB.Animation.Events
|
||||
|
||||
public override void OnReceiveRemote(bool server, EnumMessage<AnimationType> message)
|
||||
{
|
||||
if (!QSBCore.HasWokenUp || !QSBPlayerManager.GetPlayer(message.AboutId).IsReady)
|
||||
if (!QSBCore.HasWokenUp || !QSBPlayerManager.GetPlayer(message.AboutId).PlayerStates.IsReady)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -32,9 +32,9 @@ namespace QSB.Animation.Events
|
||||
public override void OnReceiveRemote(bool server, ToggleMessage message)
|
||||
{
|
||||
var player = QSBPlayerManager.GetPlayer(message.AboutId);
|
||||
player?.UpdateState(State.Suit, message.ToggleValue);
|
||||
player.PlayerStates.SuitedUp = message.ToggleValue;
|
||||
|
||||
if (!QSBCore.HasWokenUp || !player.IsReady)
|
||||
if (!QSBCore.HasWokenUp || !player.PlayerStates.IsReady)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -46,7 +46,7 @@ namespace QSB.Animation.Events
|
||||
|
||||
public override void OnReceiveLocal(bool server, ToggleMessage message)
|
||||
{
|
||||
QSBPlayerManager.LocalPlayer.UpdateState(State.Suit, message.ToggleValue);
|
||||
QSBPlayerManager.LocalPlayer.PlayerStates.SuitedUp = message.ToggleValue;
|
||||
var animator = QSBPlayerManager.LocalPlayer.AnimationSync;
|
||||
var type = message.ToggleValue ? AnimationType.PlayerSuited : AnimationType.PlayerUnsuited;
|
||||
animator.CurrentType = type;
|
||||
|
@ -1,4 +1,6 @@
|
||||
using UnityEngine;
|
||||
using OWML.Common;
|
||||
using QSB.Utility;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QSB.Animation
|
||||
{
|
||||
@ -21,6 +23,16 @@ namespace QSB.Animation
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (_attachedAnimator == null)
|
||||
{
|
||||
DebugLog.ToConsole($"Error - _attachedAnimator is null!", MessageType.Error);
|
||||
return;
|
||||
}
|
||||
if (_lookBase == null)
|
||||
{
|
||||
DebugLog.ToConsole($"Error - _lookBase is null!", MessageType.Error);
|
||||
return;
|
||||
}
|
||||
var bone = _attachedAnimator.GetBoneTransform(HumanBodyBones.Head);
|
||||
// Get the camera's local rotation with respect to the player body
|
||||
var lookLocalRotation = Quaternion.Inverse(_attachedAnimator.transform.rotation) * _lookBase.rotation;
|
||||
|
@ -7,86 +7,100 @@ namespace QSB.DeathSync
|
||||
{
|
||||
private static readonly Dictionary<DeathType, string[]> Darkhold = new Dictionary<DeathType, string[]>
|
||||
{
|
||||
{ DeathType.Default, new[]
|
||||
{ DeathType.Default, new[] // Running out of health
|
||||
{
|
||||
"{0} died"
|
||||
"{0} died",
|
||||
"{0} was killed"
|
||||
} },
|
||||
{ DeathType.Impact, new[]
|
||||
{ DeathType.Impact, new[] // Hitting the ground/wall/object
|
||||
{
|
||||
"{0} forgot to use retro-rockets",
|
||||
"{0} bonked into the ground too hard",
|
||||
"{0} went splat"
|
||||
"{0} hit the ground too hard",
|
||||
"{0} went splat",
|
||||
"{0} died",
|
||||
"{0} was killed",
|
||||
"{0} died due to impact",
|
||||
"{0} impacted the ground too hard"
|
||||
} },
|
||||
{ DeathType.Asphyxiation, new[]
|
||||
{ DeathType.Asphyxiation, new[] // Running out of oxygen
|
||||
{
|
||||
"{0} forgot to breathe",
|
||||
"{0} asphyxiated",
|
||||
"{0} died due to asphyxiation",
|
||||
"{0} forgot how to breathe",
|
||||
"{0} forgot to check their oxygen meter",
|
||||
"{0} lacked oxygen",
|
||||
"{0} forgot to check their oxygen",
|
||||
"{0} ran out of air",
|
||||
"{0} ran out of oxygen",
|
||||
"{0} didn't need air anyway"
|
||||
} },
|
||||
{ DeathType.Energy, new[]
|
||||
{ DeathType.Energy, new[] // Electricity, sun, etc.
|
||||
{
|
||||
"{0} was cooked",
|
||||
"{0} failed the Hotshot achievement",
|
||||
"{0} forgot to install an AC unit",
|
||||
"{0} got too hot"
|
||||
"{0} died",
|
||||
"{0} was killed"
|
||||
} },
|
||||
{ DeathType.Supernova, new[]
|
||||
{ DeathType.Supernova, new[] // Supernova
|
||||
{
|
||||
"{0} ran out of time",
|
||||
"{0} burnt up",
|
||||
"{0} got vaporized",
|
||||
"{0} lost track of time",
|
||||
"{0} got front row seats to the supernova",
|
||||
"{0} heard the End of Times music",
|
||||
"{0} heard the music",
|
||||
"{0} watched the sun go kaboom",
|
||||
"{0} became cosmic marshmallow",
|
||||
"{0} photosynthesized too much"
|
||||
"{0} photosynthesized too much",
|
||||
"{0} died due to the supernova"
|
||||
} },
|
||||
{ DeathType.Digestion, new[]
|
||||
{ DeathType.Digestion, new[] // Anglerfish
|
||||
{
|
||||
"{0} was eaten",
|
||||
"{0} found a fish",
|
||||
"{0} encountered an evil creature",
|
||||
"{0} followed the light, then was followed by it",
|
||||
"{0} messed with the wrong species of fish"
|
||||
"{0} messed with the wrong fish",
|
||||
"{0} was digested",
|
||||
"{0} died due to digestion"
|
||||
} },
|
||||
{ DeathType.BigBang, new[]
|
||||
{ DeathType.BigBang, new[] // End of the game
|
||||
{
|
||||
"{0} sacrificed themself for the universe",
|
||||
"{0} knows the true meaning of sacrifice",
|
||||
"{0} won at the cost of their life"
|
||||
} },
|
||||
{ DeathType.Crushed, new[]
|
||||
{ DeathType.Crushed, new[] // Crushed in sand
|
||||
{
|
||||
"{0} went through the tunnel too slow",
|
||||
"{0} didn't make it out in time",
|
||||
"{0} was squished",
|
||||
"{0} thought the Sunless City was safe",
|
||||
"{0} was buried"
|
||||
"{0} was crushed",
|
||||
"{0} was buried",
|
||||
"{0} went swimming in the sand",
|
||||
"{0} underestimated the danger of sand",
|
||||
"{0} died due to being crushed"
|
||||
} },
|
||||
{ DeathType.Meditation, new[]
|
||||
{ DeathType.Meditation, new[] // Meditation
|
||||
{
|
||||
"{0} took a deep breath and died",
|
||||
"{0} fell asleep",
|
||||
"{0} got killed by Gabbro's advice"
|
||||
"{0} broke QSB. this is a bug, you should never see this"
|
||||
} },
|
||||
{ DeathType.TimeLoop, new[]
|
||||
{ DeathType.TimeLoop, new[] // Escaping the supernova
|
||||
{
|
||||
"{0} ran out of time",
|
||||
"{0} was caught by a statue",
|
||||
"{0}'s memories were pilfered",
|
||||
"{0}'s memories fell into a black hole",
|
||||
"{0}'s universe was eaten by Grobletombus"
|
||||
"{0} lost track of time",
|
||||
"{0} watched the sun go kaboom"
|
||||
} },
|
||||
{ DeathType.Lava, new[]
|
||||
{ DeathType.Lava, new[] // Lava
|
||||
{
|
||||
"{0} died in lava",
|
||||
"{0} was melted",
|
||||
"{0} tried to swim in lava",
|
||||
"{0} didn't know what the glowy orange liquid was",
|
||||
"{0} slipped in lava",
|
||||
"{0} became one with the glowing gooey rock"
|
||||
"{0} fell into lava",
|
||||
"{0} became one with the glowing gooey rock",
|
||||
"{0} died due to lava",
|
||||
"{0} got burnt in the lava"
|
||||
} },
|
||||
{ DeathType.BlackHole, new[]
|
||||
{ DeathType.BlackHole, new[] // ATP core black hole
|
||||
{
|
||||
"{0} should visit the Ash Twin Project again",
|
||||
"{0} waited inside the Ash Twin Project",
|
||||
|
@ -28,7 +28,6 @@
|
||||
public static string QSBPlayerDeath = "QSBPlayerDeath";
|
||||
public static string QSBPlayerJoin = "QSBPlayerJoin";
|
||||
public static string QSBPlayerReady = "QSBPlayerReady";
|
||||
public static string QSBSectorChange = "QSBSectorChange";
|
||||
public static string QSBPlayerStatesRequest = "QSBPlayerStatesRequest";
|
||||
public static string QSBServerTime = "QSBServerTime";
|
||||
public static string QSBStartLift = "QSBStartLift";
|
||||
|
@ -13,7 +13,6 @@
|
||||
SuitActiveChange,
|
||||
PlayerJoin,
|
||||
PlayerDeath,
|
||||
PlayerSectorChange,
|
||||
PlayerReady,
|
||||
ProbeActiveChange,
|
||||
Elevator,
|
||||
|
@ -1,7 +1,7 @@
|
||||
using OWML.Common;
|
||||
using QSB.Messaging;
|
||||
using QSB.Player;
|
||||
using QSB.TransformSync;
|
||||
using QSB.Player.TransformSync;
|
||||
using QSB.Utility;
|
||||
using QuantumUNET;
|
||||
using QuantumUNET.Components;
|
||||
|
@ -10,6 +10,7 @@ using QSB.ItemSync.Events;
|
||||
using QSB.LogSync.Events;
|
||||
using QSB.OrbSync.Events;
|
||||
using QSB.Player.Events;
|
||||
using QSB.ProbeSync.Events;
|
||||
using QSB.QuantumSync.Events;
|
||||
using QSB.RoastingSync.Events;
|
||||
using QSB.StatueSync.Events;
|
||||
@ -40,7 +41,6 @@ namespace QSB.Events
|
||||
new PlayerTranslatorEvent(),
|
||||
new PlayerProbeLauncherEvent(),
|
||||
new PlayerProbeEvent(),
|
||||
new PlayerSectorEvent(),
|
||||
new PlayerDeathEvent(),
|
||||
new PlayerStatesRequestEvent(),
|
||||
new ServerSendPlayerStatesEvent(),
|
||||
|
@ -38,7 +38,7 @@ namespace QSB.Instruments.QSBCamera
|
||||
_cameraObj.transform.localPosition = new Vector3(0, 0, -5f);
|
||||
_cameraObj.transform.localRotation = Quaternion.Euler(0, 0, 0);
|
||||
_camera = _cameraObj.AddComponent<Camera>();
|
||||
_camera.cullingMask = Locator.GetPlayerCamera().mainCamera.cullingMask & ~(1 << 27) | (1 << 22);
|
||||
_camera.cullingMask = (Locator.GetPlayerCamera().mainCamera.cullingMask & ~(1 << 27)) | (1 << 22);
|
||||
_camera.clearFlags = CameraClearFlags.Color;
|
||||
_camera.backgroundColor = Color.black;
|
||||
_camera.fieldOfView = 90f;
|
||||
|
@ -3,7 +3,7 @@ using QSB.WorldSync;
|
||||
using QuantumUNET;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QSB.TransformSync
|
||||
namespace QSB.OrbSync.TransformSync
|
||||
{
|
||||
public class NomaiOrbTransformSync : QNetworkBehaviour
|
||||
{
|
@ -8,6 +8,7 @@ using QSB.GeyserSync.Patches;
|
||||
using QSB.ItemSync.Patches;
|
||||
using QSB.LogSync.Patches;
|
||||
using QSB.OrbSync.Patches;
|
||||
using QSB.Player.Patches;
|
||||
using QSB.PoolSync.Patches;
|
||||
using QSB.QuantumSync.Patches;
|
||||
using QSB.RoastingSync.Patches;
|
||||
@ -49,7 +50,8 @@ namespace QSB.Patches
|
||||
new GeyserPatches(),
|
||||
new PoolPatches(),
|
||||
new CampfirePatches(),
|
||||
new RoastingPatches()
|
||||
new RoastingPatches(),
|
||||
new PlayerPatches()
|
||||
};
|
||||
|
||||
DebugLog.DebugWrite("Patch Manager ready.", MessageType.Success);
|
||||
|
@ -35,7 +35,7 @@ namespace QSB.Player.Events
|
||||
private static void HandleServer(ToggleMessage message)
|
||||
{
|
||||
DebugLog.DebugWrite($"Get ready event from {message.FromId}", MessageType.Success);
|
||||
QSBPlayerManager.GetPlayer(message.AboutId).IsReady = message.ToggleValue;
|
||||
QSBPlayerManager.GetPlayer(message.AboutId).PlayerStates.IsReady = message.ToggleValue;
|
||||
QSBEventManager.FireEvent(EventNames.QSBServerSendPlayerStates);
|
||||
}
|
||||
|
||||
|
@ -1,45 +0,0 @@
|
||||
using OWML.Common;
|
||||
using QSB.Events;
|
||||
using QSB.SectorSync.WorldObjects;
|
||||
using QSB.Utility;
|
||||
using QSB.WorldSync;
|
||||
using QSB.WorldSync.Events;
|
||||
|
||||
namespace QSB.Player.Events
|
||||
{
|
||||
public class PlayerSectorEvent : QSBEvent<WorldObjectMessage>
|
||||
{
|
||||
public override EventType Type => EventType.PlayerSectorChange;
|
||||
|
||||
public override void SetupListener() => GlobalMessenger<uint, QSBSector>.AddListener(EventNames.QSBSectorChange, Handler);
|
||||
public override void CloseListener() => GlobalMessenger<uint, QSBSector>.RemoveListener(EventNames.QSBSectorChange, Handler);
|
||||
|
||||
private void Handler(uint netId, QSBSector sector) => SendEvent(CreateMessage(netId, sector));
|
||||
|
||||
private WorldObjectMessage CreateMessage(uint netId, QSBSector sector) => new WorldObjectMessage
|
||||
{
|
||||
AboutId = netId,
|
||||
ObjectId = sector.ObjectId
|
||||
};
|
||||
|
||||
public override void OnReceiveRemote(bool server, WorldObjectMessage message)
|
||||
{
|
||||
if (!QSBSceneManager.IsInUniverse)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var sector = QSBWorldSync.GetWorldFromId<QSBSector>(message.ObjectId);
|
||||
|
||||
if (sector == null)
|
||||
{
|
||||
DebugLog.ToConsole($"Sector with index id {message.ObjectId} not found!", MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
var transformSync = QSBPlayerManager.GetSyncObject<TransformSync.TransformSync>(message.AboutId);
|
||||
|
||||
QSBCore.UnityEvents.RunWhen(() => transformSync?.SyncedTransform != null,
|
||||
() => transformSync?.SetReferenceSector(sector));
|
||||
}
|
||||
}
|
||||
}
|
@ -6,23 +6,35 @@ namespace QSB.Player.Events
|
||||
public class PlayerStateMessage : PlayerMessage
|
||||
{
|
||||
public string PlayerName { get; set; }
|
||||
public bool PlayerReady { get; set; }
|
||||
public State PlayerState { get; set; }
|
||||
public PlayerState PlayerState { get; set; }
|
||||
|
||||
public override void Deserialize(QNetworkReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
PlayerName = reader.ReadString();
|
||||
PlayerReady = reader.ReadBoolean();
|
||||
PlayerState = (State)reader.ReadInt32();
|
||||
PlayerState = new PlayerState
|
||||
{
|
||||
IsReady = reader.ReadBoolean(),
|
||||
FlashlightActive = reader.ReadBoolean(),
|
||||
SuitedUp = reader.ReadBoolean(),
|
||||
ProbeLauncherEquipped = reader.ReadBoolean(),
|
||||
SignalscopeEquipped = reader.ReadBoolean(),
|
||||
TranslatorEquipped = reader.ReadBoolean(),
|
||||
ProbeActive = reader.ReadBoolean()
|
||||
};
|
||||
}
|
||||
|
||||
public override void Serialize(QNetworkWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(PlayerName);
|
||||
writer.Write(PlayerReady);
|
||||
writer.Write((int)PlayerState);
|
||||
writer.Write(PlayerState.IsReady);
|
||||
writer.Write(PlayerState.FlashlightActive);
|
||||
writer.Write(PlayerState.SuitedUp);
|
||||
writer.Write(PlayerState.ProbeLauncherEquipped);
|
||||
writer.Write(PlayerState.SignalscopeEquipped);
|
||||
writer.Write(PlayerState.TranslatorEquipped);
|
||||
writer.Write(PlayerState.ProbeActive);
|
||||
}
|
||||
}
|
||||
}
|
@ -30,11 +30,6 @@ namespace QSB.Player.Events
|
||||
{
|
||||
DebugLog.DebugWrite($"Get state request from {message.FromId} - isServer?{server}");
|
||||
QSBEventManager.FireEvent(EventNames.QSBServerSendPlayerStates);
|
||||
foreach (var item in QSBPlayerManager.GetSyncObjects<TransformSync.TransformSync>()
|
||||
.Where(x => x != null && x.IsReady && x.ReferenceSector != null))
|
||||
{
|
||||
QSBEventManager.FireEvent(EventNames.QSBSectorChange, item.NetId.Value, item.ReferenceSector);
|
||||
}
|
||||
|
||||
if (!server)
|
||||
{
|
||||
|
@ -24,16 +24,16 @@ namespace QSB.Player.Events
|
||||
{
|
||||
AboutId = player.PlayerId,
|
||||
PlayerName = player.Name,
|
||||
PlayerReady = player.IsReady,
|
||||
PlayerState = player.State
|
||||
PlayerState = player.PlayerStates
|
||||
};
|
||||
|
||||
public override void OnReceiveRemote(bool server, PlayerStateMessage message)
|
||||
{
|
||||
DebugLog.DebugWrite($"Received playerstate of player ID {message.AboutId}", MessageType.Info);
|
||||
QSBCore.UnityEvents.RunWhen(
|
||||
() => QSBPlayerManager.GetSyncObject<TransformSync.TransformSync>(message.AboutId) != null,
|
||||
() => QSBPlayerManager.HandleFullStateMessage(message));
|
||||
if (QSBPlayerManager.PlayerExists(message.AboutId))
|
||||
{
|
||||
QSBPlayerManager.HandleFullStateMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
35
QSB/Player/Patches/PlayerPatches.cs
Normal file
35
QSB/Player/Patches/PlayerPatches.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using QSB.Patches;
|
||||
|
||||
namespace QSB.Player.Patches
|
||||
{
|
||||
internal class PlayerPatches : QSBPatch
|
||||
{
|
||||
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
|
||||
|
||||
public override void DoPatches()
|
||||
{
|
||||
QSBCore.HarmonyHelper.AddPrefix<PlayerCrushedController>("CrushPlayer", typeof(PlayerPatches), nameof(PlayerCrushedController_CrushPlayer));
|
||||
QSBCore.HarmonyHelper.AddPrefix<PauseMenuManager>("OnExitToMainMenu", typeof(PlayerPatches), nameof(PauseMenuManager_OnExitToMainMenu));
|
||||
}
|
||||
|
||||
public override void DoUnpatches()
|
||||
{
|
||||
QSBCore.HarmonyHelper.Unpatch<PlayerCrushedController>("CrushPlayer");
|
||||
QSBCore.HarmonyHelper.Unpatch<PauseMenuManager>("OnExitToMainMenu");
|
||||
}
|
||||
|
||||
public static bool PlayerCrushedController_CrushPlayer()
|
||||
{
|
||||
// #CrushIt https://www.twitch.tv/videos/846916781?t=00h03m51s
|
||||
// this is what you get from me when you mix tiredness and a headache - jokes and references only i will get
|
||||
Locator.GetDeathManager().KillPlayer(DeathType.Crushed);
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void PauseMenuManager_OnExitToMainMenu()
|
||||
{
|
||||
QSBPlayerManager.LocalPlayer.PlayerStates.IsReady = false;
|
||||
QSBCore.HasWokenUp = false;
|
||||
}
|
||||
}
|
||||
}
|
@ -34,7 +34,7 @@ namespace QSB.Player
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!_isReady || !_player.IsReady)
|
||||
if (!_isReady || !_player.PlayerStates.IsReady)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
using QSB.Animation;
|
||||
using QSB.CampfireSync.WorldObjects;
|
||||
using QSB.Player.TransformSync;
|
||||
using QSB.ProbeSync;
|
||||
using QSB.QuantumSync;
|
||||
using QSB.RoastingSync;
|
||||
using QSB.Tools;
|
||||
using QSB.Utility;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
@ -13,9 +14,9 @@ namespace QSB.Player
|
||||
{
|
||||
public uint PlayerId { get; }
|
||||
public string Name { get; set; }
|
||||
public bool IsReady { get; set; }
|
||||
public PlayerHUDMarker HudMarker { get; set; }
|
||||
public State State { get; set; } // TODO : decide if this is worth it (instead of having seperate variables for each thing)
|
||||
public PlayerState PlayerStates { get; set; } = new PlayerState();
|
||||
public PlayerTransformSync TransformSync { get; set; }
|
||||
|
||||
// Body Objects
|
||||
public OWCamera Camera { get; set; }
|
||||
@ -48,8 +49,8 @@ namespace QSB.Player
|
||||
&& AnimationSync.CurrentType != AnimationType.PlayerUnsuited;
|
||||
|
||||
// Misc
|
||||
public bool IsInMoon;
|
||||
public bool IsInShrine;
|
||||
public bool IsInMoon; // TODO : move into PlayerStates?
|
||||
public bool IsInShrine; // TODO : move into PlayerStates?
|
||||
public IQSBQuantumObject EntangledObject;
|
||||
|
||||
public PlayerInfo(uint id)
|
||||
@ -58,37 +59,20 @@ namespace QSB.Player
|
||||
CurrentDialogueID = -1;
|
||||
}
|
||||
|
||||
public void UpdateState(State state, bool value)
|
||||
{
|
||||
var states = State;
|
||||
if (value)
|
||||
{
|
||||
FlagsHelper.Set(ref states, state);
|
||||
}
|
||||
else
|
||||
{
|
||||
FlagsHelper.Unset(ref states, state);
|
||||
}
|
||||
State = states;
|
||||
}
|
||||
|
||||
public void UpdateStateObjects()
|
||||
{
|
||||
if (OWInput.GetInputMode() == InputMode.None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
FlashLight?.UpdateState(FlagsHelper.IsSet(State, State.Flashlight));
|
||||
Translator?.ChangeEquipState(FlagsHelper.IsSet(State, State.Translator));
|
||||
ProbeLauncher?.ChangeEquipState(FlagsHelper.IsSet(State, State.ProbeLauncher));
|
||||
Signalscope?.ChangeEquipState(FlagsHelper.IsSet(State, State.Signalscope));
|
||||
FlashLight?.UpdateState(PlayerStates.FlashlightActive);
|
||||
Translator?.ChangeEquipState(PlayerStates.TranslatorEquipped);
|
||||
ProbeLauncher?.ChangeEquipState(PlayerStates.ProbeLauncherEquipped);
|
||||
Signalscope?.ChangeEquipState(PlayerStates.SignalscopeEquipped);
|
||||
QSBCore.UnityEvents.RunWhen(() => QSBPlayerManager.GetSyncObject<AnimationSync>(PlayerId) != null,
|
||||
() => QSBPlayerManager.GetSyncObject<AnimationSync>(PlayerId).SetSuitState(FlagsHelper.IsSet(State, State.Suit)));
|
||||
() => QSBPlayerManager.GetSyncObject<AnimationSync>(PlayerId).SetSuitState(PlayerStates.SuitedUp));
|
||||
}
|
||||
|
||||
public bool GetState(State state)
|
||||
=> FlagsHelper.IsSet(State, state);
|
||||
|
||||
private QSBTool GetToolByType(ToolType type)
|
||||
{
|
||||
return CameraBody?.GetComponentsInChildren<QSBTool>()
|
||||
|
14
QSB/Player/PlayerState.cs
Normal file
14
QSB/Player/PlayerState.cs
Normal file
@ -0,0 +1,14 @@
|
||||
namespace QSB.Player
|
||||
{
|
||||
public class PlayerState
|
||||
{
|
||||
public bool IsReady { get; set; }
|
||||
|
||||
public bool FlashlightActive { get; set; }
|
||||
public bool SuitedUp { get; set; }
|
||||
public bool ProbeLauncherEquipped { get; set; }
|
||||
public bool SignalscopeEquipped { get; set; }
|
||||
public bool TranslatorEquipped { get; set; }
|
||||
public bool ProbeActive { get; set; }
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
using OWML.Common;
|
||||
using QSB.Player.Events;
|
||||
using QSB.Player.TransformSync;
|
||||
using QSB.Tools;
|
||||
using QSB.TransformSync;
|
||||
using QSB.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -78,9 +78,8 @@ namespace QSB.Player
|
||||
{
|
||||
var player = GetPlayer(message.AboutId);
|
||||
player.Name = message.PlayerName;
|
||||
player.IsReady = message.PlayerReady;
|
||||
player.State = message.PlayerState;
|
||||
if (LocalPlayer.IsReady)
|
||||
player.PlayerStates = message.PlayerState;
|
||||
if (LocalPlayer.PlayerStates.IsReady)
|
||||
{
|
||||
player.UpdateStateObjects();
|
||||
}
|
||||
|
@ -1,16 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace QSB.Player
|
||||
{
|
||||
[Flags]
|
||||
public enum State
|
||||
{
|
||||
None = 0,
|
||||
Flashlight = 1,
|
||||
Suit = 2,
|
||||
ProbeLauncher = 4,
|
||||
Signalscope = 8,
|
||||
Translator = 16,
|
||||
ProbeActive = 32
|
||||
}
|
||||
}
|
@ -1,14 +1,14 @@
|
||||
using QSB.Events;
|
||||
using QSB.Player;
|
||||
using QSB.Tools;
|
||||
using QSB.TransformSync;
|
||||
using QSB.Utility;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QSB.TransformSync
|
||||
namespace QSB.Player.TransformSync
|
||||
{
|
||||
public class PlayerCameraSync : TransformSync
|
||||
public class PlayerCameraSync : QSBNetworkTransform
|
||||
{
|
||||
protected override Transform InitLocalTransform()
|
||||
protected override GameObject InitLocalTransform()
|
||||
{
|
||||
SectorSync.SetSectorDetector(Locator.GetPlayerSectorDetector());
|
||||
var body = Locator.GetPlayerCamera().gameObject.transform;
|
||||
@ -16,15 +16,15 @@ namespace QSB.TransformSync
|
||||
Player.Camera = Locator.GetPlayerCamera();
|
||||
Player.CameraBody = body.gameObject;
|
||||
|
||||
Player.IsReady = true;
|
||||
Player.PlayerStates.IsReady = true;
|
||||
QSBEventManager.FireEvent(EventNames.QSBPlayerReady, true);
|
||||
DebugLog.DebugWrite("PlayerCameraSync init done - Request state!");
|
||||
QSBEventManager.FireEvent(EventNames.QSBPlayerStatesRequest);
|
||||
|
||||
return body;
|
||||
return body.gameObject;
|
||||
}
|
||||
|
||||
protected override Transform InitRemoteTransform()
|
||||
protected override GameObject InitRemoteTransform()
|
||||
{
|
||||
var body = new GameObject("RemotePlayerCamera");
|
||||
|
||||
@ -39,16 +39,7 @@ namespace QSB.TransformSync
|
||||
Player.Camera = owcamera;
|
||||
Player.CameraBody = body;
|
||||
|
||||
return body.transform;
|
||||
}
|
||||
|
||||
private void OnRenderObject()
|
||||
{
|
||||
if (!QSBCore.HasWokenUp || !Player.IsReady || !QSBCore.DebugMode || !QSBCore.ShowLinesInDebug)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Popcron.Gizmos.Frustum(Player.Camera);
|
||||
return body;
|
||||
}
|
||||
|
||||
public override bool IsReady => Locator.GetPlayerTransform() != null
|
@ -1,11 +1,11 @@
|
||||
using QSB.Animation;
|
||||
using QSB.Instruments;
|
||||
using QSB.Player;
|
||||
using QSB.TransformSync;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QSB.TransformSync
|
||||
namespace QSB.Player.TransformSync
|
||||
{
|
||||
public class PlayerTransformSync : TransformSync
|
||||
public class PlayerTransformSync : QSBNetworkTransform
|
||||
{
|
||||
public static PlayerTransformSync LocalInstance { get; private set; }
|
||||
|
||||
@ -14,6 +14,12 @@ namespace QSB.TransformSync
|
||||
public override void OnStartLocalPlayer()
|
||||
=> LocalInstance = this;
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
base.Start();
|
||||
Player.TransformSync = this;
|
||||
}
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
QSBPlayerManager.OnRemovePlayer?.Invoke(PlayerId);
|
||||
@ -28,7 +34,7 @@ namespace QSB.TransformSync
|
||||
private Transform GetPlayerModel() =>
|
||||
Locator.GetPlayerTransform().Find("Traveller_HEA_Player_v2");
|
||||
|
||||
protected override Transform InitLocalTransform()
|
||||
protected override GameObject InitLocalTransform()
|
||||
{
|
||||
SectorSync.SetSectorDetector(Locator.GetPlayerSectorDetector());
|
||||
var body = GetPlayerModel();
|
||||
@ -38,10 +44,10 @@ namespace QSB.TransformSync
|
||||
|
||||
Player.Body = body.gameObject;
|
||||
|
||||
return body;
|
||||
return body.gameObject;
|
||||
}
|
||||
|
||||
protected override Transform InitRemoteTransform()
|
||||
protected override GameObject InitRemoteTransform()
|
||||
{
|
||||
var body = Instantiate(GetPlayerModel());
|
||||
|
||||
@ -55,23 +61,13 @@ namespace QSB.TransformSync
|
||||
|
||||
Player.Body = body.gameObject;
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
private void OnRenderObject()
|
||||
{
|
||||
if (!QSBCore.HasWokenUp || !Player.IsReady || !QSBCore.DebugMode || !QSBCore.ShowLinesInDebug)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Popcron.Gizmos.Line(ReferenceSector.Position, Player.Body.transform.position, Color.blue, true);
|
||||
Popcron.Gizmos.Sphere(ReferenceSector.Position, 5f, Color.cyan);
|
||||
return body.gameObject;
|
||||
}
|
||||
|
||||
public override bool IsReady => Locator.GetPlayerTransform() != null
|
||||
&& Player != null
|
||||
&& QSBPlayerManager.PlayerExists(Player.PlayerId)
|
||||
&& Player.IsReady
|
||||
&& Player.PlayerStates.IsReady
|
||||
&& NetId.Value != uint.MaxValue
|
||||
&& NetId.Value != 0U;
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
using QSB.Messaging;
|
||||
using QSB.Player;
|
||||
|
||||
namespace QSB.Tools.Events
|
||||
namespace QSB.ProbeSync.Events
|
||||
{
|
||||
public class PlayerProbeEvent : QSBEvent<ToggleMessage>
|
||||
{
|
||||
@ -32,11 +32,11 @@ namespace QSB.Tools.Events
|
||||
public override void OnReceiveRemote(bool server, ToggleMessage message)
|
||||
{
|
||||
var player = QSBPlayerManager.GetPlayer(message.AboutId);
|
||||
player.UpdateState(State.ProbeActive, message.ToggleValue);
|
||||
player.PlayerStates.ProbeActive = message.ToggleValue;
|
||||
player.Probe?.SetState(message.ToggleValue);
|
||||
}
|
||||
|
||||
public override void OnReceiveLocal(bool server, ToggleMessage message) =>
|
||||
QSBPlayerManager.LocalPlayer.UpdateState(State.ProbeActive, message.ToggleValue);
|
||||
QSBPlayerManager.LocalPlayer.PlayerStates.ProbeActive = message.ToggleValue;
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
using QSB.Messaging;
|
||||
using QSB.Player;
|
||||
|
||||
namespace QSB.Tools.Events
|
||||
namespace QSB.ProbeSync.Events
|
||||
{
|
||||
public class PlayerProbeLauncherEvent : QSBEvent<ToggleMessage>
|
||||
{
|
||||
@ -32,11 +32,11 @@ namespace QSB.Tools.Events
|
||||
public override void OnReceiveRemote(bool server, ToggleMessage message)
|
||||
{
|
||||
var player = QSBPlayerManager.GetPlayer(message.AboutId);
|
||||
player.UpdateState(State.ProbeLauncher, message.ToggleValue);
|
||||
player.PlayerStates.ProbeLauncherEquipped = message.ToggleValue;
|
||||
player.ProbeLauncher?.ChangeEquipState(message.ToggleValue);
|
||||
}
|
||||
|
||||
public override void OnReceiveLocal(bool server, ToggleMessage message) =>
|
||||
QSBPlayerManager.LocalPlayer.UpdateState(State.ProbeLauncher, message.ToggleValue);
|
||||
QSBPlayerManager.LocalPlayer.PlayerStates.ProbeLauncherEquipped = message.ToggleValue;
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
using QSB.Utility;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QSB.Tools
|
||||
namespace QSB.ProbeSync
|
||||
{
|
||||
public class QSBProbe : MonoBehaviour
|
||||
{
|
61
QSB/ProbeSync/TransformSync/PlayerProbeSync.cs
Normal file
61
QSB/ProbeSync/TransformSync/PlayerProbeSync.cs
Normal file
@ -0,0 +1,61 @@
|
||||
using OWML.Common;
|
||||
using QSB.Player;
|
||||
using QSB.Tools;
|
||||
using QSB.TransformSync;
|
||||
using QSB.Utility;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QSB.ProbeSync.TransformSync
|
||||
{
|
||||
public class PlayerProbeSync : QSBNetworkTransform
|
||||
{
|
||||
public static PlayerProbeSync LocalInstance { get; private set; }
|
||||
|
||||
protected override float DistanceLeeway => 10f;
|
||||
|
||||
public override void OnStartAuthority()
|
||||
=> LocalInstance = this;
|
||||
|
||||
private Transform GetProbe() =>
|
||||
Locator.GetProbe().transform.Find("CameraPivot").Find("Geometry");
|
||||
|
||||
protected override GameObject InitLocalTransform()
|
||||
{
|
||||
SectorSync.SetSectorDetector(Locator.GetProbe().GetSectorDetector());
|
||||
var body = GetProbe();
|
||||
|
||||
Player.ProbeBody = body.gameObject;
|
||||
|
||||
return body.gameObject;
|
||||
}
|
||||
|
||||
protected override GameObject InitRemoteTransform()
|
||||
{
|
||||
var probe = GetProbe();
|
||||
|
||||
if (probe == null)
|
||||
{
|
||||
DebugLog.ToConsole("Error - Probe is null!", MessageType.Error);
|
||||
return default;
|
||||
}
|
||||
|
||||
var body = probe.InstantiateInactive();
|
||||
body.name = "RemoteProbeTransform";
|
||||
|
||||
Destroy(body.GetComponentInChildren<ProbeAnimatorController>());
|
||||
|
||||
PlayerToolsManager.CreateProbe(body, Player);
|
||||
|
||||
Player.ProbeBody = body.gameObject;
|
||||
|
||||
return body.gameObject;
|
||||
}
|
||||
|
||||
public override bool IsReady => Locator.GetProbe() != null
|
||||
&& Player != null
|
||||
&& QSBPlayerManager.PlayerExists(Player.PlayerId)
|
||||
&& Player.PlayerStates.IsReady
|
||||
&& NetId.Value != uint.MaxValue
|
||||
&& NetId.Value != 0U;
|
||||
}
|
||||
}
|
@ -74,7 +74,7 @@
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.ParticleSystemModule">
|
||||
<HintPath>D:\EpicGames\OuterWilds\OuterWilds_Data\Managed\UnityEngine.ParticleSystemModule.dll</HintPath>
|
||||
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.ParticleSystemModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.PhysicsModule, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
@ -142,6 +142,8 @@
|
||||
<Compile Include="Instruments\QSBCamera\CameraMode.cs" />
|
||||
<Compile Include="Instruments\InstrumentsManager.cs" />
|
||||
<Compile Include="Messaging\BoolMessage.cs" />
|
||||
<Compile Include="Player\Patches\PlayerPatches.cs" />
|
||||
<Compile Include="Player\PlayerState.cs" />
|
||||
<Compile Include="PoolSync\CustomNomaiRemoteCameraPlatform.cs" />
|
||||
<Compile Include="PoolSync\CustomNomaiRemoteCameraStreaming.cs" />
|
||||
<Compile Include="ItemSync\Events\DropItemEvent.cs" />
|
||||
@ -228,7 +230,8 @@
|
||||
<Compile Include="StatueSync\Events\StartStatueMessage.cs" />
|
||||
<Compile Include="StatueSync\Patches\StatuePatches.cs" />
|
||||
<Compile Include="StatueSync\StatueManager.cs" />
|
||||
<Compile Include="TransformSync\RoastingStickTransformSync.cs" />
|
||||
<Compile Include="RoastingSync\TransformSync\RoastingStickTransformSync.cs" />
|
||||
<Compile Include="TransformSync\QSBNetworkTransform.cs" />
|
||||
<Compile Include="TranslationSync\Events\SetAsTranslatedEvent.cs" />
|
||||
<Compile Include="TranslationSync\Events\SetAsTranslatedMessage.cs" />
|
||||
<Compile Include="TranslationSync\NomaiTextType.cs" />
|
||||
@ -242,17 +245,16 @@
|
||||
<Compile Include="TimeSync\Patches\WakeUpPatches.cs" />
|
||||
<Compile Include="Tools\Events\PlayerFlashlightEvent.cs" />
|
||||
<Compile Include="Player\Events\PlayerJoinEvent.cs" />
|
||||
<Compile Include="Tools\Events\PlayerProbeEvent.cs" />
|
||||
<Compile Include="ProbeSync\Events\PlayerProbeEvent.cs" />
|
||||
<Compile Include="Player\Events\PlayerReadyEvent.cs" />
|
||||
<Compile Include="TransformSync\NomaiOrbTransformSync.cs" />
|
||||
<Compile Include="Player\Events\PlayerSectorEvent.cs" />
|
||||
<Compile Include="OrbSync\TransformSync\NomaiOrbTransformSync.cs" />
|
||||
<Compile Include="Player\Events\PlayerStatesRequestEvent.cs" />
|
||||
<Compile Include="Animation\Events\PlayerSuitEvent.cs" />
|
||||
<Compile Include="TimeSync\Events\ServerTimeEvent.cs" />
|
||||
<Compile Include="GeyserSync\Events\GeyserEvent.cs" />
|
||||
<Compile Include="GeyserSync\GeyserManager.cs" />
|
||||
<Compile Include="GeyserSync\WorldObjects\QSBGeyser.cs" />
|
||||
<Compile Include="Tools\Events\PlayerProbeLauncherEvent.cs" />
|
||||
<Compile Include="ProbeSync\Events\PlayerProbeLauncherEvent.cs" />
|
||||
<Compile Include="Tools\Events\PlayerSignalscopeEvent.cs" />
|
||||
<Compile Include="Tools\Events\PlayerTranslatorEvent.cs" />
|
||||
<Compile Include="Events\QSBEvent.cs" />
|
||||
@ -260,7 +262,6 @@
|
||||
<Compile Include="Messaging\ToggleMessage.cs" />
|
||||
<Compile Include="SectorSync\WorldObjects\QSBSector.cs" />
|
||||
<Compile Include="SectorSync\SectorSync.cs" />
|
||||
<Compile Include="TransformSync\TransformSync.cs" />
|
||||
<Compile Include="Utility\CustomCallbacks.cs" />
|
||||
<Compile Include="Utility\DebugBoxManager.cs" />
|
||||
<Compile Include="Utility\DebugZOverride.cs" />
|
||||
@ -286,10 +287,10 @@
|
||||
<Compile Include="WorldSync\Events\EnumWorldObjectMessage.cs" />
|
||||
<Compile Include="WorldSync\Events\WorldObjectMessage.cs" />
|
||||
<Compile Include="Tools\QSBFlashlight.cs" />
|
||||
<Compile Include="Tools\QSBProbe.cs" />
|
||||
<Compile Include="ProbeSync\QSBProbe.cs" />
|
||||
<Compile Include="Tools\QSBTool.cs" />
|
||||
<Compile Include="Tools\ToolType.cs" />
|
||||
<Compile Include="TransformSync\PlayerProbeSync.cs" />
|
||||
<Compile Include="ProbeSync\TransformSync\PlayerProbeSync.cs" />
|
||||
<Compile Include="Utility\DebugActions.cs" />
|
||||
<Compile Include="Events\QSBEventManager.cs" />
|
||||
<Compile Include="Player\Events\PlayerStateMessage.cs" />
|
||||
@ -299,22 +300,20 @@
|
||||
<Compile Include="Messaging\MessageHandler.cs" />
|
||||
<Compile Include="Events\EventType.cs" />
|
||||
<Compile Include="Player\PlayerInfo.cs" />
|
||||
<Compile Include="Player\State.cs" />
|
||||
<Compile Include="DeathSync\RespawnOnDeath.cs" />
|
||||
<Compile Include="Player\QSBPlayerManager.cs" />
|
||||
<Compile Include="TransformSync\PlayerCameraSync.cs" />
|
||||
<Compile Include="Utility\FlagsHelper.cs" />
|
||||
<Compile Include="Player\TransformSync\PlayerCameraSync.cs" />
|
||||
<Compile Include="Player\PlayerHUDMarker.cs" />
|
||||
<Compile Include="Tools\PlayerToolsManager.cs" />
|
||||
<Compile Include="Utility\QuaternionHelper.cs" />
|
||||
<Compile Include="TimeSync\PreserveTimeScale.cs" />
|
||||
<Compile Include="TransformSync\ShipTransformSync.cs" />
|
||||
<Compile Include="ShipSync\TransformSync\ShipTransformSync.cs" />
|
||||
<Compile Include="SectorSync\QSBSectorManager.cs" />
|
||||
<Compile Include="TimeSync\Events\ServerTimeMessage.cs" />
|
||||
<Compile Include="TimeSync\WakeUpSync.cs" />
|
||||
<Compile Include="QSBNetworkManager.cs" />
|
||||
<Compile Include="QSBCore.cs" />
|
||||
<Compile Include="TransformSync\PlayerTransformSync.cs" />
|
||||
<Compile Include="Player\TransformSync\PlayerTransformSync.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="WorldSync\FactReveal.cs" />
|
||||
<Compile Include="WorldSync\IWorldObject.cs" />
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<GameDir>D:\EpicGames\OuterWilds</GameDir>
|
||||
<GameDir>E:\Epic\Epic Games\OuterWilds</GameDir>
|
||||
<OwmlDir>C:\Users\Henry\AppData\Roaming\OuterWildsModManager\OWML</OwmlDir>
|
||||
<ProjectView>ShowAllFiles</ProjectView>
|
||||
</PropertyGroup>
|
||||
|
@ -9,13 +9,14 @@ using QSB.ItemSync;
|
||||
using QSB.OrbSync;
|
||||
using QSB.Patches;
|
||||
using QSB.Player;
|
||||
using QSB.Player.TransformSync;
|
||||
using QSB.PoolSync;
|
||||
using QSB.ProbeSync.TransformSync;
|
||||
using QSB.QuantumSync;
|
||||
using QSB.QuantumSync.WorldObjects;
|
||||
using QSB.SectorSync;
|
||||
using QSB.StatueSync;
|
||||
using QSB.TimeSync;
|
||||
using QSB.TransformSync;
|
||||
using QSB.TranslationSync;
|
||||
using QSB.Utility;
|
||||
using QSB.WorldSync;
|
||||
@ -146,13 +147,9 @@ namespace QSB
|
||||
}
|
||||
|
||||
var offset3 = 10f;
|
||||
GUI.Label(new Rect(420, offset3, 200f, 20f), $"Current synced sector :");
|
||||
GUI.Label(new Rect(420, offset3, 400f, 20f), $"Current sector : {PlayerTransformSync.LocalInstance.ReferenceSector.Name}");
|
||||
offset3 += _debugLineSpacing;
|
||||
var sector = PlayerTransformSync.LocalInstance.ReferenceSector;
|
||||
var text = sector == null
|
||||
? "NULL SECTOR"
|
||||
: $"{sector.AttachedObject.name} : {sector.IsFakeSector}";
|
||||
GUI.Label(new Rect(420, offset3, 400f, 20f), $"- {text}");
|
||||
GUI.Label(new Rect(420, offset3, 400f, 20f), $"Probe sector : {PlayerProbeSync.LocalInstance.ReferenceSector.Name}");
|
||||
offset3 += _debugLineSpacing;
|
||||
|
||||
var offset2 = 10f;
|
||||
@ -169,16 +166,14 @@ namespace QSB
|
||||
return;
|
||||
}
|
||||
|
||||
GUI.Label(new Rect(220, offset, 200f, 20f), $"QM Illuminated : {Locator.GetQuantumMoon().IsIlluminated()}");
|
||||
GUI.Label(new Rect(220, offset, 200f, 20f), $"Probe Active : {Locator.GetProbe().gameObject.activeInHierarchy}");
|
||||
offset += _debugLineSpacing;
|
||||
GUI.Label(new Rect(220, offset, 200f, 20f), $"Shrine player in dark? : {QuantumManager.Instance.Shrine.IsPlayerInDarkness()}");
|
||||
GUI.Label(new Rect(220, offset, 200f, 20f), $"Player positions :");
|
||||
offset += _debugLineSpacing;
|
||||
GUI.Label(new Rect(220, offset, 200f, 20f), $"QM Visible by :");
|
||||
offset += _debugLineSpacing;
|
||||
var tracker = Locator.GetQuantumMoon().GetValue<ShapeVisibilityTracker>("_visibilityTracker");
|
||||
foreach (var player in QSBPlayerManager.GetPlayersWithCameras())
|
||||
foreach (var player in QSBPlayerManager.PlayerList.Where(x => x.PlayerStates.IsReady))
|
||||
{
|
||||
GUI.Label(new Rect(220, offset, 200f, 20f), $" - {player.PlayerId} : {tracker.GetType().GetMethod("IsInFrustum", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(tracker, new object[] { player.Camera.GetFrustumPlanes() })}");
|
||||
var networkTransform = player.TransformSync;
|
||||
GUI.Label(new Rect(220, offset, 400f, 20f), $"- {player.PlayerId} : {networkTransform.transform.localPosition} from {networkTransform.ReferenceSector.Name}");
|
||||
offset += _debugLineSpacing;
|
||||
}
|
||||
|
||||
|
@ -4,11 +4,15 @@ using QSB.Animation;
|
||||
using QSB.DeathSync;
|
||||
using QSB.Events;
|
||||
using QSB.Instruments;
|
||||
using QSB.OrbSync.TransformSync;
|
||||
using QSB.Patches;
|
||||
using QSB.Player;
|
||||
using QSB.Player.TransformSync;
|
||||
using QSB.PoolSync;
|
||||
using QSB.ProbeSync.TransformSync;
|
||||
using QSB.RoastingSync.TransformSync;
|
||||
using QSB.ShipSync.TransformSync;
|
||||
using QSB.TimeSync;
|
||||
using QSB.TransformSync;
|
||||
using QSB.Utility;
|
||||
using QSB.WorldSync;
|
||||
using QuantumUNET;
|
||||
@ -100,8 +104,6 @@ namespace QSB
|
||||
|
||||
private void SetupNetworkTransform(GameObject go)
|
||||
{
|
||||
var trans = go.AddComponent<QNetworkTransform>();
|
||||
trans.SyncRotationAxis = QNetworkTransform.AxisSyncMode.AxisXYZ;
|
||||
foreach (var item in go.GetComponents<NetworkTransformChild>())
|
||||
{
|
||||
var child = go.AddComponent<QNetworkTransformChild>();
|
||||
|
@ -1,13 +1,13 @@
|
||||
using OWML.Utils;
|
||||
using QSB.Player;
|
||||
using QSB.RoastingSync;
|
||||
using QSB.TransformSync;
|
||||
using QSB.Utility;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QSB.TransformSync
|
||||
namespace QSB.RoastingSync.TransformSync
|
||||
{
|
||||
internal class RoastingStickTransformSync : TransformSync
|
||||
internal class RoastingStickTransformSync : QSBNetworkTransform
|
||||
{
|
||||
private Transform _stickTip;
|
||||
private Transform _networkStickTip => gameObject.transform.GetChild(0);
|
||||
@ -18,15 +18,15 @@ namespace QSB.TransformSync
|
||||
private Transform GetPivot()
|
||||
=> Resources.FindObjectsOfTypeAll<RoastingStickController>().First().transform.Find("Stick_Root/Stick_Pivot");
|
||||
|
||||
protected override Transform InitLocalTransform()
|
||||
protected override GameObject InitLocalTransform()
|
||||
{
|
||||
var pivot = GetPivot();
|
||||
Player.RoastingStick = pivot.gameObject;
|
||||
_stickTip = pivot.Find("Stick_Tip");
|
||||
return pivot;
|
||||
return pivot.gameObject;
|
||||
}
|
||||
|
||||
protected override Transform InitRemoteTransform()
|
||||
protected override GameObject InitRemoteTransform()
|
||||
{
|
||||
var newPivot = Instantiate(GetPivot());
|
||||
newPivot.parent = null;
|
||||
@ -56,7 +56,7 @@ namespace QSB.TransformSync
|
||||
Player.Marshmallow = newMarshmallow;
|
||||
mallowRoot.gameObject.SetActive(true);
|
||||
_stickTip = newPivot.Find("Stick_Tip");
|
||||
return newPivot;
|
||||
return newPivot.gameObject;
|
||||
}
|
||||
|
||||
protected override void UpdateTransform()
|
||||
@ -82,7 +82,7 @@ namespace QSB.TransformSync
|
||||
public override bool IsReady => Locator.GetPlayerTransform() != null
|
||||
&& Player != null
|
||||
&& QSBPlayerManager.PlayerExists(Player.PlayerId)
|
||||
&& Player.IsReady
|
||||
&& Player.PlayerStates.IsReady
|
||||
&& NetId.Value != uint.MaxValue
|
||||
&& NetId.Value != 0U;
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
using OWML.Common;
|
||||
using QSB.Events;
|
||||
using QSB.Player;
|
||||
using QSB.SectorSync.WorldObjects;
|
||||
using QSB.TransformSync;
|
||||
using QSB.Utility;
|
||||
using QSB.WorldSync;
|
||||
using System.Collections.Generic;
|
||||
@ -21,8 +20,19 @@ namespace QSB.SectorSync
|
||||
|
||||
public void Invoke()
|
||||
{
|
||||
QSBPlayerManager.GetSyncObjects<TransformSync.TransformSync>()
|
||||
.Where(x => x.HasAuthority).ToList().ForEach(CheckTransformSyncSector);
|
||||
foreach (var sync in QSBNetworkTransform.NetworkTransformList)
|
||||
{
|
||||
if (sync.AttachedObject == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (sync.HasAuthority
|
||||
&& sync.AttachedObject.activeInHierarchy
|
||||
&& sync.IsReady)
|
||||
{
|
||||
CheckTransformSyncSector(sync);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Awake()
|
||||
@ -54,14 +64,10 @@ namespace QSB.SectorSync
|
||||
IsReady = QSBWorldSync.GetWorldObjects<QSBSector>().Any();
|
||||
}
|
||||
|
||||
private void CheckTransformSyncSector(TransformSync.TransformSync transformSync)
|
||||
private void CheckTransformSyncSector(QSBNetworkTransform transformSync)
|
||||
{
|
||||
var syncedTransform = transformSync.SyncedTransform;
|
||||
if (syncedTransform == null || syncedTransform.position == Vector3.zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var closestSector = transformSync.SectorSync.GetClosestSector(syncedTransform);
|
||||
var attachedObject = transformSync.AttachedObject;
|
||||
var closestSector = transformSync.SectorSync.GetClosestSector(attachedObject.transform);
|
||||
if (closestSector == default(QSBSector))
|
||||
{
|
||||
return;
|
||||
@ -71,10 +77,6 @@ namespace QSB.SectorSync
|
||||
return;
|
||||
}
|
||||
transformSync.SetReferenceSector(closestSector);
|
||||
SendSector(transformSync.NetId.Value, closestSector);
|
||||
}
|
||||
|
||||
private void SendSector(uint id, QSBSector sector) =>
|
||||
QSBEventManager.FireEvent(EventNames.QSBSectorChange, id, sector);
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using OWML.Common;
|
||||
using OWML.Utils;
|
||||
using QSB.SectorSync.WorldObjects;
|
||||
using QSB.Utility;
|
||||
using QSB.WorldSync;
|
||||
@ -12,6 +13,7 @@ namespace QSB.SectorSync
|
||||
{
|
||||
public List<QSBSector> SectorList = new List<QSBSector>();
|
||||
|
||||
private OWRigidbody _attachedOWRigidbody;
|
||||
private SectorDetector _sectorDetector;
|
||||
|
||||
private void OnDestroy()
|
||||
@ -33,6 +35,12 @@ namespace QSB.SectorSync
|
||||
_sectorDetector = detector;
|
||||
_sectorDetector.OnEnterSector += AddSector;
|
||||
_sectorDetector.OnExitSector += RemoveSector;
|
||||
|
||||
_attachedOWRigidbody = _sectorDetector.GetValue<OWRigidbody>("_attachedRigidbody");
|
||||
if (_attachedOWRigidbody == null)
|
||||
{
|
||||
DebugLog.ToConsole($"Warning - OWRigidbody for {_sectorDetector.name} is null!", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddSector(Sector sector)
|
||||
@ -94,9 +102,12 @@ namespace QSB.SectorSync
|
||||
{
|
||||
return default;
|
||||
}
|
||||
//var ordered = activeNotNullNotBlacklisted
|
||||
//.OrderBy(sector => Vector3.Distance(sector.Position, trans.position))
|
||||
//.ThenBy(sector => GetRelativeVelocity(sector, _attachedOWRigidbody))
|
||||
//.ThenBy(sector => GetRadius(sector));
|
||||
var ordered = activeNotNullNotBlacklisted
|
||||
.OrderBy(sector => Vector3.Distance(sector.Position, trans.position))
|
||||
.ThenBy(sector => GetRadius(sector));
|
||||
.OrderBy(sector => CalculateSectorScore(sector, trans, _attachedOWRigidbody));
|
||||
|
||||
if (
|
||||
// if any fake sectors are *roughly* in the same place as other sectors - we want fake sectors to override other sectors
|
||||
@ -111,7 +122,16 @@ namespace QSB.SectorSync
|
||||
return ordered.FirstOrDefault();
|
||||
}
|
||||
|
||||
private float GetRadius(QSBSector sector)
|
||||
public static float CalculateSectorScore(QSBSector sector, Transform trans, OWRigidbody rigidbody)
|
||||
{
|
||||
var distance = Vector3.Distance(sector.Position, trans.position); // want to be small
|
||||
var radius = GetRadius(sector); // want to be small
|
||||
var velocity = GetRelativeVelocity(sector, rigidbody); // want to be small
|
||||
|
||||
return (distance * distance) + (radius * radius) + (velocity * velocity);
|
||||
}
|
||||
|
||||
public static float GetRadius(QSBSector sector)
|
||||
{
|
||||
if (sector == null)
|
||||
{
|
||||
@ -128,5 +148,17 @@ namespace QSB.SectorSync
|
||||
}
|
||||
return 0f;
|
||||
}
|
||||
|
||||
public static float GetRelativeVelocity(QSBSector sector, OWRigidbody rigidbody)
|
||||
{
|
||||
var sectorRigidBody = sector.AttachedObject.GetOWRigidbody();
|
||||
if (sectorRigidBody != null && rigidbody != null)
|
||||
{
|
||||
var relativeVelocity = sectorRigidBody.GetRelativeVelocity(rigidbody);
|
||||
var relativeVelocityMagnitude = relativeVelocity.sqrMagnitude; // Remember this is squared for efficiency!
|
||||
return relativeVelocityMagnitude;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -49,6 +49,7 @@ namespace QSB.SectorSync.WorldObjects
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (AttachedObject.name == "Sector_Shuttle" || AttachedObject.name == "Sector_NomaiShuttleInterior")
|
||||
{
|
||||
if (QSBSceneManager.CurrentScene == OWScene.SolarSystem)
|
||||
|
@ -1,19 +1,22 @@
|
||||
using QSB.Player;
|
||||
using QSB.TransformSync;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QSB.TransformSync
|
||||
namespace QSB.ShipSync.TransformSync
|
||||
{
|
||||
public class ShipTransformSync : TransformSync
|
||||
public class ShipTransformSync : QSBNetworkTransform
|
||||
{
|
||||
protected override float DistanceLeeway => 20f;
|
||||
|
||||
private Transform GetShipModel() => Locator.GetShipTransform();
|
||||
|
||||
protected override Transform InitLocalTransform()
|
||||
protected override GameObject InitLocalTransform()
|
||||
{
|
||||
SectorSync.SetSectorDetector(Locator.GetShipDetector().GetComponent<SectorDetector>());
|
||||
return GetShipModel().Find("Module_Cockpit/Geo_Cockpit/Cockpit_Geometry/Cockpit_Exterior");
|
||||
return GetShipModel().Find("Module_Cockpit/Geo_Cockpit/Cockpit_Geometry/Cockpit_Exterior").gameObject;
|
||||
}
|
||||
|
||||
protected override Transform InitRemoteTransform()
|
||||
protected override GameObject InitRemoteTransform()
|
||||
{
|
||||
var shipModel = GetShipModel();
|
||||
|
||||
@ -38,13 +41,13 @@ namespace QSB.TransformSync
|
||||
= landingGearRight.localPosition
|
||||
+= Vector3.up * 3.762f;
|
||||
|
||||
return remoteTransform;
|
||||
return remoteTransform.gameObject;
|
||||
}
|
||||
|
||||
public override bool IsReady => GetShipModel() != null
|
||||
&& Player != null
|
||||
&& QSBPlayerManager.PlayerExists(Player.PlayerId)
|
||||
&& Player.IsReady
|
||||
&& Player.PlayerStates.IsReady
|
||||
&& NetId.Value != uint.MaxValue
|
||||
&& NetId.Value != 0U;
|
||||
}
|
@ -32,11 +32,11 @@ namespace QSB.Tools.Events
|
||||
public override void OnReceiveRemote(bool server, ToggleMessage message)
|
||||
{
|
||||
var player = QSBPlayerManager.GetPlayer(message.AboutId);
|
||||
player.UpdateState(State.Flashlight, message.ToggleValue);
|
||||
player.PlayerStates.FlashlightActive = message.ToggleValue;
|
||||
player.FlashLight?.UpdateState(message.ToggleValue);
|
||||
}
|
||||
|
||||
public override void OnReceiveLocal(bool server, ToggleMessage message) =>
|
||||
QSBPlayerManager.LocalPlayer.UpdateState(State.Flashlight, message.ToggleValue);
|
||||
QSBPlayerManager.LocalPlayer.PlayerStates.FlashlightActive = message.ToggleValue;
|
||||
}
|
||||
}
|
@ -32,11 +32,11 @@ namespace QSB.Tools.Events
|
||||
public override void OnReceiveRemote(bool server, ToggleMessage message)
|
||||
{
|
||||
var player = QSBPlayerManager.GetPlayer(message.AboutId);
|
||||
player.UpdateState(State.Signalscope, message.ToggleValue);
|
||||
player.PlayerStates.SignalscopeEquipped = message.ToggleValue;
|
||||
player.Signalscope?.ChangeEquipState(message.ToggleValue);
|
||||
}
|
||||
|
||||
public override void OnReceiveLocal(bool server, ToggleMessage message) =>
|
||||
QSBPlayerManager.LocalPlayer.UpdateState(State.Signalscope, message.ToggleValue);
|
||||
QSBPlayerManager.LocalPlayer.PlayerStates.SignalscopeEquipped = message.ToggleValue;
|
||||
}
|
||||
}
|
@ -32,11 +32,11 @@ namespace QSB.Tools.Events
|
||||
public override void OnReceiveRemote(bool server, ToggleMessage message)
|
||||
{
|
||||
var player = QSBPlayerManager.GetPlayer(message.AboutId);
|
||||
player.UpdateState(State.Translator, message.ToggleValue);
|
||||
player.PlayerStates.TranslatorEquipped = message.ToggleValue;
|
||||
player.Translator?.ChangeEquipState(message.ToggleValue);
|
||||
}
|
||||
|
||||
public override void OnReceiveLocal(bool server, ToggleMessage message) =>
|
||||
QSBPlayerManager.LocalPlayer.UpdateState(State.Translator, message.ToggleValue);
|
||||
QSBPlayerManager.LocalPlayer.PlayerStates.TranslatorEquipped = message.ToggleValue;
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
using OWML.Utils;
|
||||
using QSB.Player;
|
||||
using QSB.ProbeSync;
|
||||
using QSB.Utility;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
@ -1,95 +0,0 @@
|
||||
using OWML.Common;
|
||||
using QSB.Player;
|
||||
using QSB.Tools;
|
||||
using QSB.Utility;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QSB.TransformSync
|
||||
{
|
||||
public class PlayerProbeSync : TransformSync
|
||||
{
|
||||
private Transform _disabledSocket;
|
||||
|
||||
private Transform GetProbe() =>
|
||||
Locator.GetProbe().transform.Find("CameraPivot").Find("Geometry");
|
||||
|
||||
protected override Transform InitLocalTransform()
|
||||
{
|
||||
SectorSync.SetSectorDetector(Locator.GetProbe().GetSectorDetector());
|
||||
var body = GetProbe();
|
||||
|
||||
SetSocket(Player.CameraBody.transform);
|
||||
Player.ProbeBody = body.gameObject;
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
protected override Transform InitRemoteTransform()
|
||||
{
|
||||
var probe = GetProbe();
|
||||
|
||||
if (probe == null)
|
||||
{
|
||||
DebugLog.ToConsole("Error - Probe is null!", MessageType.Error);
|
||||
return default;
|
||||
}
|
||||
|
||||
var body = probe.InstantiateInactive();
|
||||
body.name = "RemoteProbeTransform";
|
||||
|
||||
Destroy(body.GetComponentInChildren<ProbeAnimatorController>());
|
||||
|
||||
PlayerToolsManager.CreateProbe(body, Player);
|
||||
|
||||
QSBCore.UnityEvents.RunWhen(
|
||||
() => Player.ProbeLauncher != null,
|
||||
() => SetSocket(Player.ProbeLauncher.ToolGameObject.transform));
|
||||
Player.ProbeBody = body.gameObject;
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
private void SetSocket(Transform socket)
|
||||
{
|
||||
DebugLog.DebugWrite($"Set DisabledSocket of id:{PlayerId}.");
|
||||
_disabledSocket = socket;
|
||||
}
|
||||
|
||||
|
||||
protected override void UpdateTransform()
|
||||
{
|
||||
base.UpdateTransform();
|
||||
if (Player == null)
|
||||
{
|
||||
DebugLog.ToConsole($"Player is null for {AttachedNetId}!", MessageType.Error);
|
||||
return;
|
||||
}
|
||||
if (_disabledSocket == null)
|
||||
{
|
||||
DebugLog.ToConsole($"DisabledSocket is null for {PlayerId}! (ProbeLauncher null? : {Player.ProbeLauncher == null})", MessageType.Error);
|
||||
return;
|
||||
}
|
||||
if (Player.GetState(State.ProbeActive) || ReferenceSector?.AttachedObject == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (HasAuthority)
|
||||
{
|
||||
transform.position = ReferenceSector.Transform.InverseTransformPoint(_disabledSocket.position);
|
||||
return;
|
||||
}
|
||||
if (SyncedTransform.position == Vector3.zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
SyncedTransform.localPosition = ReferenceSector.Transform.InverseTransformPoint(_disabledSocket.position);
|
||||
}
|
||||
|
||||
public override bool IsReady => Locator.GetProbe() != null
|
||||
&& Player != null
|
||||
&& QSBPlayerManager.PlayerExists(Player.PlayerId)
|
||||
&& Player.IsReady
|
||||
&& NetId.Value != uint.MaxValue
|
||||
&& NetId.Value != 0U;
|
||||
}
|
||||
}
|
235
QSB/TransformSync/QSBNetworkTransform.cs
Normal file
235
QSB/TransformSync/QSBNetworkTransform.cs
Normal file
@ -0,0 +1,235 @@
|
||||
using OWML.Common;
|
||||
using QSB.Player;
|
||||
using QSB.Player.TransformSync;
|
||||
using QSB.SectorSync.WorldObjects;
|
||||
using QSB.Utility;
|
||||
using QSB.WorldSync;
|
||||
using QuantumUNET.Components;
|
||||
using QuantumUNET.Transport;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QSB.TransformSync
|
||||
{
|
||||
public abstract class QSBNetworkTransform : QNetworkTransform
|
||||
{
|
||||
public uint AttachedNetId => NetIdentity?.NetId.Value ?? uint.MaxValue;
|
||||
public uint PlayerId => NetIdentity.RootIdentity?.NetId.Value ?? NetIdentity.NetId.Value;
|
||||
public PlayerInfo Player => QSBPlayerManager.GetPlayer(PlayerId);
|
||||
|
||||
public static List<QSBNetworkTransform> NetworkTransformList = new List<QSBNetworkTransform>();
|
||||
|
||||
public QSBSector ReferenceSector { get; set; }
|
||||
public GameObject AttachedObject { get; set; }
|
||||
public SectorSync.SectorSync SectorSync { get; private set; }
|
||||
|
||||
public abstract bool IsReady { get; }
|
||||
|
||||
protected abstract GameObject InitLocalTransform();
|
||||
protected abstract GameObject InitRemoteTransform();
|
||||
|
||||
private bool _isInitialized;
|
||||
private const float SmoothTime = 0.1f;
|
||||
protected virtual float DistanceLeeway { get; } = 5f;
|
||||
private float _previousDistance;
|
||||
private Vector3 _positionSmoothVelocity;
|
||||
private Quaternion _rotationSmoothVelocity;
|
||||
|
||||
public virtual void Start()
|
||||
{
|
||||
var lowestBound = Resources.FindObjectsOfTypeAll<PlayerTransformSync>()
|
||||
.Where(x => x.NetId.Value <= NetId.Value).OrderBy(x => x.NetId.Value).Last();
|
||||
NetIdentity.SetRootIdentity(lowestBound.NetIdentity);
|
||||
|
||||
SectorSync = gameObject.AddComponent<SectorSync.SectorSync>();
|
||||
|
||||
NetworkTransformList.Add(this);
|
||||
DontDestroyOnLoad(gameObject);
|
||||
QSBSceneManager.OnSceneLoaded += OnSceneLoaded;
|
||||
}
|
||||
|
||||
protected virtual void OnDestroy()
|
||||
{
|
||||
if (!HasAuthority && AttachedObject != null)
|
||||
{
|
||||
Destroy(AttachedObject);
|
||||
}
|
||||
NetworkTransformList.Remove(this);
|
||||
QSBSceneManager.OnSceneLoaded -= OnSceneLoaded;
|
||||
if (SectorSync != null)
|
||||
{
|
||||
Destroy(SectorSync);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSceneLoaded(OWScene scene, bool isInUniverse) =>
|
||||
_isInitialized = false;
|
||||
|
||||
protected void Init()
|
||||
{
|
||||
AttachedObject = HasAuthority ? InitLocalTransform() : InitRemoteTransform();
|
||||
SetReferenceSector(SectorSync.GetClosestSector(AttachedObject.transform));
|
||||
_isInitialized = true;
|
||||
}
|
||||
|
||||
public override void SerializeTransform(QNetworkWriter writer)
|
||||
{
|
||||
if (ReferenceSector != null)
|
||||
{
|
||||
writer.Write(ReferenceSector.ObjectId);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write(-1);
|
||||
}
|
||||
|
||||
writer.Write(transform.localPosition);
|
||||
SerializeRotation(writer, transform.localRotation);
|
||||
_prevPosition = transform.localPosition;
|
||||
_prevRotation = transform.localRotation;
|
||||
}
|
||||
|
||||
public override void DeserializeTransform(QNetworkReader reader)
|
||||
{
|
||||
if (!QSBCore.HasWokenUp)
|
||||
{
|
||||
reader.ReadInt32();
|
||||
reader.ReadVector3();
|
||||
DeserializeRotation(reader);
|
||||
return;
|
||||
}
|
||||
|
||||
var sectorId = reader.ReadInt32();
|
||||
var sector = sectorId == -1
|
||||
? null
|
||||
: QSBWorldSync.GetWorldFromId<QSBSector>(sectorId);
|
||||
|
||||
if (sector != ReferenceSector)
|
||||
{
|
||||
SetReferenceSector(sector);
|
||||
}
|
||||
|
||||
var localPosition = reader.ReadVector3();
|
||||
var localRotation = DeserializeRotation(reader);
|
||||
|
||||
if (HasAuthority)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
transform.localPosition = localPosition;
|
||||
transform.localRotation = localRotation;
|
||||
|
||||
if (transform.position == Vector3.zero)
|
||||
{
|
||||
DebugLog.ToConsole($"Warning - {PlayerId}.{GetType().Name} at (0,0,0)! - Given localPosition was {localPosition} at sector {sector?.Name}", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
if (!_isInitialized && IsReady)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
else if (_isInitialized && !IsReady)
|
||||
{
|
||||
_isInitialized = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_isInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (AttachedObject == null)
|
||||
{
|
||||
DebugLog.ToConsole($"Warning - AttachedObject {Player.PlayerId}.{GetType().Name} is null.", MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateTransform();
|
||||
|
||||
base.Update();
|
||||
}
|
||||
|
||||
protected virtual void UpdateTransform()
|
||||
{
|
||||
if (HasAuthority)
|
||||
{
|
||||
transform.position = AttachedObject.transform.position;
|
||||
transform.rotation = AttachedObject.transform.rotation;
|
||||
}
|
||||
else
|
||||
{
|
||||
AttachedObject.transform.localPosition = SmartSmoothDamp(AttachedObject.transform.localPosition, transform.localPosition);
|
||||
AttachedObject.transform.localRotation = QuaternionHelper.SmoothDamp(AttachedObject.transform.localRotation, transform.localRotation, ref _rotationSmoothVelocity, SmoothTime);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool HasMoved()
|
||||
{
|
||||
var displacementMagnitude = (transform.localPosition - _prevPosition).magnitude;
|
||||
return displacementMagnitude > 1E-03f
|
||||
|| Quaternion.Angle(transform.localRotation, _prevRotation) > 1E-03f;
|
||||
}
|
||||
|
||||
public void SetReferenceSector(QSBSector sector)
|
||||
{
|
||||
if (ReferenceSector == sector)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ReferenceSector = sector;
|
||||
transform.SetParent(sector.Transform, true);
|
||||
if (AttachedObject == null)
|
||||
{
|
||||
DebugLog.ToConsole($"Warning - AttachedObject was null for {PlayerId}.{GetType().Name} when trying to set reference sector to {sector.Name}. Waiting until not null...", MessageType.Warning);
|
||||
QSBCore.UnityEvents.RunWhen(
|
||||
() => AttachedObject != null,
|
||||
() => ReparentAttachedObject(sector.Transform));
|
||||
return;
|
||||
}
|
||||
if (!HasAuthority)
|
||||
{
|
||||
ReparentAttachedObject(sector.Transform);
|
||||
}
|
||||
}
|
||||
|
||||
private void ReparentAttachedObject(Transform sectorTransform)
|
||||
{
|
||||
AttachedObject.transform.SetParent(sectorTransform, true);
|
||||
AttachedObject.transform.localScale = GetType() == typeof(PlayerTransformSync)
|
||||
? Vector3.one / 10
|
||||
: Vector3.one;
|
||||
}
|
||||
|
||||
private Vector3 SmartSmoothDamp(Vector3 currentPosition, Vector3 targetPosition)
|
||||
{
|
||||
var distance = Vector3.Distance(currentPosition, targetPosition);
|
||||
if (distance > _previousDistance + DistanceLeeway)
|
||||
{
|
||||
DebugLog.DebugWrite($"Warning - {PlayerId}.{GetType().Name} moved too fast!", MessageType.Warning);
|
||||
_previousDistance = distance;
|
||||
return targetPosition;
|
||||
}
|
||||
_previousDistance = distance;
|
||||
return Vector3.SmoothDamp(currentPosition, targetPosition, ref _positionSmoothVelocity, SmoothTime);
|
||||
}
|
||||
|
||||
private void OnRenderObject()
|
||||
{
|
||||
if (!QSBCore.HasWokenUp || !QSBCore.DebugMode || !QSBCore.ShowLinesInDebug || !IsReady)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Popcron.Gizmos.Cube(transform.position, transform.rotation, Vector3.one / 2, Color.red);
|
||||
var color = HasMoved() ? Color.green : Color.yellow;
|
||||
Popcron.Gizmos.Cube(AttachedObject.transform.position, AttachedObject.transform.rotation, Vector3.one / 2, color);
|
||||
Popcron.Gizmos.Line(AttachedObject.transform.position, ReferenceSector.Transform.position, Color.cyan);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,182 +0,0 @@
|
||||
using OWML.Common;
|
||||
using QSB.Player;
|
||||
using QSB.SectorSync.WorldObjects;
|
||||
using QSB.Utility;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QSB.TransformSync
|
||||
{
|
||||
public abstract class TransformSync : PlayerSyncObject
|
||||
{
|
||||
public abstract bool IsReady { get; }
|
||||
|
||||
protected abstract Transform InitLocalTransform();
|
||||
protected abstract Transform InitRemoteTransform();
|
||||
|
||||
public Transform SyncedTransform { get; private set; }
|
||||
public QSBSector ReferenceSector { get; set; }
|
||||
public SectorSync.SectorSync SectorSync { get; private set; }
|
||||
|
||||
private const float SmoothTime = 0.1f;
|
||||
private const float DistanceLeeway = 5f;
|
||||
private bool _isInitialized;
|
||||
private Vector3 _positionSmoothVelocity;
|
||||
private Quaternion _rotationSmoothVelocity;
|
||||
private bool _isVisible;
|
||||
private float _previousDistance;
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
var lowestBound = QSBPlayerManager.GetSyncObjects<PlayerTransformSync>()
|
||||
.Where(x => x.NetId.Value <= NetId.Value).OrderBy(x => x.NetId.Value).Last();
|
||||
NetIdentity.SetRootIdentity(lowestBound.NetIdentity);
|
||||
|
||||
SectorSync = gameObject.AddComponent<SectorSync.SectorSync>();
|
||||
|
||||
DontDestroyOnLoad(gameObject);
|
||||
QSBSceneManager.OnSceneLoaded += OnSceneLoaded;
|
||||
}
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
base.OnDestroy();
|
||||
if (!HasAuthority && SyncedTransform != null)
|
||||
{
|
||||
Destroy(SyncedTransform.gameObject);
|
||||
}
|
||||
QSBSceneManager.OnSceneLoaded -= OnSceneLoaded;
|
||||
if (SectorSync != null)
|
||||
{
|
||||
Destroy(SectorSync);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSceneLoaded(OWScene scene, bool isInUniverse) =>
|
||||
_isInitialized = false;
|
||||
|
||||
protected void Init()
|
||||
{
|
||||
SyncedTransform = HasAuthority ? InitLocalTransform() : InitRemoteTransform();
|
||||
SetReferenceSector(SectorSync.GetClosestSector(SyncedTransform));
|
||||
_isInitialized = true;
|
||||
_isVisible = true;
|
||||
}
|
||||
|
||||
public void OnRenderObject()
|
||||
{
|
||||
if (!QSBCore.HasWokenUp || !QSBCore.DebugMode || !QSBCore.ShowLinesInDebug || !IsReady)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Popcron.Gizmos.Cube(SyncedTransform.position, SyncedTransform.rotation, Vector3.one / 2, Color.green);
|
||||
Popcron.Gizmos.Cube(transform.position, transform.rotation, Vector3.one / 2, Color.red);
|
||||
Popcron.Gizmos.Line(SyncedTransform.position, transform.position, Color.magenta);
|
||||
Popcron.Gizmos.Cube(ReferenceSector.Position, ReferenceSector.Transform.rotation, Vector3.one, Color.cyan);
|
||||
Popcron.Gizmos.Line(SyncedTransform.position, ReferenceSector.Position, Color.blue);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (!_isInitialized && IsReady)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
else if (_isInitialized && !IsReady)
|
||||
{
|
||||
_isInitialized = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_isInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (SyncedTransform == null)
|
||||
{
|
||||
DebugLog.ToConsole($"Warning - SyncedTransform {Player.PlayerId}.{GetType().Name} is null.", MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateTransform();
|
||||
}
|
||||
|
||||
protected virtual void UpdateTransform()
|
||||
{
|
||||
if (HasAuthority) // If this script is attached to the client's own body on the client's side.
|
||||
{
|
||||
if (ReferenceSector == null || ReferenceSector.AttachedObject == null)
|
||||
{
|
||||
DebugLog.ToConsole($"Error - ReferenceSector has null value for {Player.PlayerId}.{GetType().Name}", MessageType.Error);
|
||||
return;
|
||||
}
|
||||
transform.position = ReferenceSector.Transform.InverseTransformPoint(SyncedTransform.position);
|
||||
transform.rotation = ReferenceSector.Transform.InverseTransformRotation(SyncedTransform.rotation);
|
||||
return;
|
||||
}
|
||||
|
||||
// If this script is attached to any other body, eg the representations of other players
|
||||
if (SyncedTransform.position == Vector3.zero)
|
||||
{
|
||||
Hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
Show();
|
||||
}
|
||||
|
||||
SyncedTransform.localPosition = SmartSmoothDamp(SyncedTransform.localPosition, transform.position);
|
||||
SyncedTransform.localRotation = QuaternionHelper.SmoothDamp(SyncedTransform.localRotation, transform.rotation, ref _rotationSmoothVelocity, SmoothTime);
|
||||
}
|
||||
|
||||
private Vector3 SmartSmoothDamp(Vector3 currentPosition, Vector3 targetPosition)
|
||||
{
|
||||
var distance = Vector3.Distance(currentPosition, targetPosition);
|
||||
if (distance > _previousDistance + DistanceLeeway)
|
||||
{
|
||||
// moved too far! assume sector sync warp / actual warp
|
||||
_previousDistance = distance;
|
||||
return targetPosition;
|
||||
}
|
||||
_previousDistance = distance;
|
||||
return Vector3.SmoothDamp(currentPosition, targetPosition, ref _positionSmoothVelocity, SmoothTime);
|
||||
}
|
||||
|
||||
public void SetReferenceSector(QSBSector sector)
|
||||
{
|
||||
if (sector == ReferenceSector || sector == default(QSBSector))
|
||||
{
|
||||
return;
|
||||
}
|
||||
_positionSmoothVelocity = Vector3.zero;
|
||||
ReferenceSector = sector;
|
||||
if (!HasAuthority)
|
||||
{
|
||||
SyncedTransform.SetParent(sector.Transform, true);
|
||||
transform.position = sector.Transform.InverseTransformPoint(SyncedTransform.position);
|
||||
transform.rotation = sector.Transform.InverseTransformRotation(SyncedTransform.rotation);
|
||||
}
|
||||
}
|
||||
|
||||
private void Show()
|
||||
{
|
||||
if (!_isVisible)
|
||||
{
|
||||
SyncedTransform.gameObject.Show();
|
||||
_isVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void Hide()
|
||||
{
|
||||
if (_isVisible)
|
||||
{
|
||||
SyncedTransform.gameObject.Hide();
|
||||
_isVisible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,4 @@
|
||||
using OWML.Utils;
|
||||
using QSB.Player;
|
||||
using QSB.TransformSync;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QSB.Utility
|
||||
@ -27,35 +24,12 @@ namespace QSB.Utility
|
||||
bridgeVolume.AddObjectToVolume(Locator.GetPlayerCameraDetector());
|
||||
}
|
||||
|
||||
private void DebugWarpToPlayer(int index)
|
||||
{
|
||||
var allPlayers = QSBPlayerManager.PlayerList.Where(x => x != QSBPlayerManager.LocalPlayer).ToList();
|
||||
if (allPlayers.Count <= index)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var player = allPlayers[index];
|
||||
var localPlayer = Locator.GetPlayerBody();
|
||||
localPlayer.WarpToPositionRotation(player.CameraBody.transform.position, player.CameraBody.transform.rotation);
|
||||
var playerTransformSync = QSBPlayerManager.GetSyncObject<PlayerTransformSync>(player.PlayerId);
|
||||
var syncedRigidbody = playerTransformSync.ReferenceSector.AttachedObject.GetOWRigidbody();
|
||||
localPlayer.SetVelocity(syncedRigidbody.GetPointVelocity(player.Body.transform.position));
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (!QSBCore.DebugMode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (Input.GetKeyDown(KeyCode.Keypad0))
|
||||
{
|
||||
DebugWarpToPlayer(0);
|
||||
}
|
||||
if (Input.GetKeyDown(KeyCode.Keypad1))
|
||||
{
|
||||
DebugWarpToPlayer(1);
|
||||
}
|
||||
if (Input.GetKeyDown(KeyCode.Keypad7))
|
||||
{
|
||||
GoToVessel();
|
||||
|
@ -1,5 +1,5 @@
|
||||
using OWML.Common;
|
||||
using QSB.TransformSync;
|
||||
using QSB.Player.TransformSync;
|
||||
using QuantumUNET;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
@ -23,6 +23,9 @@ namespace QSB.Utility
|
||||
}
|
||||
}
|
||||
|
||||
public static Quaternion TransformRotation(this Transform transform, Quaternion localRotation)
|
||||
=> transform.rotation * localRotation;
|
||||
|
||||
public static GameObject InstantiateInactive(this GameObject original)
|
||||
{
|
||||
original.SetActive(false);
|
||||
|
@ -1,31 +0,0 @@
|
||||
namespace QSB.Utility
|
||||
{
|
||||
// Stolen from here : https://stackoverflow.com/questions/3261451/using-a-bitmask-in-c-sharp
|
||||
|
||||
public static class FlagsHelper
|
||||
{
|
||||
public static bool IsSet<T>(T flags, T flag) where T : struct
|
||||
{
|
||||
var flagsValue = (int)(object)flags;
|
||||
var flagValue = (int)(object)flag;
|
||||
|
||||
return (flagsValue & flagValue) != 0;
|
||||
}
|
||||
|
||||
public static void Set<T>(ref T flags, T flag) where T : struct
|
||||
{
|
||||
var flagsValue = (int)(object)flags;
|
||||
var flagValue = (int)(object)flag;
|
||||
|
||||
flags = (T)(object)(flagsValue | flagValue);
|
||||
}
|
||||
|
||||
public static void Unset<T>(ref T flags, T flag) where T : struct
|
||||
{
|
||||
var flagsValue = (int)(object)flags;
|
||||
var flagValue = (int)(object)flag;
|
||||
|
||||
flags = (T)(object)(flagsValue & ~flagValue);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
using OWML.Common;
|
||||
using QSB.OrbSync.TransformSync;
|
||||
using QSB.OrbSync.WorldObjects;
|
||||
using QSB.TransformSync;
|
||||
using QSB.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -4,6 +4,6 @@
|
||||
"name": "Quantum Space Buddies",
|
||||
"description": "Adds online multiplayer to the game.",
|
||||
"uniqueName": "Raicuparta.QuantumSpaceBuddies",
|
||||
"version": "0.10.0",
|
||||
"version": "0.10.1",
|
||||
"owmlVersion": "1.1.8"
|
||||
}
|
@ -8,23 +8,26 @@ namespace QuantumUNET.Components
|
||||
{
|
||||
public class QNetworkTransform : QNetworkBehaviour
|
||||
{
|
||||
public float SendInterval { get; set; } = 0.1f;
|
||||
public AxisSyncMode SyncRotationAxis { get; set; } = AxisSyncMode.AxisXYZ;
|
||||
public CompressionSyncMode RotationSyncCompression { get; set; } = CompressionSyncMode.None;
|
||||
public ClientMoveCallback3D clientMoveCallback3D { get; set; }
|
||||
public float SendInterval { get; set; } = 0.05f;
|
||||
public float LastSyncTime { get; private set; }
|
||||
|
||||
private float _lastClientSendTime;
|
||||
protected Vector3 _prevPosition;
|
||||
protected Quaternion _prevRotation;
|
||||
private QNetworkWriter _localTransformWriter;
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
m_PrevPosition = transform.position;
|
||||
m_PrevRotation = transform.rotation;
|
||||
_prevPosition = transform.position;
|
||||
_prevRotation = transform.rotation;
|
||||
if (LocalPlayerAuthority)
|
||||
{
|
||||
m_LocalTransformWriter = new QNetworkWriter();
|
||||
_localTransformWriter = new QNetworkWriter();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnStartServer() => LastSyncTime = 0f;
|
||||
public override void OnStartServer()
|
||||
=> LastSyncTime = 0f;
|
||||
|
||||
public override bool OnSerialize(QNetworkWriter writer, bool initialState)
|
||||
{
|
||||
@ -37,21 +40,10 @@ namespace QuantumUNET.Components
|
||||
}
|
||||
writer.WritePackedUInt32(1U);
|
||||
}
|
||||
SerializeModeTransform(writer);
|
||||
SerializeTransform(writer);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void SerializeModeTransform(QNetworkWriter writer)
|
||||
{
|
||||
writer.Write(transform.position);
|
||||
if (SyncRotationAxis != AxisSyncMode.None)
|
||||
{
|
||||
SerializeRotation3D(writer, transform.rotation, SyncRotationAxis, RotationSyncCompression);
|
||||
}
|
||||
m_PrevPosition = transform.position;
|
||||
m_PrevRotation = transform.rotation;
|
||||
}
|
||||
|
||||
public override void OnDeserialize(QNetworkReader reader, bool initialState)
|
||||
{
|
||||
if (!IsServer || !QNetworkServer.localClientActive)
|
||||
@ -63,116 +55,78 @@ namespace QuantumUNET.Components
|
||||
return;
|
||||
}
|
||||
}
|
||||
UnserializeModeTransform(reader, initialState);
|
||||
DeserializeTransform(reader);
|
||||
LastSyncTime = Time.time;
|
||||
}
|
||||
}
|
||||
|
||||
private void UnserializeModeTransform(QNetworkReader reader, bool initialState)
|
||||
public virtual void SerializeTransform(QNetworkWriter writer)
|
||||
{
|
||||
writer.Write(transform.position);
|
||||
SerializeRotation(writer, transform.rotation);
|
||||
_prevPosition = transform.position;
|
||||
_prevRotation = transform.rotation;
|
||||
}
|
||||
|
||||
public virtual void DeserializeTransform(QNetworkReader reader)
|
||||
{
|
||||
if (HasAuthority)
|
||||
{
|
||||
reader.ReadVector3();
|
||||
if (SyncRotationAxis != AxisSyncMode.None)
|
||||
{
|
||||
UnserializeRotation3D(reader, SyncRotationAxis, RotationSyncCompression);
|
||||
}
|
||||
}
|
||||
else if (IsServer && clientMoveCallback3D != null)
|
||||
{
|
||||
var position = reader.ReadVector3();
|
||||
var zero = Vector3.zero;
|
||||
var rotation = Quaternion.identity;
|
||||
if (SyncRotationAxis != AxisSyncMode.None)
|
||||
{
|
||||
rotation = UnserializeRotation3D(reader, SyncRotationAxis, RotationSyncCompression);
|
||||
}
|
||||
if (clientMoveCallback3D(ref position, ref zero, ref rotation))
|
||||
{
|
||||
transform.position = position;
|
||||
if (SyncRotationAxis != AxisSyncMode.None)
|
||||
{
|
||||
transform.rotation = rotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
transform.position = reader.ReadVector3();
|
||||
if (SyncRotationAxis != AxisSyncMode.None)
|
||||
{
|
||||
transform.rotation = UnserializeRotation3D(reader, SyncRotationAxis, RotationSyncCompression);
|
||||
}
|
||||
DeserializeRotation(reader);
|
||||
return;
|
||||
}
|
||||
transform.position = reader.ReadVector3();
|
||||
transform.rotation = DeserializeRotation(reader);
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (IsServer)
|
||||
if (!IsServer)
|
||||
{
|
||||
FixedUpdateServer();
|
||||
return;
|
||||
}
|
||||
|
||||
if (SyncVarDirtyBits != 0U)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!QNetworkServer.active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetNetworkSendInterval() != 0f && HasMoved())
|
||||
{
|
||||
SetDirtyBit(1U);
|
||||
}
|
||||
}
|
||||
|
||||
private void FixedUpdateServer()
|
||||
public virtual void Update()
|
||||
{
|
||||
if (SyncVarDirtyBits == 0U)
|
||||
if (!HasAuthority || !LocalPlayerAuthority)
|
||||
{
|
||||
if (QNetworkServer.active)
|
||||
{
|
||||
if (IsServer)
|
||||
{
|
||||
if (GetNetworkSendInterval() != 0f)
|
||||
{
|
||||
if (HasMoved())
|
||||
{
|
||||
SetDirtyBit(1U);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (QNetworkServer.active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Time.time - _lastClientSendTime > GetNetworkSendInterval())
|
||||
{
|
||||
SendTransform();
|
||||
_lastClientSendTime = Time.time;
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
public virtual bool HasMoved()
|
||||
{
|
||||
if (HasAuthority)
|
||||
{
|
||||
if (LocalPlayerAuthority)
|
||||
{
|
||||
if (!QNetworkServer.active)
|
||||
{
|
||||
if (Time.time - m_LastClientSendTime > GetNetworkSendInterval())
|
||||
{
|
||||
SendTransform();
|
||||
m_LastClientSendTime = Time.time;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasMoved()
|
||||
{
|
||||
var num = (transform.position - m_PrevPosition).magnitude;
|
||||
bool result;
|
||||
if (num > 1E-05f)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
num = Quaternion.Angle(transform.rotation, m_PrevRotation);
|
||||
if (num > 1E-05f)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = num > 1E-05f;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
var displacementMagnitude = (transform.position - _prevPosition).magnitude;
|
||||
return displacementMagnitude > 1E-05f
|
||||
|| Quaternion.Angle(transform.rotation, _prevRotation) > 1E-05f;
|
||||
}
|
||||
|
||||
[Client]
|
||||
@ -180,13 +134,14 @@ namespace QuantumUNET.Components
|
||||
{
|
||||
if (HasMoved() && QClientScene.readyConnection != null)
|
||||
{
|
||||
m_LocalTransformWriter.StartMessage(6);
|
||||
m_LocalTransformWriter.Write(NetId);
|
||||
SerializeModeTransform(m_LocalTransformWriter);
|
||||
m_PrevPosition = transform.position;
|
||||
m_PrevRotation = transform.rotation;
|
||||
m_LocalTransformWriter.FinishMessage();
|
||||
QClientScene.readyConnection.SendWriter(m_LocalTransformWriter, GetNetworkChannel());
|
||||
_localTransformWriter.StartMessage(QMsgType.LocalPlayerTransform);
|
||||
_localTransformWriter.Write(NetId);
|
||||
SerializeTransform(_localTransformWriter);
|
||||
_prevPosition = transform.position;
|
||||
_prevRotation = transform.rotation;
|
||||
_localTransformWriter.FinishMessage();
|
||||
|
||||
QClientScene.readyConnection.SendWriter(_localTransformWriter, GetNetworkChannel());
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,281 +152,63 @@ namespace QuantumUNET.Components
|
||||
if (gameObject == null)
|
||||
{
|
||||
QLog.Warning("Received NetworkTransform data for GameObject that doesn't exist");
|
||||
return;
|
||||
}
|
||||
|
||||
var component = gameObject.GetComponent<QNetworkTransform>();
|
||||
if (component == null)
|
||||
{
|
||||
QLog.Warning("HandleTransform null target");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!component.LocalPlayerAuthority)
|
||||
{
|
||||
QLog.Warning("HandleTransform no localPlayerAuthority");
|
||||
return;
|
||||
}
|
||||
|
||||
if (netMsg.Connection.ClientOwnedObjects == null)
|
||||
{
|
||||
QLog.Warning("HandleTransform object not owned by connection");
|
||||
return;
|
||||
}
|
||||
|
||||
if (netMsg.Connection.ClientOwnedObjects.Contains(networkInstanceId))
|
||||
{
|
||||
component.DeserializeTransform(netMsg.Reader);
|
||||
component.LastSyncTime = Time.time;
|
||||
}
|
||||
else
|
||||
{
|
||||
var component = gameObject.GetComponent<QNetworkTransform>();
|
||||
if (component == null)
|
||||
{
|
||||
QLog.Warning("HandleTransform null target");
|
||||
}
|
||||
else if (!component.LocalPlayerAuthority)
|
||||
{
|
||||
QLog.Warning("HandleTransform no localPlayerAuthority");
|
||||
}
|
||||
else if (netMsg.Connection.ClientOwnedObjects == null)
|
||||
{
|
||||
QLog.Warning("HandleTransform object not owned by connection");
|
||||
}
|
||||
else if (netMsg.Connection.ClientOwnedObjects.Contains(networkInstanceId))
|
||||
{
|
||||
component.UnserializeModeTransform(netMsg.Reader, false);
|
||||
component.LastSyncTime = Time.time;
|
||||
}
|
||||
else
|
||||
{
|
||||
QLog.Warning(
|
||||
$"HandleTransform netId:{networkInstanceId} is not for a valid player");
|
||||
}
|
||||
QLog.Warning(
|
||||
$"HandleTransform netId:{networkInstanceId} is not for a valid player");
|
||||
}
|
||||
}
|
||||
|
||||
private static void WriteAngle(QNetworkWriter writer, float angle, CompressionSyncMode compression)
|
||||
public static void SerializeRotation(QNetworkWriter writer, Quaternion rot)
|
||||
{
|
||||
if (compression != CompressionSyncMode.None)
|
||||
{
|
||||
if (compression != CompressionSyncMode.Low)
|
||||
{
|
||||
if (compression == CompressionSyncMode.High)
|
||||
{
|
||||
writer.Write((short)angle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write((short)angle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write(angle);
|
||||
}
|
||||
writer.Write(rot.eulerAngles.x);
|
||||
writer.Write(rot.eulerAngles.y);
|
||||
writer.Write(rot.eulerAngles.z);
|
||||
}
|
||||
|
||||
private static float ReadAngle(QNetworkReader reader, CompressionSyncMode compression)
|
||||
public static Quaternion DeserializeRotation(QNetworkReader reader)
|
||||
{
|
||||
float result;
|
||||
if (compression != CompressionSyncMode.None)
|
||||
{
|
||||
if (compression != CompressionSyncMode.Low)
|
||||
{
|
||||
if (compression != CompressionSyncMode.High)
|
||||
{
|
||||
result = 0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = reader.ReadInt16();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = reader.ReadInt16();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = reader.ReadSingle();
|
||||
}
|
||||
return result;
|
||||
var rotation = Quaternion.identity;
|
||||
var eulerAngles = Vector3.zero;
|
||||
eulerAngles.Set(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
|
||||
rotation.eulerAngles = eulerAngles;
|
||||
return rotation;
|
||||
}
|
||||
|
||||
public static void SerializeVelocity3D(QNetworkWriter writer, Vector3 velocity, CompressionSyncMode compression) =>
|
||||
writer.Write(velocity);
|
||||
public override int GetNetworkChannel()
|
||||
=> 1;
|
||||
|
||||
public static void SerializeRotation3D(QNetworkWriter writer, Quaternion rot, AxisSyncMode mode, CompressionSyncMode compression)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case AxisSyncMode.AxisX:
|
||||
WriteAngle(writer, rot.eulerAngles.x, compression);
|
||||
break;
|
||||
public override float GetNetworkSendInterval()
|
||||
=> SendInterval;
|
||||
|
||||
case AxisSyncMode.AxisY:
|
||||
WriteAngle(writer, rot.eulerAngles.y, compression);
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisZ:
|
||||
WriteAngle(writer, rot.eulerAngles.z, compression);
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisXY:
|
||||
WriteAngle(writer, rot.eulerAngles.x, compression);
|
||||
WriteAngle(writer, rot.eulerAngles.y, compression);
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisXZ:
|
||||
WriteAngle(writer, rot.eulerAngles.x, compression);
|
||||
WriteAngle(writer, rot.eulerAngles.z, compression);
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisYZ:
|
||||
WriteAngle(writer, rot.eulerAngles.y, compression);
|
||||
WriteAngle(writer, rot.eulerAngles.z, compression);
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisXYZ:
|
||||
WriteAngle(writer, rot.eulerAngles.x, compression);
|
||||
WriteAngle(writer, rot.eulerAngles.y, compression);
|
||||
WriteAngle(writer, rot.eulerAngles.z, compression);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SerializeSpin3D(QNetworkWriter writer, Vector3 angularVelocity, AxisSyncMode mode, CompressionSyncMode compression)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case AxisSyncMode.AxisX:
|
||||
WriteAngle(writer, angularVelocity.x, compression);
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisY:
|
||||
WriteAngle(writer, angularVelocity.y, compression);
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisZ:
|
||||
WriteAngle(writer, angularVelocity.z, compression);
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisXY:
|
||||
WriteAngle(writer, angularVelocity.x, compression);
|
||||
WriteAngle(writer, angularVelocity.y, compression);
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisXZ:
|
||||
WriteAngle(writer, angularVelocity.x, compression);
|
||||
WriteAngle(writer, angularVelocity.z, compression);
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisYZ:
|
||||
WriteAngle(writer, angularVelocity.y, compression);
|
||||
WriteAngle(writer, angularVelocity.z, compression);
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisXYZ:
|
||||
WriteAngle(writer, angularVelocity.x, compression);
|
||||
WriteAngle(writer, angularVelocity.y, compression);
|
||||
WriteAngle(writer, angularVelocity.z, compression);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static Vector3 UnserializeVelocity3D(QNetworkReader reader, CompressionSyncMode compression) => reader.ReadVector3();
|
||||
|
||||
public static Quaternion UnserializeRotation3D(QNetworkReader reader, AxisSyncMode mode, CompressionSyncMode compression)
|
||||
{
|
||||
var identity = Quaternion.identity;
|
||||
var zero = Vector3.zero;
|
||||
switch (mode)
|
||||
{
|
||||
case AxisSyncMode.AxisX:
|
||||
zero.Set(ReadAngle(reader, compression), 0f, 0f);
|
||||
identity.eulerAngles = zero;
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisY:
|
||||
zero.Set(0f, ReadAngle(reader, compression), 0f);
|
||||
identity.eulerAngles = zero;
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisZ:
|
||||
zero.Set(0f, 0f, ReadAngle(reader, compression));
|
||||
identity.eulerAngles = zero;
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisXY:
|
||||
zero.Set(ReadAngle(reader, compression), ReadAngle(reader, compression), 0f);
|
||||
identity.eulerAngles = zero;
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisXZ:
|
||||
zero.Set(ReadAngle(reader, compression), 0f, ReadAngle(reader, compression));
|
||||
identity.eulerAngles = zero;
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisYZ:
|
||||
zero.Set(0f, ReadAngle(reader, compression), ReadAngle(reader, compression));
|
||||
identity.eulerAngles = zero;
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisXYZ:
|
||||
zero.Set(ReadAngle(reader, compression), ReadAngle(reader, compression), ReadAngle(reader, compression));
|
||||
identity.eulerAngles = zero;
|
||||
break;
|
||||
}
|
||||
return identity;
|
||||
}
|
||||
|
||||
public static Vector3 UnserializeSpin3D(QNetworkReader reader, AxisSyncMode mode, CompressionSyncMode compression)
|
||||
{
|
||||
var zero = Vector3.zero;
|
||||
switch (mode)
|
||||
{
|
||||
case AxisSyncMode.AxisX:
|
||||
zero.Set(ReadAngle(reader, compression), 0f, 0f);
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisY:
|
||||
zero.Set(0f, ReadAngle(reader, compression), 0f);
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisZ:
|
||||
zero.Set(0f, 0f, ReadAngle(reader, compression));
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisXY:
|
||||
zero.Set(ReadAngle(reader, compression), ReadAngle(reader, compression), 0f);
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisXZ:
|
||||
zero.Set(ReadAngle(reader, compression), 0f, ReadAngle(reader, compression));
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisYZ:
|
||||
zero.Set(0f, ReadAngle(reader, compression), ReadAngle(reader, compression));
|
||||
break;
|
||||
|
||||
case AxisSyncMode.AxisXYZ:
|
||||
zero.Set(ReadAngle(reader, compression), ReadAngle(reader, compression), ReadAngle(reader, compression));
|
||||
break;
|
||||
}
|
||||
return zero;
|
||||
}
|
||||
|
||||
public override int GetNetworkChannel() => 1;
|
||||
|
||||
public override float GetNetworkSendInterval() => SendInterval;
|
||||
|
||||
public override void OnStartAuthority() => LastSyncTime = 0f;
|
||||
|
||||
private float m_LastClientSendTime;
|
||||
|
||||
private Vector3 m_PrevPosition;
|
||||
|
||||
private Quaternion m_PrevRotation;
|
||||
|
||||
private QNetworkWriter m_LocalTransformWriter;
|
||||
|
||||
public enum AxisSyncMode
|
||||
{
|
||||
None,
|
||||
AxisX,
|
||||
AxisY,
|
||||
AxisZ,
|
||||
AxisXY,
|
||||
AxisXZ,
|
||||
AxisYZ,
|
||||
AxisXYZ
|
||||
}
|
||||
|
||||
public enum CompressionSyncMode
|
||||
{
|
||||
None,
|
||||
Low,
|
||||
High
|
||||
}
|
||||
|
||||
public delegate bool ClientMoveCallback3D(ref Vector3 position, ref Vector3 velocity, ref Quaternion rotation);
|
||||
public override void OnStartAuthority()
|
||||
=> LastSyncTime = 0f;
|
||||
}
|
||||
}
|
@ -11,11 +11,7 @@ namespace QuantumUNET.Components
|
||||
public Transform Target
|
||||
{
|
||||
get => m_Target;
|
||||
set
|
||||
{
|
||||
m_Target = value;
|
||||
OnValidate();
|
||||
}
|
||||
set => m_Target = value;
|
||||
}
|
||||
|
||||
public uint ChildIndex => m_ChildIndex;
|
||||
@ -26,18 +22,6 @@ namespace QuantumUNET.Components
|
||||
set => m_SendInterval = value;
|
||||
}
|
||||
|
||||
public QNetworkTransform.AxisSyncMode SyncRotationAxis
|
||||
{
|
||||
get => m_SyncRotationAxis;
|
||||
set => m_SyncRotationAxis = value;
|
||||
}
|
||||
|
||||
public QNetworkTransform.CompressionSyncMode RotationSyncCompression
|
||||
{
|
||||
get => m_RotationSyncCompression;
|
||||
set => m_RotationSyncCompression = value;
|
||||
}
|
||||
|
||||
public float MovementThreshold
|
||||
{
|
||||
get => m_MovementThreshold;
|
||||
@ -56,89 +40,10 @@ namespace QuantumUNET.Components
|
||||
set => m_InterpolateMovement = value;
|
||||
}
|
||||
|
||||
public QNetworkTransform.ClientMoveCallback3D ClientMoveCallback3D
|
||||
{
|
||||
get => m_ClientMoveCallback3D;
|
||||
set => m_ClientMoveCallback3D = value;
|
||||
}
|
||||
|
||||
public float LastSyncTime { get; private set; }
|
||||
public Vector3 TargetSyncPosition => m_TargetSyncPosition;
|
||||
public Quaternion TargetSyncRotation3D => m_TargetSyncRotation3D;
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
if (m_Target != null)
|
||||
{
|
||||
var parent = m_Target.parent;
|
||||
if (parent == null)
|
||||
{
|
||||
Debug.LogError("NetworkTransformChild target cannot be the root transform.");
|
||||
m_Target = null;
|
||||
return;
|
||||
}
|
||||
while (parent.parent != null)
|
||||
{
|
||||
parent = parent.parent;
|
||||
}
|
||||
m_Root = parent.gameObject.GetComponent<QNetworkTransform>();
|
||||
if (m_Root == null)
|
||||
{
|
||||
Debug.LogError("NetworkTransformChild root must have NetworkTransform");
|
||||
m_Target = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (m_Root != null)
|
||||
{
|
||||
m_ChildIndex = uint.MaxValue;
|
||||
var components = m_Root.GetComponents<QNetworkTransformChild>();
|
||||
var num = 0U;
|
||||
while (num < (ulong)components.Length)
|
||||
{
|
||||
if (components[(int)(UIntPtr)num] == this)
|
||||
{
|
||||
m_ChildIndex = num;
|
||||
break;
|
||||
}
|
||||
num += 1U;
|
||||
}
|
||||
if (m_ChildIndex == 4294967295U)
|
||||
{
|
||||
Debug.LogError("QNetworkTransformChild component must be a child in the same hierarchy");
|
||||
m_Target = null;
|
||||
}
|
||||
}
|
||||
if (m_SendInterval < 0f)
|
||||
{
|
||||
m_SendInterval = 0f;
|
||||
}
|
||||
if (m_SyncRotationAxis < QNetworkTransform.AxisSyncMode.None || m_SyncRotationAxis > QNetworkTransform.AxisSyncMode.AxisXYZ)
|
||||
{
|
||||
m_SyncRotationAxis = QNetworkTransform.AxisSyncMode.None;
|
||||
}
|
||||
if (MovementThreshold < 0f)
|
||||
{
|
||||
MovementThreshold = 0f;
|
||||
}
|
||||
if (InterpolateRotation < 0f)
|
||||
{
|
||||
InterpolateRotation = 0.01f;
|
||||
}
|
||||
if (InterpolateRotation > 1f)
|
||||
{
|
||||
InterpolateRotation = 1f;
|
||||
}
|
||||
if (InterpolateMovement < 0f)
|
||||
{
|
||||
InterpolateMovement = 0.01f;
|
||||
}
|
||||
if (InterpolateMovement > 1f)
|
||||
{
|
||||
InterpolateMovement = 1f;
|
||||
}
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
m_PrevPosition = m_Target.localPosition;
|
||||
@ -167,10 +72,7 @@ namespace QuantumUNET.Components
|
||||
private void SerializeModeTransform(QNetworkWriter writer)
|
||||
{
|
||||
writer.Write(m_Target.localPosition);
|
||||
if (m_SyncRotationAxis != QNetworkTransform.AxisSyncMode.None)
|
||||
{
|
||||
QNetworkTransform.SerializeRotation3D(writer, m_Target.localRotation, SyncRotationAxis, RotationSyncCompression);
|
||||
}
|
||||
QNetworkTransform.SerializeRotation(writer, m_Target.localRotation);
|
||||
m_PrevPosition = m_Target.localPosition;
|
||||
m_PrevRotation = m_Target.localRotation;
|
||||
}
|
||||
@ -197,36 +99,12 @@ namespace QuantumUNET.Components
|
||||
if (HasAuthority)
|
||||
{
|
||||
reader.ReadVector3();
|
||||
if (SyncRotationAxis != QNetworkTransform.AxisSyncMode.None)
|
||||
{
|
||||
QNetworkTransform.UnserializeRotation3D(reader, SyncRotationAxis, RotationSyncCompression);
|
||||
}
|
||||
}
|
||||
else if (IsServer && m_ClientMoveCallback3D != null)
|
||||
{
|
||||
var targetSyncPosition = reader.ReadVector3();
|
||||
var zero = Vector3.zero;
|
||||
var targetSyncRotation3D = Quaternion.identity;
|
||||
if (SyncRotationAxis != QNetworkTransform.AxisSyncMode.None)
|
||||
{
|
||||
targetSyncRotation3D = QNetworkTransform.UnserializeRotation3D(reader, SyncRotationAxis, RotationSyncCompression);
|
||||
}
|
||||
if (m_ClientMoveCallback3D(ref targetSyncPosition, ref zero, ref targetSyncRotation3D))
|
||||
{
|
||||
m_TargetSyncPosition = targetSyncPosition;
|
||||
if (SyncRotationAxis != QNetworkTransform.AxisSyncMode.None)
|
||||
{
|
||||
m_TargetSyncRotation3D = targetSyncRotation3D;
|
||||
}
|
||||
}
|
||||
QNetworkTransform.DeserializeRotation(reader);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_TargetSyncPosition = reader.ReadVector3();
|
||||
if (SyncRotationAxis != QNetworkTransform.AxisSyncMode.None)
|
||||
{
|
||||
m_TargetSyncRotation3D = QNetworkTransform.UnserializeRotation3D(reader, SyncRotationAxis, RotationSyncCompression);
|
||||
}
|
||||
m_TargetSyncRotation3D = QNetworkTransform.DeserializeRotation(reader);
|
||||
}
|
||||
}
|
||||
|
||||
@ -404,12 +282,9 @@ namespace QuantumUNET.Components
|
||||
public uint m_ChildIndex;
|
||||
public QNetworkTransform m_Root;
|
||||
public float m_SendInterval = 0.1f;
|
||||
public QNetworkTransform.AxisSyncMode m_SyncRotationAxis = QNetworkTransform.AxisSyncMode.AxisXYZ;
|
||||
public QNetworkTransform.CompressionSyncMode m_RotationSyncCompression = QNetworkTransform.CompressionSyncMode.None;
|
||||
public float m_MovementThreshold = 0.001f;
|
||||
public float m_InterpolateRotation = 0.5f;
|
||||
public float m_InterpolateMovement = 0.5f;
|
||||
public QNetworkTransform.ClientMoveCallback3D m_ClientMoveCallback3D;
|
||||
private Vector3 m_TargetSyncPosition;
|
||||
private Quaternion m_TargetSyncRotation3D;
|
||||
private float m_LastClientSendTime;
|
||||
|
49
README.md
49
README.md
@ -1,5 +1,11 @@
|
||||

|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
Quantum Space Buddies (QSB) is a multiplayer mod for Outer Wilds. The mod uses the OWML mod loader and customized UNET code (internally referred to as QNet or QuantumUNET) for networking.
|
||||
|
||||
## License
|
||||
@ -56,19 +62,36 @@ QSB relies on exact orders of objects found using Resources.FindObjectsOfTypeAll
|
||||
**NomaiVR compatibility is currently not planned and likely will never happen, due to extensive changes needed to both mods for it to work.**
|
||||
|
||||
### What is currently synced?
|
||||
QSB does not operate on a strict server-client relationship. Each player's game is left as a completely seperate game, and individual elemets are synced or patched so they can be controlled though network messages. Right now, the list of synced objects are :
|
||||
- Geysers
|
||||
- Elevators
|
||||
- Nomai interface orbs
|
||||
- Player animations
|
||||
- Player tools
|
||||
- Player ships
|
||||
- Player probes
|
||||
- NPC heads in conversations
|
||||
- Ship log
|
||||
- Discovering frequencies / signals
|
||||
- Nomai text (Spirals + Computers)
|
||||
- Picking up/dropping/socketing items
|
||||
|
||||
| System / Mechanic | Synced? |
|
||||
| :---: | :---: |
|
||||
| Anglerfish | No |
|
||||
| Brittle Hollow fragments | No |
|
||||
| Campfires | Yes |
|
||||
| Conversations with NPCs | Yes |
|
||||
| Discovering signals/frequencies | Yes |
|
||||
| Eye of the Universe ancient glade | No |
|
||||
| Eye of the Universe instrument hunt | No |
|
||||
| Eye of the Universe jam session | No |
|
||||
| Eye of the Universe quantum lightning | No |
|
||||
| Geysers | Yes |
|
||||
| Items | Yes |
|
||||
| Jellyfish | No |
|
||||
| Marshmallow roasting | Yes |
|
||||
| Meteors | No |
|
||||
| Museum statue | Yes |
|
||||
| NPC animations | Kind of |
|
||||
| Nomai orbs | Yes |
|
||||
| Nomai shuttle | Kind of |
|
||||
| Orbital Probe Cannon (direction) | No |
|
||||
| Player animation | Kind of |
|
||||
| Player position | Yes |
|
||||
| Player tools | Yes |
|
||||
| Projection pools | Yes |
|
||||
| Quantum objects | Yes |
|
||||
| Ship log | Yes |
|
||||
| Timber Hearth satellite | No |
|
||||
| Tornadoes | No |
|
||||
|
||||
QSB also changes some mechanics of the base game, to better fit a multiplayer experience. These include :
|
||||
- Adding dialogue boxes above NPC and player heads, so other players can "listen in" on conversations.
|
||||
|
Loading…
x
Reference in New Issue
Block a user