Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync footstep audio #2177

Merged
merged 41 commits into from
Oct 20, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
d4e3ff2
Created packet and processors for footstep audio(not functional at al…
OhmV-IR Aug 28, 2024
7e0c624
prototype client-side footstep packet processing
OhmV-IR Aug 30, 2024
380d9ba
Switch to using player's AnimationController to find velocity
OhmV-IR Aug 30, 2024
e07a5c3
Footstep packets are forwarded from server to players within hearing …
OhmV-IR Sep 2, 2024
180bb35
Fixed FootstepPacket class to fit format(was crashing)
OhmV-IR Sep 2, 2024
26db96c
Removed duplicate var
OhmV-IR Sep 2, 2024
a772c16
cleanup
OhmV-IR Sep 2, 2024
eaf1122
Added transpiler to send packets when local client plays footstep sou…
OhmV-IR Sep 2, 2024
a879656
Lower volume of other players' footsteps(suggested by NinjaPedroX)
OhmV-IR Sep 2, 2024
8ef9842
Added same structure/submarine check for sending footstep packet to o…
OhmV-IR Sep 2, 2024
092af16
Removed logs
OhmV-IR Sep 7, 2024
c6814b3
Formatting changes
OhmV-IR Sep 7, 2024
737028e
Formatting changes
OhmV-IR Sep 7, 2024
103c14e
Newline changes
OhmV-IR Sep 18, 2024
5a5fc18
newline changes
OhmV-IR Sep 18, 2024
91936ec
Split long line into shorter lines
OhmV-IR Sep 18, 2024
6545583
Remove unneeded this keyword
OhmV-IR Sep 18, 2024
33d249c
Applying suggestions from Jannify's review
OhmV-IR Sep 18, 2024
8cc0956
Merge
OhmV-IR Sep 18, 2024
c1d0ef3
Added comment in packet processors to keep values updated, trying to …
OhmV-IR Sep 18, 2024
c4c851f
Pull sound range from .csv file(UNTESTED)
OhmV-IR Sep 18, 2024
756bece
Add whitespace
OhmV-IR Sep 24, 2024
30055b8
Add whitespace
OhmV-IR Sep 24, 2024
d26a186
Merged ifs and removed var type usage
OhmV-IR Sep 24, 2024
5c6f971
Merge branch 'sync-footstep-audio' of https://github.com/OhmV-IR/Nitr…
OhmV-IR Sep 24, 2024
38c6161
Merged else + if into else if
OhmV-IR Sep 24, 2024
9a5927b
Inverted if with early return condition
OhmV-IR Sep 24, 2024
38c1aa7
Compare subroot IDs using .Equals instead of 2 if statements
OhmV-IR Sep 26, 2024
6d4dcbf
Overriding .Equals in Optional<> for consistency and performance
OhmV-IR Sep 26, 2024
bef5717
Merged 2 if statements & fixed bad clause
OhmV-IR Sep 26, 2024
7e56f40
Fixed bug(was getting all players instead of only connected ones)
OhmV-IR Sep 28, 2024
76c9b07
Changed names of StepSound enum members
OhmV-IR Sep 30, 2024
2bd2d9d
removed unneeded this keyword
OhmV-IR Oct 1, 2024
7d81eaa
Reordered and cleaned usings
OhmV-IR Oct 1, 2024
5b17e1f
Did sort and clean usings with correct setting
OhmV-IR Oct 2, 2024
4d70262
added extra if check
OhmV-IR Oct 2, 2024
80b4006
Change number of added instructions in test class
OhmV-IR Oct 12, 2024
33b5201
equality methods can be used by systems depending on the IEquatable a…
OhmV-IR Oct 15, 2024
22e8113
Inverted if statement
OhmV-IR Oct 15, 2024
5a4b34a
Updated sound levels
OhmV-IR Oct 19, 2024
7f2b288
Change references of exosuit steps asset path to land asset path
OhmV-IR Oct 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -281,9 +281,9 @@ event:/player/enzyme_cure;false;false;0
event:/player/food_critical;false;false;0
event:/player/food_low;false;false;0
event:/player/food_very_low;false;false;0
event:/player/footstep_dirt;false;false;0
event:/player/footstep_metal;false;false;0
event:/player/footstep_precursor_base;false;false;0
event:/player/footstep_dirt;false;false;20
event:/player/footstep_metal;false;false;20
event:/player/footstep_precursor_base;false;false;20
event:/player/goal_airsack;false;false;0
event:/player/goal_BiomeKelpForest;false;false;0
event:/player/goal_BiomePrecursorGunUpper;false;false;0
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using FMOD;
using FMOD.Studio;
using FMODUnity;
using NitroxClient.Communication.Packets.Processors.Abstract;
using NitroxClient.GameLogic;
using NitroxClient.GameLogic.FMOD;
using NitroxModel.GameLogic.FMOD;
using NitroxModel.Packets;

namespace NitroxClient.Communication.Packets.Processors;

public class FootstepPacketProcessor : ClientPacketProcessor<FootstepPacket>
{
private readonly PlayerManager remotePlayerManager;
private readonly FootstepSounds localFootstepSounds;
private PARAMETER_ID fmodIndexSpeed = FMODUWE.invalidParameterId;
private readonly float footstepAudioRadius; // To modify this value, modify the last value in the SoundWhitelist_Subnautica.csv file
private const float footstepAudioMaxVolume = 0.5f;

public FootstepPacketProcessor(PlayerManager remotePlayerManager, FMODWhitelist whitelist)
{
this.remotePlayerManager = remotePlayerManager;
localFootstepSounds = Player.mainObject.GetComponent<FootstepSounds>();
whitelist.TryGetSoundData("event:/player/footstep_precursor_base", out SoundData soundData);
footstepAudioRadius = soundData.Radius;
}

public override void Process(FootstepPacket packet)
{
var player = remotePlayerManager.Find(packet.PlayerID);
OhmV-IR marked this conversation as resolved.
Show resolved Hide resolved
if (player.HasValue)
{
FMODAsset asset = packet.AssetIndex switch
{
FootstepPacket.StepSounds.PRECURSOR_STEP_SOUND => localFootstepSounds.precursorInteriorSound,
FootstepPacket.StepSounds.METAL_STEP_SOUND => localFootstepSounds.metalSound,
FootstepPacket.StepSounds.LAND_STEP_SOUND => localFootstepSounds.landSound,
_ => null
};
EventInstance evt = FMODUWE.GetEvent(asset);
if (evt.isValid())
{
if (FMODUWE.IsInvalidParameterId(fmodIndexSpeed))
{
fmodIndexSpeed = FMODUWE.GetEventInstanceParameterIndex(evt, "speed");
}
ATTRIBUTES_3D attributes = player.Value.Body.To3DAttributes();
evt.set3DAttributes(attributes);
evt.setParameterValueByIndex(fmodIndexSpeed, player.Value.AnimationController.Velocity.magnitude);
evt.setVolume(FMODSystem.CalculateVolume(Player.mainObject.transform.position, player.Value.Body.transform.position, footstepAudioRadius, footstepAudioMaxVolume));
evt.start();
evt.release();
}
}
}
}
22 changes: 22 additions & 0 deletions NitroxModel/Packets/FootstepPacket.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;

namespace NitroxModel.Packets;
[Serializable]
OhmV-IR marked this conversation as resolved.
Show resolved Hide resolved
public class FootstepPacket : Packet
{
public ushort PlayerID { get; }
public StepSounds AssetIndex { get; }

public FootstepPacket(ushort playerID, StepSounds assetIndex)
{
this.PlayerID = playerID;
OhmV-IR marked this conversation as resolved.
Show resolved Hide resolved
this.AssetIndex = assetIndex;
}

public enum StepSounds : byte
{
PRECURSOR_STEP_SOUND,
METAL_STEP_SOUND,
LAND_STEP_SOUND
}
OhmV-IR marked this conversation as resolved.
Show resolved Hide resolved
}
46 changes: 43 additions & 3 deletions NitroxPatcher/Patches/Dynamic/FootstepSounds_OnStep_Patch.cs
Original file line number Diff line number Diff line change
@@ -1,32 +1,43 @@
using System;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using FMOD.Studio;
using HarmonyLib;
using NitroxClient.Communication.Abstract;
using NitroxClient.GameLogic;
using NitroxClient.GameLogic.FMOD;
using NitroxModel.GameLogic.FMOD;
using NitroxModel.Helper;
using NitroxModel.Packets;
using UnityEngine;

namespace NitroxPatcher.Patches.Dynamic;

public sealed partial class FootstepSounds_OnStep_Patch : NitroxPatch, IDynamicPatch
{
private const string EXO_STEP_SOUND_PATH = "event:/sub/exo/step";
tornac1234 marked this conversation as resolved.
Show resolved Hide resolved
private const string PRECURSOR_STEP_SOUND_PATH = "event:/player/footstep_precursor_base";
private const string METAL_STEP_SOUND_PATH = "event:/player/footstep_metal";

internal static readonly MethodInfo TARGET_METHOD = Reflect.Method((FootstepSounds t) => t.OnStep(default));

public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
/*
From:

evt.setVolume(volume);

To:

evt.setVolume(CalculateVolume(volume, this, asset, xform));


From:
event.release();

To:
event.release();
SendFootstepPacket(asset);
*/

return new CodeMatcher(instructions)
Expand All @@ -40,6 +51,13 @@ public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructio
new CodeInstruction(OpCodes.Ldarg_1),
new CodeInstruction(OpCodes.Call, Reflect.Method(() => CalculateVolume(default, default, default, default)))
)
.MatchEndForward(
new CodeMatch(OpCodes.Call, Reflect.Method((EventInstance evt) => evt.release())),
new CodeMatch(OpCodes.Pop)
)
.Advance(1)
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_0))
.Insert(new CodeInstruction(OpCodes.Call, Reflect.Method(() => SendFootstepPacket(default))))
.InstructionEnumeration();
}

