mirror of
https://github.com/misternebula/quantum-space-buddies.git
synced 2025-02-13 21:40:50 +00:00
Merge branch 'dev' into pr/649
This commit is contained in:
commit
7280e0d08a
QSB.slnQSB.sln.DotSettings
QSB
API
Animation/Player
AssetBundles
Audio
BodyCustomization
Messaging
Patches
Player
PlayerBodySetup/Remote
QSB.csprojQSBCore.csmanifest.jsonQSBPatcher
README.mdSteamRerouter/ExeSide
8
QSB.sln
8
QSB.sln
@ -29,7 +29,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mirror", "Mirror", "{851AB4
|
||||
Mirror\Telepathy.dll = Mirror\Telepathy.dll
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "APITestMod", "APITestMod\APITestMod.csproj", "{0A10143E-6C00-409B-B3A5-C54C1B01599D}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "APITestMod", "APITestMod\APITestMod.csproj", "{0A10143E-6C00-409B-B3A5-C54C1B01599D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QSBPatcher", "QSBPatcher\QSBPatcher.csproj", "{CA4CBA2B-54D5-4C4B-9B51-957BC6D77D6B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@ -57,6 +59,10 @@ Global
|
||||
{0A10143E-6C00-409B-B3A5-C54C1B01599D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0A10143E-6C00-409B-B3A5-C54C1B01599D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0A10143E-6C00-409B-B3A5-C54C1B01599D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CA4CBA2B-54D5-4C4B-9B51-957BC6D77D6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CA4CBA2B-54D5-4C4B-9B51-957BC6D77D6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CA4CBA2B-54D5-4C4B-9B51-957BC6D77D6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CA4CBA2B-54D5-4C4B-9B51-957BC6D77D6B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -10,6 +10,7 @@
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/CASE_BLOCK_BRACES/@EntryValue">NEXT_LINE_SHIFTED_2</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=API/@EntryIndexedValue">API</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ID/@EntryIndexedValue">ID</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OW/@EntryIndexedValue">OW</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=QSB/@EntryIndexedValue">QSB</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UWP/@EntryIndexedValue">UWP</s:String>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
|
@ -37,6 +37,19 @@ public interface IQSBAPI
|
||||
/// <param name="playerID">The ID of the player you want the name of.</param>
|
||||
string GetPlayerName(uint playerID);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the position of a given player.
|
||||
/// This position is in world space, where (0, 0, 0) is roughly where the local player is located.
|
||||
/// </summary>
|
||||
/// <param name="playerID">The ID of the player you want the position of.</param>
|
||||
Vector3 GetPlayerPosition(uint playerID);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if a given player has fully loaded into the game. If the local player is still loading into the game, this will return false.
|
||||
/// </summary>
|
||||
/// <param name="playerID">The ID of the player.</param>
|
||||
bool GetPlayerReady(uint playerID);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the list of IDs of all connected players.
|
||||
///
|
||||
|
@ -25,6 +25,13 @@ public class QSBAPI : IQSBAPI
|
||||
|
||||
public uint GetLocalPlayerID() => QSBPlayerManager.LocalPlayerId;
|
||||
public string GetPlayerName(uint playerId) => QSBPlayerManager.GetPlayer(playerId).Name;
|
||||
public Vector3 GetPlayerPosition(uint playerId) => QSBPlayerManager.GetPlayer(playerId).Body.transform.position;
|
||||
|
||||
public bool GetPlayerReady(uint playerId)
|
||||
{
|
||||
var player = QSBPlayerManager.GetPlayer(playerId);
|
||||
return player.IsReady && player.Body != null;
|
||||
}
|
||||
public uint[] GetPlayerIDs() => QSBPlayerManager.PlayerList.Select(x => x.PlayerId).ToArray();
|
||||
|
||||
public UnityEvent<uint> OnPlayerJoin() => QSBAPIEvents.OnPlayerJoinEvent;
|
||||
|
95
QSB/Animation/Player/HelmetAnimator.cs
Normal file
95
QSB/Animation/Player/HelmetAnimator.cs
Normal file
@ -0,0 +1,95 @@
|
||||
using OWML.Common;
|
||||
using QSB.PlayerBodySetup.Remote;
|
||||
using QSB.Utility;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QSB.Animation.Player;
|
||||
|
||||
[UsedInUnityProject]
|
||||
public class HelmetAnimator : MonoBehaviour
|
||||
{
|
||||
public Transform FakeHelmet;
|
||||
public Transform FakeHead;
|
||||
public GameObject SuitGroup;
|
||||
|
||||
private QSBDitheringAnimator _fakeHelmetDitheringAnimator;
|
||||
|
||||
private const float ANIM_TIME = 0.5f;
|
||||
private bool _isPuttingOnHelmet;
|
||||
private bool _isTakingOffHelmet;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
_fakeHelmetDitheringAnimator = FakeHelmet.GetComponent<QSBDitheringAnimator>();
|
||||
|
||||
FakeHead.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
public void RemoveHelmet()
|
||||
{
|
||||
if (!SuitGroup.activeSelf)
|
||||
{
|
||||
DebugLog.DebugWrite($"Trying to remove helmet when player is not wearing suit!", MessageType.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
_fakeHelmetDitheringAnimator.SetVisible(true);
|
||||
FakeHelmet.gameObject.SetActive(true);
|
||||
FakeHead.gameObject.SetActive(true);
|
||||
_fakeHelmetDitheringAnimator.SetVisible(false, ANIM_TIME);
|
||||
_isTakingOffHelmet = true;
|
||||
}
|
||||
|
||||
public void PutOnHelmet()
|
||||
{
|
||||
if (!SuitGroup.activeSelf)
|
||||
{
|
||||
DebugLog.DebugWrite($"Trying to put on helmet when player is not wearing suit!", MessageType.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
_fakeHelmetDitheringAnimator.SetVisible(false);
|
||||
FakeHead.gameObject.SetActive(true);
|
||||
FakeHelmet.gameObject.SetActive(true);
|
||||
_fakeHelmetDitheringAnimator.SetVisible(true, ANIM_TIME);
|
||||
_isPuttingOnHelmet = true;
|
||||
}
|
||||
|
||||
public void SetHelmetInstant(bool helmetOn)
|
||||
{
|
||||
if (helmetOn)
|
||||
{
|
||||
FakeHelmet.gameObject.SetActive(true);
|
||||
_fakeHelmetDitheringAnimator.SetVisible(true);
|
||||
FakeHead.gameObject.SetActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_fakeHelmetDitheringAnimator.SetVisible(false);
|
||||
FakeHelmet.gameObject.SetActive(false);
|
||||
if (!SuitGroup.activeSelf)
|
||||
{
|
||||
FakeHead.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (_isPuttingOnHelmet && _fakeHelmetDitheringAnimator.FullyVisible)
|
||||
{
|
||||
_isPuttingOnHelmet = false;
|
||||
FakeHead.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
if (_isTakingOffHelmet && _fakeHelmetDitheringAnimator.FullyInvisible)
|
||||
{
|
||||
FakeHelmet.gameObject.SetActive(false);
|
||||
|
||||
if (!SuitGroup.activeSelf)
|
||||
{
|
||||
FakeHead.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
43
QSB/Animation/Player/Messages/PlayerHelmetMessage.cs
Normal file
43
QSB/Animation/Player/Messages/PlayerHelmetMessage.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using QSB.Messaging;
|
||||
using QSB.Player.TransformSync;
|
||||
using QSB.WorldSync;
|
||||
using QSB.Player;
|
||||
|
||||
namespace QSB.Animation.Player.Messages;
|
||||
|
||||
public class PlayerHelmetMessage : QSBMessage<bool>
|
||||
{
|
||||
static PlayerHelmetMessage()
|
||||
{
|
||||
GlobalMessenger.AddListener(OWEvents.PutOnHelmet, () => Handle(true));
|
||||
GlobalMessenger.AddListener(OWEvents.RemoveHelmet, () => Handle(false));
|
||||
}
|
||||
|
||||
private static void Handle(bool on)
|
||||
{
|
||||
if (PlayerTransformSync.LocalInstance)
|
||||
{
|
||||
new PlayerHelmetMessage(on).Send();
|
||||
}
|
||||
}
|
||||
|
||||
public PlayerHelmetMessage(bool on) : base(on) { }
|
||||
|
||||
public override bool ShouldReceive => QSBWorldSync.AllObjectsReady;
|
||||
|
||||
public override void OnReceiveRemote()
|
||||
{
|
||||
var player = QSBPlayerManager.GetPlayer(From);
|
||||
var animator = player.HelmetAnimator;
|
||||
if (Data)
|
||||
{
|
||||
animator.PutOnHelmet();
|
||||
player.AudioController.PlayWearHelmet();
|
||||
}
|
||||
else
|
||||
{
|
||||
animator.RemoveHelmet();
|
||||
player.AudioController.PlayRemoveHelmet();
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
BIN
QSB/AssetBundles/qsb_skins
Normal file
BIN
QSB/AssetBundles/qsb_skins
Normal file
Binary file not shown.
@ -12,6 +12,7 @@ public class QSBPlayerAudioController : MonoBehaviour
|
||||
public OWAudioSource _damageAudioSource;
|
||||
|
||||
private AudioManager _audioManager;
|
||||
private float _playWearHelmetTime;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
@ -30,6 +31,15 @@ public class QSBPlayerAudioController : MonoBehaviour
|
||||
damageAudio.SetActive(true);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Time.time > this._playWearHelmetTime)
|
||||
{
|
||||
enabled = false;
|
||||
PlayOneShot(global::AudioType.PlayerSuitWearHelmet);
|
||||
}
|
||||
}
|
||||
|
||||
public void PlayEquipTool()
|
||||
=> _oneShotExternalSource?.PlayOneShot(AudioType.ToolTranslatorEquip);
|
||||
|
||||
@ -48,6 +58,18 @@ public class QSBPlayerAudioController : MonoBehaviour
|
||||
public void PlayRemoveSuit()
|
||||
=> PlayOneShot(AudioType.PlayerSuitRemoveSuit);
|
||||
|
||||
public void PlayRemoveHelmet()
|
||||
{
|
||||
enabled = false;
|
||||
PlayOneShot(AudioType.PlayerSuitRemoveHelmet);
|
||||
}
|
||||
|
||||
public void PlayWearHelmet()
|
||||
{
|
||||
enabled = true;
|
||||
_playWearHelmetTime = Time.time + 0.4f;
|
||||
}
|
||||
|
||||
public void PlayOneShot(AudioType audioType, float pitch = 1f, float volume = 1f)
|
||||
{
|
||||
if (_oneShotExternalSource)
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using OWML.Common;
|
||||
using QSB.Utility;
|
||||
using UnityEngine;
|
||||
|
||||
@ -9,13 +10,26 @@ public class BodyCustomizer : MonoBehaviour, IAddComponentOnStart
|
||||
private Dictionary<string, (Texture2D albedo, Texture2D normal)> skinMap = new();
|
||||
private Dictionary<string, Texture2D> jetpackMap = new();
|
||||
|
||||
public AssetBundle SkinsBundle { get; private set; }
|
||||
|
||||
public static BodyCustomizer Instance { get; private set; }
|
||||
|
||||
private void Start()
|
||||
{
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
skinMap.Add("Default", (QSBCore.BigBundle.LoadAsset<Texture2D>("Assets/GameAssets/Texture2D/Traveller_HEA_Player_Skin_d.png"), QSBCore.BigBundle.LoadAsset<Texture2D>("Assets/GameAssets/Texture2D/Traveller_HEA_Player_Skin_n.png")));
|
||||
public void OnBundleLoaded(AssetBundle bundle)
|
||||
{
|
||||
SkinsBundle = bundle;
|
||||
LoadAssets();
|
||||
}
|
||||
|
||||
private void LoadAssets()
|
||||
{
|
||||
DebugLog.DebugWrite($"Loading skin assets...", MessageType.Info);
|
||||
|
||||
skinMap.Add("Default", (SkinsBundle.LoadAsset<Texture2D>("Assets/GameAssets/Texture2D/Traveller_HEA_Player_Skin_d.png"), SkinsBundle.LoadAsset<Texture2D>("Assets/GameAssets/Texture2D/Traveller_HEA_Player_Skin_n.png")));
|
||||
skinMap.Add("Type 1", LoadSkin("Type 1"));
|
||||
skinMap.Add("Type 2", LoadSkin("Type 2"));
|
||||
skinMap.Add("Type 3", LoadSkin("Type 3"));
|
||||
@ -34,7 +48,7 @@ public class BodyCustomizer : MonoBehaviour, IAddComponentOnStart
|
||||
skinMap.Add("Type 16", LoadSkin("Type 16"));
|
||||
skinMap.Add("Type 17", LoadSkin("Type 17"));
|
||||
|
||||
jetpackMap.Add("Orange", QSBCore.BigBundle.LoadAsset<Texture2D>("Assets/GameAssets/Texture2D/Props_HEA_Jetpack_d.png"));
|
||||
jetpackMap.Add("Orange", SkinsBundle.LoadAsset<Texture2D>("Assets/GameAssets/Texture2D/Props_HEA_Jetpack_d.png"));
|
||||
jetpackMap.Add("Yellow", LoadJetpack("yellow"));
|
||||
jetpackMap.Add("Red", LoadJetpack("red"));
|
||||
jetpackMap.Add("Pink", LoadJetpack("pink"));
|
||||
@ -48,22 +62,26 @@ public class BodyCustomizer : MonoBehaviour, IAddComponentOnStart
|
||||
private (Texture2D d, Texture2D n) LoadSkin(string skinName)
|
||||
{
|
||||
var number = skinName.Replace($"Type ", "");
|
||||
return (QSBCore.BigBundle.LoadAsset<Texture2D>($"Assets/GameAssets/Texture2D/Skin Variations/{number}d.png"), QSBCore.BigBundle.LoadAsset<Texture2D>($"Assets/GameAssets/Texture2D/Skin Variations/{number}n.png"));
|
||||
return (SkinsBundle.LoadAsset<Texture2D>($"Assets/GameAssets/Texture2D/Skin Variations/{number}d.png"), SkinsBundle.LoadAsset<Texture2D>($"Assets/GameAssets/Texture2D/Skin Variations/{number}n.png"));
|
||||
}
|
||||
|
||||
private Texture2D LoadJetpack(string jetpackName)
|
||||
{
|
||||
return QSBCore.BigBundle.LoadAsset<Texture2D>($"Assets/GameAssets/Texture2D/Jetpack Variations/{jetpackName}.png");
|
||||
return SkinsBundle.LoadAsset<Texture2D>($"Assets/GameAssets/Texture2D/Jetpack Variations/{jetpackName}.png");
|
||||
}
|
||||
|
||||
public void CustomizeRemoteBody(GameObject REMOTE_Traveller_HEA_Player_v2, string skinType, string jetpackType)
|
||||
public void CustomizeRemoteBody(GameObject REMOTE_Traveller_HEA_Player_v2, GameObject fakeHead, string skinType, string jetpackType)
|
||||
{
|
||||
var headMesh = REMOTE_Traveller_HEA_Player_v2.transform.Find("player_mesh_noSuit:Traveller_HEA_Player/player_mesh_noSuit:Player_Head");
|
||||
var skinMaterial = headMesh.GetComponent<SkinnedMeshRenderer>().material;
|
||||
|
||||
var skinMaterial = headMesh.GetComponent<SkinnedMeshRenderer>().material;
|
||||
skinMaterial.SetTexture("_MainTex", skinMap[skinType].albedo);
|
||||
skinMaterial.SetTexture("_BumpMap", skinMap[skinType].normal);
|
||||
|
||||
var fakeHeadMaterial = fakeHead.GetComponent<SkinnedMeshRenderer>().material;
|
||||
fakeHeadMaterial.SetTexture("_MainTex", skinMap[skinType].albedo);
|
||||
fakeHeadMaterial.SetTexture("_BumpMap", skinMap[skinType].normal);
|
||||
|
||||
var jetpackMesh = REMOTE_Traveller_HEA_Player_v2.transform.Find("Traveller_Mesh_v01:Traveller_Geo/Traveller_Mesh_v01:Props_HEA_Jetpack");
|
||||
var jetpackMaterial = jetpackMesh.GetComponent<SkinnedMeshRenderer>().material;
|
||||
|
||||
|
@ -41,4 +41,6 @@ public static class OWEvents
|
||||
public const string ProbeExitQuantumMoon = nameof(ProbeExitQuantumMoon);
|
||||
public const string EnterCloak = nameof(EnterCloak);
|
||||
public const string ExitCloak = nameof(ExitCloak);
|
||||
public const string PutOnHelmet = nameof(PutOnHelmet);
|
||||
public const string RemoveHelmet = nameof(RemoveHelmet);
|
||||
}
|
@ -87,10 +87,10 @@ public static class QSBPatchManager
|
||||
}
|
||||
|
||||
OnPatchType?.SafeInvoke(type);
|
||||
DebugLog.DebugWrite($"Patch block {Enum.GetName(typeof(QSBPatchTypes), type)}", MessageType.Info);
|
||||
//DebugLog.DebugWrite($"Patch block {Enum.GetName(typeof(QSBPatchTypes), type)}", MessageType.Info);
|
||||
foreach (var patch in _patchList.Where(x => x.Type == type && x.PatchVendor.HasFlag(QSBCore.GameVendor)))
|
||||
{
|
||||
DebugLog.DebugWrite($" - Patching in {patch.GetType().Name}", MessageType.Info);
|
||||
//DebugLog.DebugWrite($" - Patching in {patch.GetType().Name}", MessageType.Info);
|
||||
try
|
||||
{
|
||||
patch.DoPatches(TypeToInstance[type]);
|
||||
|
@ -13,6 +13,7 @@ public class PlayerInformationMessage : QSBMessage
|
||||
private bool IsReady;
|
||||
private bool FlashlightActive;
|
||||
private bool SuitedUp;
|
||||
private bool HelmetOn;
|
||||
private bool LocalProbeLauncherEquipped;
|
||||
private bool SignalscopeEquipped;
|
||||
private bool TranslatorEquipped;
|
||||
@ -31,6 +32,7 @@ public class PlayerInformationMessage : QSBMessage
|
||||
IsReady = player.IsReady;
|
||||
FlashlightActive = player.FlashlightActive;
|
||||
SuitedUp = player.SuitedUp;
|
||||
HelmetOn = Locator.GetPlayerSuit() != null && Locator.GetPlayerSuit().IsWearingHelmet();
|
||||
LocalProbeLauncherEquipped = player.LocalProbeLauncherEquipped;
|
||||
SignalscopeEquipped = player.SignalscopeEquipped;
|
||||
TranslatorEquipped = player.TranslatorEquipped;
|
||||
@ -50,6 +52,7 @@ public class PlayerInformationMessage : QSBMessage
|
||||
writer.Write(IsReady);
|
||||
writer.Write(FlashlightActive);
|
||||
writer.Write(SuitedUp);
|
||||
writer.Write(HelmetOn);
|
||||
writer.Write(LocalProbeLauncherEquipped);
|
||||
writer.Write(SignalscopeEquipped);
|
||||
writer.Write(TranslatorEquipped);
|
||||
@ -69,6 +72,7 @@ public class PlayerInformationMessage : QSBMessage
|
||||
IsReady = reader.Read<bool>();
|
||||
FlashlightActive = reader.Read<bool>();
|
||||
SuitedUp = reader.Read<bool>();
|
||||
HelmetOn = reader.Read<bool>();
|
||||
LocalProbeLauncherEquipped = reader.Read<bool>();
|
||||
SignalscopeEquipped = reader.Read<bool>();
|
||||
TranslatorEquipped = reader.Read<bool>();
|
||||
@ -91,22 +95,23 @@ public class PlayerInformationMessage : QSBMessage
|
||||
player.IsReady = IsReady;
|
||||
player.FlashlightActive = FlashlightActive;
|
||||
player.SuitedUp = SuitedUp;
|
||||
|
||||
player.LocalProbeLauncherEquipped = LocalProbeLauncherEquipped;
|
||||
player.SignalscopeEquipped = SignalscopeEquipped;
|
||||
player.TranslatorEquipped = TranslatorEquipped;
|
||||
player.ProbeActive = ProbeActive;
|
||||
player.IsInShip = IsInShip;
|
||||
if (QSBPlayerManager.LocalPlayer.IsReady && player.IsReady)
|
||||
|
||||
Delay.RunWhen(() => player.IsReady && QSBPlayerManager.LocalPlayer.IsReady, () =>
|
||||
{
|
||||
player.UpdateObjectsFromStates();
|
||||
player.HelmetAnimator.SetHelmetInstant(HelmetOn);
|
||||
|
||||
var REMOTE_Traveller_HEA_Player_v2 = player.Body.transform.Find("REMOTE_Traveller_HEA_Player_v2");
|
||||
BodyCustomization.BodyCustomizer.Instance.CustomizeRemoteBody(REMOTE_Traveller_HEA_Player_v2.gameObject, SkinType, JetpackType);
|
||||
}
|
||||
BodyCustomization.BodyCustomizer.Instance.CustomizeRemoteBody(REMOTE_Traveller_HEA_Player_v2.gameObject, player.HelmetAnimator.FakeHead.gameObject, SkinType, JetpackType);
|
||||
|
||||
Delay.RunWhen(
|
||||
() => player.Camera != null,
|
||||
() => player.Camera.fieldOfView = FieldOfView);
|
||||
player.Camera.fieldOfView = FieldOfView;
|
||||
});
|
||||
|
||||
player.State = ClientState;
|
||||
|
||||
|
@ -12,4 +12,5 @@ public partial class PlayerInfo
|
||||
internal QSBDitheringAnimator _ditheringAnimator;
|
||||
public DreamWorldSpawnAnimator DreamWorldSpawnAnimator { get; set; }
|
||||
public RemotePlayerFluidDetector FluidDetector { get; set; }
|
||||
public HelmetAnimator HelmetAnimator { get; set; }
|
||||
}
|
||||
|
@ -35,6 +35,12 @@ public class PlayerTransformSync : SectoredTransformSync
|
||||
{
|
||||
var player = new PlayerInfo(this);
|
||||
QSBPlayerManager.PlayerList.SafeAdd(player);
|
||||
|
||||
if (isLocalPlayer)
|
||||
{
|
||||
LocalInstance = this;
|
||||
}
|
||||
|
||||
base.OnStartClient();
|
||||
QSBPatch.Remote = !isLocalPlayer;
|
||||
QSBPlayerManager.OnAddPlayer?.SafeInvoke(Player);
|
||||
|
@ -59,6 +59,10 @@ public class QSBDitheringAnimator : MonoBehaviour
|
||||
|
||||
private void UpdateRenderers()
|
||||
{
|
||||
_renderers ??= GetComponentsInChildren<Renderer>(true)
|
||||
.Select(x => (x.gameObject.GetAddComponent<OWRenderer>(), x.shadowCastingMode != ShadowCastingMode.Off))
|
||||
.ToArray();
|
||||
|
||||
foreach (var (renderer, updateShadows) in _renderers)
|
||||
{
|
||||
if (renderer == null)
|
||||
|
@ -1,4 +1,5 @@
|
||||
using QSB.Audio;
|
||||
using QSB.Animation.Player;
|
||||
using QSB.Audio;
|
||||
using QSB.EchoesOfTheEye.LightSensorSync;
|
||||
using QSB.Player;
|
||||
using QSB.RoastingSync;
|
||||
@ -54,6 +55,7 @@ public static class RemotePlayerCreation
|
||||
player.ThrusterLightTracker = player.Body.GetComponentInChildren<ThrusterLightTracker>();
|
||||
player.FluidDetector = REMOTE_PlayerDetector.GetComponent<RemotePlayerFluidDetector>();
|
||||
player.RulesetDetector = REMOTE_PlayerDetector.GetComponent<RemotePlayerRulesetDetector>();
|
||||
player.HelmetAnimator = REMOTE_Traveller_HEA_Player_v2.GetComponent<HelmetAnimator>();
|
||||
|
||||
player.AnimationSync.InitRemote(REMOTE_Traveller_HEA_Player_v2.transform);
|
||||
|
||||
|
@ -79,6 +79,7 @@
|
||||
<Reference Include="..\Lib\*.dll" />
|
||||
<ProjectReference Include="..\FizzySteamworks\FizzySteamworks.csproj" />
|
||||
<ProjectReference Include="..\SteamRerouter\SteamRerouter.csproj" />
|
||||
<ProjectReference Include="..\QSBPatcher\QSBPatcher.csproj" />
|
||||
<ProjectReference Include="..\MirrorWeaver\MirrorWeaver.csproj" ReferenceOutputAssembly="false" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
@ -14,10 +14,12 @@ using QSB.WorldSync;
|
||||
using Steamworks;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using QSB.API;
|
||||
using QSB.BodyCustomization;
|
||||
using QSB.Player.Messages;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
@ -54,7 +56,6 @@ public class QSBCore : ModBehaviour
|
||||
public static AssetBundle ConversationAssetBundle { get; private set; }
|
||||
public static AssetBundle DebugAssetBundle { get; private set; }
|
||||
public static AssetBundle HUDAssetBundle { get; private set; }
|
||||
public static AssetBundle BigBundle { get; private set; }
|
||||
public static bool IsHost => NetworkServer.active;
|
||||
public static bool IsInMultiplayer;
|
||||
public static string QSBVersion => Helper.Manifest.Version;
|
||||
@ -78,8 +79,6 @@ public class QSBCore : ModBehaviour
|
||||
public static IMenuAPI MenuApi { get; private set; }
|
||||
public static DebugSettings DebugSettings { get; private set; } = new();
|
||||
|
||||
public const string NEW_HORIZONS = "xen.NewHorizons";
|
||||
public const string NEW_HORIZONS_COMPAT = "xen.NHQSBCompat";
|
||||
|
||||
public static readonly string[] IncompatibleMods =
|
||||
{
|
||||
@ -92,6 +91,8 @@ public class QSBCore : ModBehaviour
|
||||
"PacificEngine.OW_Randomizer",
|
||||
};
|
||||
|
||||
public static event Action OnSkinsBundleLoaded;
|
||||
|
||||
public override object GetApi() => new QSBAPI();
|
||||
|
||||
private static void DetermineGameVendor()
|
||||
@ -161,7 +162,7 @@ public class QSBCore : ModBehaviour
|
||||
|
||||
if (!SteamAPI.Init())
|
||||
{
|
||||
DebugLog.ToConsole($"FATAL - SteamAPI.Init() failed. Refer to Valve's documentation.", MessageType.Fatal);
|
||||
DebugLog.ToConsole($"FATAL - SteamAPI.Init() failed. Do you have Steam open, and are you logged in?", MessageType.Fatal);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -258,18 +259,15 @@ public class QSBCore : ModBehaviour
|
||||
|
||||
MenuApi = ModHelper.Interaction.TryGetModApi<IMenuAPI>(ModHelper.Manifest.Dependencies[0]);
|
||||
|
||||
DebugLog.DebugWrite("loading qsb_network_big bundle", MessageType.Info);
|
||||
var path = Path.Combine(ModHelper.Manifest.ModFolderPath, "AssetBundles/qsb_network_big");
|
||||
var request = AssetBundle.LoadFromFileAsync(path);
|
||||
request.completed += _ => DebugLog.DebugWrite("qsb_network_big bundle loaded", MessageType.Success);
|
||||
BigBundle = request.assetBundle;
|
||||
LoadBundleAsync("qsb_network_big");
|
||||
LoadBundleAsync("qsb_skins", request => BodyCustomizer.Instance.OnBundleLoaded(request.assetBundle));
|
||||
|
||||
NetworkAssetBundle = Helper.Assets.LoadBundle("AssetBundles/qsb_network");
|
||||
ConversationAssetBundle = Helper.Assets.LoadBundle("AssetBundles/qsb_conversation");
|
||||
DebugAssetBundle = Helper.Assets.LoadBundle("AssetBundles/qsb_debug");
|
||||
HUDAssetBundle = Helper.Assets.LoadBundle("AssetBundles/qsb_hud");
|
||||
NetworkAssetBundle = LoadBundle("qsb_network");
|
||||
ConversationAssetBundle = LoadBundle("qsb_conversation");
|
||||
DebugAssetBundle = LoadBundle("qsb_debug");
|
||||
HUDAssetBundle = LoadBundle("qsb_hud");
|
||||
|
||||
if (NetworkAssetBundle == null || ConversationAssetBundle == null || DebugAssetBundle == null)
|
||||
if (NetworkAssetBundle == null || ConversationAssetBundle == null || DebugAssetBundle == null || HUDAssetBundle == null)
|
||||
{
|
||||
DebugLog.ToConsole($"FATAL - An assetbundle is missing! Re-install mod or contact devs.", MessageType.Fatal);
|
||||
return;
|
||||
@ -287,6 +285,31 @@ public class QSBCore : ModBehaviour
|
||||
QSBPatchManager.OnUnpatchType += OnUnpatchType;
|
||||
}
|
||||
|
||||
private AssetBundle LoadBundle(string name)
|
||||
{
|
||||
var timer = new Stopwatch();
|
||||
timer.Start();
|
||||
var ret = Helper.Assets.LoadBundle($"AssetBundles/{name}");
|
||||
timer.Stop();
|
||||
DebugLog.ToConsole($"Bundle {name} loaded in {timer.ElapsedMilliseconds} ms!", MessageType.Success);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void LoadBundleAsync(string bundleName, Action<AssetBundleCreateRequest> runOnLoaded = null)
|
||||
{
|
||||
DebugLog.DebugWrite($"Loading {bundleName}...", MessageType.Info);
|
||||
var timer = new Stopwatch();
|
||||
timer.Start();
|
||||
var path = Path.Combine(ModHelper.Manifest.ModFolderPath, $"AssetBundles/{bundleName}");
|
||||
var request = AssetBundle.LoadFromFileAsync(path);
|
||||
request.completed += _ =>
|
||||
{
|
||||
timer.Stop();
|
||||
DebugLog.ToConsole($"Bundle {bundleName} loaded in {timer.ElapsedMilliseconds} ms!", MessageType.Success);
|
||||
runOnLoaded?.Invoke(request);
|
||||
};
|
||||
}
|
||||
|
||||
private static void OnPatchType(QSBPatchTypes type)
|
||||
{
|
||||
if (type == QSBPatchTypes.OnClientConnect)
|
||||
|
@ -12,5 +12,6 @@
|
||||
"owmlVersion": "2.9.8",
|
||||
"dependencies": [ "_nebula.MenuFramework", "JohnCorby.VanillaFix" ],
|
||||
"pathsToPreserve": [ "debugsettings.json" ],
|
||||
"requireLatestVersion": true
|
||||
"requireLatestVersion": true,
|
||||
"patcher": "QSBPatcher.exe"
|
||||
}
|
||||
|
45
QSBPatcher/QSBPatcher.cs
Normal file
45
QSBPatcher/QSBPatcher.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace QSBPatcher;
|
||||
|
||||
public static class QSBPatcher
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var basePath = args.Length > 0 ? args[0] : ".";
|
||||
var gamePath = AppDomain.CurrentDomain.BaseDirectory;
|
||||
|
||||
var steamDLLPath = Path.Combine(basePath, "com.rlabrecque.steamworks.net.dll");
|
||||
|
||||
var managedPath = Path.Combine(gamePath, GetDataPath(gamePath), "Managed");
|
||||
|
||||
File.Copy(steamDLLPath, Path.Combine(managedPath, "com.rlabrecque.steamworks.net.dll"), true);
|
||||
}
|
||||
|
||||
private static string GetDataDirectoryName()
|
||||
{
|
||||
var gamePath = AppDomain.CurrentDomain.BaseDirectory;
|
||||
return $"{GetExecutableName(gamePath)}_Data";
|
||||
}
|
||||
|
||||
private static string GetDataPath(string gamePath)
|
||||
{
|
||||
return Path.Combine(gamePath, $"{GetDataDirectoryName()}");
|
||||
}
|
||||
|
||||
private static string GetExecutableName(string gamePath)
|
||||
{
|
||||
var executableNames = new[] { "Outer Wilds.exe", "OuterWilds.exe" };
|
||||
foreach (var executableName in executableNames)
|
||||
{
|
||||
var executablePath = Path.Combine(gamePath, executableName);
|
||||
if (File.Exists(executablePath))
|
||||
{
|
||||
return Path.GetFileNameWithoutExtension(executablePath);
|
||||
}
|
||||
}
|
||||
|
||||
throw new FileNotFoundException($"Outer Wilds exe file not found in {gamePath}");
|
||||
}
|
||||
}
|
12
QSBPatcher/QSBPatcher.csproj
Normal file
12
QSBPatcher/QSBPatcher.csproj
Normal file
@ -0,0 +1,12 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AssemblyTitle>QSB Patcher</AssemblyTitle>
|
||||
<Product>QSB Patcher</Product>
|
||||
<Title>QSB Patcher</Title>
|
||||
<Description>Copies steamworks into the game for non-steam vendors</Description>
|
||||
<Authors>William Corby, Henry Pointer</Authors>
|
||||
<Company>William Corby, Henry Pointer</Company>
|
||||
<Copyright>Copyright © William Corby, Henry Pointer 2022-2023</Copyright>
|
||||
</PropertyGroup>
|
||||
</Project>
|
@ -34,6 +34,7 @@ Spoilers within!
|
||||
|
||||
#### Connecting to a server
|
||||
|
||||
- Make sure to have Steam open and logged in.
|
||||
- On the title screen, click the option `CONNECT TO MULTIPLAYER`.
|
||||
- Enter the Steam ID of the person you are trying to connect to.
|
||||
- If "Use KCP Transport" is enabled, enter the public IP address of the person instead.
|
||||
@ -41,6 +42,7 @@ Spoilers within!
|
||||
|
||||
#### Hosting a server
|
||||
|
||||
- Make sure to have Steam open and logged in.
|
||||
- On the title screen, click the option `OPEN TO MULTIPLAYER`.
|
||||
- Share your Steam ID with the people who want to connect.
|
||||
- If "Use KCP Transport" is enabled, share your public IP address instead. This can be found on websites like https://www.whatismyip.com/.
|
||||
|
@ -53,7 +53,7 @@ public static class Program
|
||||
|
||||
if (!SteamAPI.Init())
|
||||
{
|
||||
LogError($"FATAL - SteamAPI.Init() failed. Refer to Valve's documentation.");
|
||||
LogError($"FATAL - SteamAPI.Init() failed. Do you have Steam open, and are you logged in?");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user