Skip to content

Commit

Permalink
Some refactoring, added comments, adapted to the new vehicle movement…
Browse files Browse the repository at this point in the history
… system
  • Loading branch information
tornac1234 committed Nov 30, 2024
1 parent 9ccbfde commit 93619cb
Show file tree
Hide file tree
Showing 25 changed files with 115 additions and 113 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using HarmonyLib;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NitroxTest.Patcher;

namespace NitroxPatcher.Patches.Dynamic;
Expand Down
2 changes: 1 addition & 1 deletion NitroxClient/GameLogic/AI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public static void AggressiveWhenSeeTargetChanged(NitroxId creatureId, NitroxId
lastTarget.SetTargetInternal(targetObject);
lastTarget.targetLocked = locked;

if (aggressiveWhenSeeTarget.sightedSound != null && !aggressiveWhenSeeTarget.sightedSound.GetIsPlaying())
if (aggressiveWhenSeeTarget.sightedSound && !aggressiveWhenSeeTarget.sightedSound.GetIsPlaying())
{
// TODO: Adapt this code when #1780 is merged
aggressiveWhenSeeTarget.sightedSound.StartEvent();
Expand Down
7 changes: 5 additions & 2 deletions NitroxClient/GameLogic/BulletManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ public void ShootSeamothTorpedo(NitroxId bulletId, TechType techType, Vector3 po

public void TorpedoHit(NitroxId bulletId, Vector3 position, Quaternion rotation)
{
// On the local player, the torpedo might have already exploded while the packet is received with latency.
// Therefore we don't need to log a failed query of bulletId
if (NitroxEntity.TryGetComponentFrom(bulletId, out SeamothTorpedo torpedo))
{
torpedo.tr.position = position;
Expand Down Expand Up @@ -111,6 +113,7 @@ private StasisSphere EnsurePlayerHasSphere(ushort playerId)

// It should be set to inactive automatically in Bullet.Awake
GameObject playerSphereClone = GameObject.Instantiate(stasisSpherePrefab);
playerSphereClone.name = $"remote-{playerId}-{playerSphereClone.name}";
// We mark it to be able to ignore events from remote bullets
playerSphereClone.AddComponent<RemotePlayerBullet>();
StasisSphere stasisSphere = playerSphereClone.GetComponent<StasisSphere>();
Expand Down Expand Up @@ -159,8 +162,8 @@ public IEnumerator Initialize()
EnsurePlayerHasSphere(remotePlayer.PlayerId);
}

playerManager.onCreate += (playerId, _) => { EnsurePlayerHasSphere(playerId); };
playerManager.onRemove += (playerId, _) => { DestroyPlayerSphere(playerId); };
playerManager.OnCreate += (playerId, _) => { EnsurePlayerHasSphere(playerId); };
playerManager.OnRemove += (playerId, _) => { DestroyPlayerSphere(playerId); };
}

public class RemotePlayerBullet : MonoBehaviour { }
Expand Down
2 changes: 1 addition & 1 deletion NitroxClient/GameLogic/PlayerManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public void RemovePlayer(ushort playerId)
{
player.Destroy();
playersById.Remove(playerId);
OnRemove(playerId, opPlayer.Value);
OnRemove(playerId, player);
DiscordClient.UpdatePartySize(GetTotalPlayerCount());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
namespace NitroxPatcher.Patches.Dynamic;

/// <summary>
/// Allow creatures to chose remote players as targets only if they can be attacked (<see cref="RemotePlayer.CanBeAttacked"/>)
/// Allow creatures to choose remote players as targets only if they can be attacked (<see cref="RemotePlayer.CanBeAttacked"/>)
/// </summary>
public sealed partial class AggressiveWhenSeeTarget_IsTargetValid_Patch : NitroxPatch, IDynamicPatch
{
Expand All @@ -19,7 +19,7 @@ public static bool Prefix(GameObject target, ref bool __result)
{
return false;
}
// We only want to cancel if the target is a remote player which can't attacked
// We only want to cancel if the target is a remote player which can't be attacked
if (target.TryGetComponent(out RemotePlayerIdentifier remotePlayerIdentifier) &&
!remotePlayerIdentifier.RemotePlayer.CanBeAttacked())
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using HarmonyLib;
using NitroxClient.Communication.Abstract;
using NitroxClient.GameLogic;
using NitroxClient.GameLogic.PlayerLogic;
using NitroxClient.MonoBehaviours.Cyclops;
using NitroxModel.DataStructures;
using NitroxModel.Helper;
using NitroxModel.Packets;
Expand Down Expand Up @@ -58,9 +58,8 @@ public static bool Prefix(AttackCyclops __instance)

public static void Postfix(AttackCyclops __instance)
{
if (__instance.currentTarget && __instance.TryGetNitroxId(out NitroxId creatureId) &&
__instance.currentTarget.TryGetNitroxId(out NitroxId targetId) &&
Resolve<SimulationOwnership>().HasAnyLockType(creatureId))
if (__instance.currentTarget && __instance.currentTarget.TryGetNitroxId(out NitroxId targetId) &&
__instance.TryGetNitroxId(out NitroxId creatureId) && Resolve<SimulationOwnership>().HasAnyLockType(creatureId))
{
float aggressiveToNoise = __instance.aggressiveToNoise.Value;

Expand All @@ -87,19 +86,6 @@ public static bool IsTargetAValidInhabitedCyclops(IEcoTarget target)

public static bool IsTargetAValidInhabitedCyclops(GameObject targetObject)
{
// Is a Cyclops
if (!targetObject.TryGetComponent(out SubRoot subRoot) || !subRoot.isCyclops)
{
return false;
}

// Has the local player inside
if (Player.main && Player.main.currentSub == subRoot)
{
return true;
}

// Has a remote player inside
return targetObject.GetComponentInChildren<RemotePlayerIdentifier>(true);
return targetObject.TryGetComponent(out NitroxCyclops nitroxCyclops) && nitroxCyclops.Pawns.Count > 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
namespace NitroxPatcher.Patches.Dynamic;

/// <summary>
/// Allows creatures to chose remote players as targets only if they can be attacked (<see cref="RemotePlayer.CanBeAttacked"/>)
/// Allows creatures to choose remote players as targets only if they can be attacked (<see cref="RemotePlayer.CanBeAttacked"/>)
/// </summary>
public sealed partial class AttackLastTarget_CanAttackTarget_Patch : NitroxPatch, IDynamicPatch
{
Expand All @@ -19,7 +19,7 @@ public static bool Prefix(GameObject target, ref bool __result)
{
return false;
}
// We only want to cancel if the target is a remote player which can't attacked
// We only want to cancel if the target is a remote player which can't be attacked
if (target.TryGetComponent(out RemotePlayerIdentifier remotePlayerIdentifier) &&
!remotePlayerIdentifier.RemotePlayer.CanBeAttacked())
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using System.Reflection;
using NitroxClient.Communication.Abstract;
using NitroxClient.GameLogic;
using NitroxModel.DataStructures;
using NitroxModel.Helper;
using NitroxModel.Packets;

Expand All @@ -17,18 +14,10 @@ public sealed partial class RangedAttackLastTarget_StartCasting_Patch : NitroxPa

public static void Prefix(RangedAttackLastTarget __instance)
{
if (!Resolve<AI>().IsCreatureWhitelisted(__instance.creature) ||
!__instance.TryGetNitroxId(out NitroxId creatureId) ||
!Resolve<SimulationOwnership>().HasAnyLockType(creatureId) ||
!__instance.currentTarget || !__instance.currentTarget.TryGetNitroxId(out NitroxId targetId))
if (RangedAttackLastTarget_StartCharging_Patch.BroadcastRangedAttack(__instance, RangedAttackLastTargetUpdate.ActionState.CASTING))
{
return;
ErrorMessage.AddMessage($"[SEND] {__instance.name} casts against {__instance.currentTarget.name}");
}

int attackTypeIndex = __instance.attackTypes.GetIndex(__instance.currentAttack);

Resolve<IPacketSender>().Send(new RangedAttackLastTargetUpdate(creatureId, targetId, attackTypeIndex, RangedAttackLastTargetUpdate.ActionState.CASTING));
ErrorMessage.AddMessage($"[SEND] {__instance.name} casts against {__instance.currentTarget.name}");
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
namespace NitroxPatcher.Patches.Dynamic;

/// <summary>
/// Prevents non simulating players from running locally <see cref="RangedAttackLastTarget.StartCasting"/>.
/// Prevents non simulating players from running locally <see cref="RangedAttackLastTarget.StartCharging"/>.
/// Broadcasts this event on the simulating player.
/// </summary>
public sealed partial class RangedAttackLastTarget_StartCharging_Patch : NitroxPatch, IDynamicPatch
Expand All @@ -17,18 +17,42 @@ public sealed partial class RangedAttackLastTarget_StartCharging_Patch : NitroxP

public static void Prefix(RangedAttackLastTarget __instance)
{
if (!Resolve<AI>().IsCreatureWhitelisted(__instance.creature) ||
!__instance.TryGetNitroxId(out NitroxId creatureId) ||
!Resolve<SimulationOwnership>().HasAnyLockType(creatureId) ||
!__instance.currentTarget || !__instance.currentTarget.TryGetNitroxId(out NitroxId targetId))
if (BroadcastRangedAttack(__instance, RangedAttackLastTargetUpdate.ActionState.CHARGING))
{
return;
ErrorMessage.AddMessage($"[SEND] {__instance.name} charges against {__instance.currentTarget.name}");
}
}

/// <summary>
/// Broadcasts a range attack CHARGING or CASTING state if the attacking creature is whitelisted, valid and if the target is valid.
/// </summary>
/// <returns>
/// true if the broadcast was done (all conditions met)
/// </returns>
internal static bool BroadcastRangedAttack(RangedAttackLastTarget attackBehaviour, RangedAttackLastTargetUpdate.ActionState actionState)
{
// should action be broadcasted
if (!Resolve<AI>().IsCreatureWhitelisted(attackBehaviour.creature))
{
return false;
}

// Attacker object validity
if (!attackBehaviour.TryGetNitroxId(out NitroxId creatureId) || !Resolve<SimulationOwnership>().HasAnyLockType(creatureId))
{
return false;
}

// Target validity
if (!attackBehaviour.currentTarget || !attackBehaviour.currentTarget.TryGetNitroxId(out NitroxId targetId))
{
return false;
}

int attackTypeIndex = __instance.attackTypes.GetIndex(__instance.currentAttack);
int attackTypeIndex = attackBehaviour.attackTypes.GetIndex(attackBehaviour.currentAttack);

Resolve<IPacketSender>().Send(new RangedAttackLastTargetUpdate(creatureId, targetId, attackTypeIndex, RangedAttackLastTargetUpdate.ActionState.CHARGING));
ErrorMessage.AddMessage($"[SEND] {__instance.name} charges against {__instance.currentTarget.name}");
Resolve<IPacketSender>().Send(new RangedAttackLastTargetUpdate(creatureId, targetId, attackTypeIndex, actionState));
return true;
}
}

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System.Reflection;
using NitroxClient.MonoBehaviours;
using NitroxClient.MonoBehaviours.Vehicles;
using NitroxModel.Helper;

namespace NitroxPatcher.Patches.Dynamic;
Expand All @@ -13,9 +13,9 @@ public sealed partial class ReaperLeviathan_GrabVehicle_Patch : NitroxPatch, IDy

public static void Prefix(Vehicle vehicle)
{
if (vehicle.TryGetComponent(out RemotelyControlled remotelyControlled))
if (vehicle.TryGetComponent(out VehicleMovementReplicator vehicleMovementReplicator))
{
remotelyControlled.enabled = false;
vehicleMovementReplicator.enabled = false;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System.Reflection;
using NitroxClient.MonoBehaviours;
using NitroxClient.MonoBehaviours.Vehicles;
using NitroxModel.Helper;

namespace NitroxPatcher.Patches.Dynamic;
Expand All @@ -13,10 +13,9 @@ public sealed partial class ReaperLeviathan_ReleaseVehicle_Patch : NitroxPatch,

public static void Prefix(ReaperLeviathan __instance)
{
if (__instance.holdingVehicle &&
__instance.holdingVehicle.TryGetComponent(out RemotelyControlled remotelyControlled))
if (__instance.holdingVehicle && __instance.holdingVehicle.TryGetComponent(out VehicleMovementReplicator vehicleMovementReplicator))
{
remotelyControlled.enabled = true;
vehicleMovementReplicator.enabled = true;
}
}
}
12 changes: 7 additions & 5 deletions NitroxPatcher/Patches/Dynamic/SeaDragon_GrabExosuit_Patch.cs
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
using System.Reflection;
using NitroxClient.Communication.Abstract;
using NitroxClient.MonoBehaviours;
using NitroxClient.GameLogic;
using NitroxClient.MonoBehaviours.Vehicles;
using NitroxModel.DataStructures;
using NitroxModel.Helper;
using NitroxModel.Packets;

namespace NitroxPatcher.Patches.Dynamic;

/// <summary>
/// Broadcasts the exosuit grab by Sea Dragons and temporarily disables exosuit's position sync while they're grabbed.
/// Broadcasts the exosuit grab by Sea Dragons (if local player has remote control of them) and temporarily disables exosuit's position sync while they're grabbed.
/// </summary>
public sealed partial class SeaDragon_GrabExosuit_Patch : NitroxPatch, IDynamicPatch
{
public static readonly MethodInfo TARGET_METHOD = Reflect.Method((SeaDragon t) => t.GrabExosuit(default));

public static void Prefix(SeaDragon __instance, Exosuit exosuit)
{
if (exosuit.TryGetComponent(out RemotelyControlled remotelyControlled))
if (exosuit.TryGetComponent(out VehicleMovementReplicator vehicleMovementReplicator))
{
remotelyControlled.enabled = false;
vehicleMovementReplicator.enabled = false;
}

if (__instance.TryGetNitroxId(out NitroxId seaDragonId) && exosuit.TryGetNitroxId(out NitroxId targetId))
if (__instance.TryGetNitroxId(out NitroxId seaDragonId) && Resolve<SimulationOwnership>().HasAnyLockType(seaDragonId) &&
exosuit.TryGetNitroxId(out NitroxId targetId))
{
Resolve<IPacketSender>().Send(new SeaDragonGrabExosuit(seaDragonId, targetId));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
using System.Reflection;
using NitroxClient.MonoBehaviours;
using NitroxClient.MonoBehaviours.Vehicles;
using NitroxModel.Helper;

namespace NitroxPatcher.Patches.Dynamic;

/// <summary>
/// Enables exosuits's position sync when they're released from sea dragons
/// </summary>
public sealed partial class SeaDrargon_ReleaseExosuit_Patch : NitroxPatch, IDynamicPatch
public sealed partial class SeaDragon_ReleaseExosuit_Patch : NitroxPatch, IDynamicPatch
{
public static readonly MethodInfo TARGET_METHOD = Reflect.Method((SeaDragon t) => t.ReleaseExosuit());

public static void Prefix(SeaDragon __instance)
{
if (__instance.holdingExosuit &&
__instance.holdingExosuit.TryGetComponent(out RemotelyControlled remotelyControlled))
if (__instance.holdingExosuit && __instance.holdingExosuit.TryGetComponent(out VehicleMovementReplicator vehicleMovementReplicator))
{
remotelyControlled.enabled = true;
vehicleMovementReplicator.enabled = true;
}
}
}
9 changes: 7 additions & 2 deletions NitroxPatcher/Patches/Dynamic/StasisSphere_OnHit_Patch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,18 @@ public static bool Prefix(StasisSphere __instance)
return false;
}

ushort localPlayerId = Resolve<LocalPlayer>().PlayerId;
ushort? localPlayerId = Resolve<LocalPlayer>().PlayerId;
// If the lcoal player id isn't set then there's already a bigger problem/no problem and we can ignore that
if (!localPlayerId.HasValue)
{
return true;
}
NitroxVector3 position = __instance.tr.position.ToDto();
NitroxQuaternion rotation = __instance.tr.rotation.ToDto();
// Calculate the chargeNormalized value which was passed to StasisSphere.Shoot
float chargeNormalized = Mathf.Unlerp(__instance.minRadius, __instance.maxRadius, __instance.radius);

Resolve<IPacketSender>().Send(new StasisSphereHit(localPlayerId, position, rotation, chargeNormalized, __instance._consumption));
Resolve<IPacketSender>().Send(new StasisSphereHit(localPlayerId.Value, position, rotation, chargeNormalized, __instance._consumption));
return true;
}
}
6 changes: 3 additions & 3 deletions NitroxPatcher/Patches/Dynamic/StasisSphere_Shoot_Patch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ public sealed partial class StasisSphere_Shoot_Patch : NitroxPatch, IDynamicPatc
{
private static readonly MethodInfo TARGET_METHOD = Reflect.Method((StasisSphere t) => t.Shoot(default, default, default, default, default));

private static ushort LocalPlayerId => Resolve<LocalPlayer>().PlayerId;
private static ushort? LocalPlayerId => Resolve<LocalPlayer>().PlayerId;

public static void Prefix(StasisSphere __instance, Vector3 position, Quaternion rotation, float speed, float lifeTime, float chargeNormalized)
{
if (__instance.GetComponent<BulletManager.RemotePlayerBullet>())
if (__instance.GetComponent<BulletManager.RemotePlayerBullet>() || !LocalPlayerId.HasValue)
{
return;
}

Resolve<IPacketSender>().Send(new StasisSphereShot(LocalPlayerId, position.ToDto(), rotation.ToDto(), speed, lifeTime, chargeNormalized));
Resolve<IPacketSender>().Send(new StasisSphereShot(LocalPlayerId.Value, position.ToDto(), rotation.ToDto(), speed, lifeTime, chargeNormalized));
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using NitroxModel.DataStructures;
using NitroxModel.DataStructures.GameLogic;
using NitroxModel.Packets;
Expand Down Expand Up @@ -36,21 +37,10 @@ public void TransmitIfCanSeeEntities(Packet packet, Player senderPlayer, List<Ni
return;
}
}
bool canPlayerSeeAllEntities(Player player)
{
foreach (Entity entity in entities)
{
if (!player.CanSee(entity))
{
return false;
}
}
return true;
}

foreach (Player player in playerManager.GetConnectedPlayersExcept(senderPlayer))
{
if (canPlayerSeeAllEntities(player))
if (entities.All(player.CanSee))
{
player.SendPacket(packet);
}
Expand Down
Loading

0 comments on commit 93619cb

Please sign in to comment.