Expand All @@ -61,4 +79,26 @@ private static float CalculateVolume(float originalVolume, FootstepSounds instan
Resolve<FMODWhitelist>().TryGetSoundData(EXO_STEP_SOUND_PATH, out SoundData soundData);
return soundData.Radius;
});

private static void SendFootstepPacket(FMODAsset asset)
{
if (Resolve<LocalPlayer>().PlayerId.HasValue)
{
FootstepPacket.StepSounds assetIndex;
switch (asset.path)
{
case PRECURSOR_STEP_SOUND_PATH:
assetIndex = FootstepPacket.StepSounds.PRECURSOR_STEP_SOUND;
break;
case METAL_STEP_SOUND_PATH:
assetIndex = FootstepPacket.StepSounds.METAL_STEP_SOUND;
break;
default:
assetIndex = FootstepPacket.StepSounds.LAND_STEP_SOUND;
break;
}
OhmV-IR marked this conversation as resolved.
Show resolved Hide resolved
FootstepPacket footstepPacket = new(Resolve<LocalPlayer>().PlayerId.Value, assetIndex);
Resolve<IPacketSender>().Send(footstepPacket);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using NitroxModel.DataStructures.Unity;
using NitroxModel.GameLogic.FMOD;
using NitroxModel.Packets;
using NitroxServer.Communication.Packets.Processors.Abstract;
using NitroxServer.GameLogic;

namespace NitroxServer.Communication.Packets.Processors;
public class FootstepPacketProcessor : AuthenticatedPacketProcessor<FootstepPacket>
OhmV-IR marked this conversation as resolved.
Show resolved Hide resolved
{
private readonly float footstepAudioRange; // To modify this value, modify the last value in the SoundWhitelist_Subnautica.csv file
private readonly PlayerManager playerManager;

public FootstepPacketProcessor(PlayerManager playerManager, FMODWhitelist whitelist)
{
this.playerManager = playerManager;
whitelist.TryGetSoundData("event:/player/footstep_precursor_base", out SoundData soundData);
footstepAudioRange = soundData.Radius;
}

public override void Process(FootstepPacket footstepPacket, Player sendingPlayer)
{
var players = playerManager.GetAllPlayers();
OhmV-IR marked this conversation as resolved.
Show resolved Hide resolved
foreach (Player player in players)
{
if (sendingPlayer.SubRootId.HasValue)
{
if (player.SubRootId.HasValue)
{
// If both players have id's, check if they are the same
if (NitroxVector3.Distance(player.Position, sendingPlayer.Position) <= footstepAudioRange && player != sendingPlayer && player.SubRootId.Value == sendingPlayer.SubRootId.Value)
OhmV-IR marked this conversation as resolved.
Show resolved Hide resolved
{
// Forward footstep packet to players if they are within range to hear it and are in the same structure / submarine
player.SendPacket(footstepPacket);
}
}
// If one player has an id and the other doesn't, automatically false
}
else
{
// if both player's don't have SubRootIds
if (!player.SubRootId.HasValue)
{
if (NitroxVector3.Distance(player.Position, sendingPlayer.Position) <= footstepAudioRange && player != sendingPlayer)
OhmV-IR marked this conversation as resolved.
Show resolved Hide resolved
{
// Forward footstep packet to players if they are within range to hear it and are in the same structure / submarine
player.SendPacket(footstepPacket);
}
}
// If one player doesn't have an id and other does, automatically false
OhmV-IR marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
}