-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Sync stasis rifles and torpedos (precise and desync-proof). Fix seamo…
…th inventory not storing torpedos
- Loading branch information
1 parent
905edef
commit 3762c2c
Showing
38 changed files
with
791 additions
and
212 deletions.
There are no files selected for viewing
22 changes: 22 additions & 0 deletions
22
Nitrox.Test/Patcher/Patches/Dynamic/Bullet_Update_PatchTest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Reflection.Emit; | ||
using FluentAssertions; | ||
using HarmonyLib; | ||
using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
using NitroxTest.Patcher; | ||
|
||
namespace NitroxPatcher.Patches.Dynamic; | ||
|
||
[TestClass] | ||
public class Bullet_Update_PatchTest | ||
{ | ||
[TestMethod] | ||
public void Sanity() | ||
{ | ||
ILGenerator generator = Bullet_Update_Patch.TARGET_METHOD.GetILGenerator(); | ||
IEnumerable<CodeInstruction> originalIl = PatchTestHelper.GetInstructionsFromMethod(Bullet_Update_Patch.TARGET_METHOD); | ||
IEnumerable<CodeInstruction> transformedIl = Bullet_Update_Patch.Transpiler(originalIl, generator); | ||
transformedIl.Count().Should().Be(originalIl.Count() + 3); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
NitroxClient/Communication/Packets/Processors/StasisSphereHitProcessor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
using NitroxClient.Communication.Packets.Processors.Abstract; | ||
using NitroxClient.GameLogic; | ||
using NitroxModel.Packets; | ||
using NitroxModel_Subnautica.DataStructures; | ||
|
||
namespace NitroxClient.Communication.Packets.Processors; | ||
|
||
public class StasisSphereHitProcessor : ClientPacketProcessor<StasisSphereHit> | ||
{ | ||
private readonly BulletManager bulletManager; | ||
|
||
public StasisSphereHitProcessor(BulletManager bulletManager) | ||
{ | ||
this.bulletManager = bulletManager; | ||
} | ||
|
||
public override void Process(StasisSphereHit packet) | ||
{ | ||
bulletManager.StasisSphereHit(packet.PlayerId, packet.Position.ToUnity(), packet.Rotation.ToUnity(), packet.ChargeNormalized, packet.Consumption); | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
NitroxClient/Communication/Packets/Processors/StasisSphereShotProcessor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
using NitroxClient.Communication.Packets.Processors.Abstract; | ||
using NitroxClient.GameLogic; | ||
using NitroxModel.Packets; | ||
using NitroxModel_Subnautica.DataStructures; | ||
|
||
namespace NitroxClient.Communication.Packets.Processors; | ||
|
||
public class StasisSphereShotProcessor : ClientPacketProcessor<StasisSphereShot> | ||
{ | ||
private readonly BulletManager bulletManager; | ||
|
||
public StasisSphereShotProcessor(BulletManager bulletManager) | ||
{ | ||
this.bulletManager = bulletManager; | ||
} | ||
|
||
public override void Process(StasisSphereShot packet) | ||
{ | ||
bulletManager.ShootStasisSphere(packet.PlayerId, packet.Position.ToUnity(), packet.Rotation.ToUnity(), packet.Speed, packet.LifeTime, packet.ChargeNormalized); | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
NitroxClient/Communication/Packets/Processors/TorpedoHitProcessor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
using NitroxClient.Communication.Packets.Processors.Abstract; | ||
using NitroxClient.GameLogic; | ||
using NitroxModel.Packets; | ||
using NitroxModel_Subnautica.DataStructures; | ||
|
||
namespace NitroxClient.Communication.Packets.Processors; | ||
|
||
public class TorpedoHitProcessor : ClientPacketProcessor<TorpedoHit> | ||
{ | ||
private readonly BulletManager bulletManager; | ||
|
||
public TorpedoHitProcessor(BulletManager bulletManager) | ||
{ | ||
this.bulletManager = bulletManager; | ||
} | ||
|
||
public override void Process(TorpedoHit packet) | ||
{ | ||
bulletManager.TorpedoHit(packet.BulletId, packet.Position.ToUnity(), packet.Rotation.ToUnity()); | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
NitroxClient/Communication/Packets/Processors/TorpedoShotProcessor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
using NitroxClient.Communication.Packets.Processors.Abstract; | ||
using NitroxClient.GameLogic; | ||
using NitroxModel.Packets; | ||
using NitroxModel_Subnautica.DataStructures; | ||
|
||
namespace NitroxClient.Communication.Packets.Processors; | ||
|
||
public class TorpedoShotProcessor : ClientPacketProcessor<TorpedoShot> | ||
{ | ||
private readonly BulletManager bulletManager; | ||
|
||
public TorpedoShotProcessor(BulletManager bulletManager) | ||
{ | ||
this.bulletManager = bulletManager; | ||
} | ||
|
||
public override void Process(TorpedoShot packet) | ||
{ | ||
bulletManager.ShootSeamothTorpedo(packet.BulletId, packet.TechType.ToUnity(), packet.Position.ToUnity(), packet.Rotation.ToUnity(), packet.Speed, packet.LifeTime); | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
NitroxClient/Communication/Packets/Processors/TorpedoTargetAcquiredProcessor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
using NitroxClient.Communication.Packets.Processors.Abstract; | ||
using NitroxClient.GameLogic; | ||
using NitroxModel.Packets; | ||
using NitroxModel_Subnautica.DataStructures; | ||
|
||
namespace NitroxClient.Communication.Packets.Processors; | ||
|
||
public class TorpedoTargetAcquiredProcessor : ClientPacketProcessor<TorpedoTargetAcquired> | ||
{ | ||
private readonly BulletManager bulletManager; | ||
|
||
public TorpedoTargetAcquiredProcessor(BulletManager bulletManager) | ||
{ | ||
this.bulletManager = bulletManager; | ||
} | ||
|
||
public override void Process(TorpedoTargetAcquired packet) | ||
{ | ||
bulletManager.TorpedoTargetAcquired(packet.BulletId, packet.TargetId, packet.Position.ToUnity(), packet.Rotation.ToUnity()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using NitroxClient.GameLogic.Spawning.WorldEntities; | ||
using NitroxClient.MonoBehaviours; | ||
using NitroxClient.Unity.Helper; | ||
using NitroxModel.DataStructures; | ||
using UnityEngine; | ||
|
||
namespace NitroxClient.GameLogic; | ||
|
||
public class BulletManager | ||
{ | ||
private readonly PlayerManager playerManager; | ||
|
||
// This only allows for one stasis sphere per player | ||
// (which is the normal capacity, but could be adapted for a mod letting multiple stasis spheres) | ||
private readonly Dictionary<ushort, StasisSphere> stasisSpherePerPlayerId = []; | ||
|
||
/// <summary> | ||
/// TechTypes of objects which should have a Vehicle MB | ||
/// </summary> | ||
public static readonly HashSet<TechType> PreloadedVehicleTypes = [ | ||
TechType.Seamoth, TechType.Exosuit | ||
]; | ||
|
||
private readonly Dictionary<TechType, GameObject> torpedoPrefabByTechType = []; | ||
|
||
private GameObject stasisSpherePrefab { get; set; } | ||
|
||
public BulletManager(PlayerManager playerManager) | ||
{ | ||
this.playerManager = playerManager; | ||
} | ||
|
||
public void ShootSeamothTorpedo(NitroxId bulletId, TechType techType, Vector3 position, Quaternion rotation, float speed, float lifeTime) | ||
{ | ||
if (!torpedoPrefabByTechType.TryGetValue(techType, out GameObject prefab)) | ||
{ | ||
Log.ErrorOnce($"[{nameof(BulletManager)}] Received ShootSeamothTorpedo request with TechType: {techType} but no prefab was loaded for it"); | ||
return; | ||
} | ||
|
||
GameObject torpedoClone = GameObjectHelper.SpawnFromPrefab(prefab, bulletId); | ||
// We mark it to be able to ignore events from remote bullets | ||
torpedoClone.AddComponent<RemotePlayerBullet>(); | ||
|
||
// We cast it to Bullet to ensure we're calling the same method as in Vehicle.TorpedoShot | ||
Bullet seamothTorpedo = torpedoClone.GetComponent<SeamothTorpedo>(); | ||
seamothTorpedo.Shoot(position, rotation, speed, lifeTime); | ||
} | ||
|
||
public void TorpedoHit(NitroxId bulletId, Vector3 position, Quaternion rotation) | ||
{ | ||
if (NitroxEntity.TryGetComponentFrom(bulletId, out SeamothTorpedo torpedo)) | ||
{ | ||
torpedo.tr.position = position; | ||
torpedo.tr.rotation = rotation; | ||
torpedo.OnHit(default); | ||
torpedo.Deactivate(); | ||
} | ||
} | ||
|
||
public void TorpedoTargetAcquired(NitroxId bulletId, NitroxId targetId, Vector3 position, Quaternion rotation) | ||
{ | ||
// The target object might not be findable in which case we'll just ignore it | ||
// because the explosion will still be moved to the right spot | ||
if (NitroxEntity.TryGetComponentFrom(bulletId, out SeamothTorpedo torpedo) && | ||
NitroxEntity.TryGetObjectFrom(targetId, out GameObject targetObject)) | ||
{ | ||
torpedo.tr.position = position; | ||
torpedo.tr.rotation = rotation; | ||
// Stuff from SeamothTorpedo.RepeatingTargeting | ||
torpedo.homingTarget = targetObject; | ||
torpedo.CancelInvoke(); | ||
} | ||
} | ||
|
||
public void ShootStasisSphere(ushort playerId, Vector3 position, Quaternion rotation, float speed, float lifeTime, float chargeNormalized) | ||
{ | ||
if (!stasisSpherePerPlayerId.TryGetValue(playerId, out StasisSphere cloneSphere) || !cloneSphere) | ||
{ | ||
cloneSphere = EnsurePlayerHasSphere(playerId); | ||
} | ||
|
||
cloneSphere.Shoot(position, rotation, speed, lifeTime, chargeNormalized); | ||
} | ||
|
||
public void StasisSphereHit(ushort playerId, Vector3 position, Quaternion rotation, float chargeNormalized, float consumption) | ||
{ | ||
StasisSphere cloneSphere = EnsurePlayerHasSphere(playerId); | ||
|
||
// Setup the sphere in case it the shot was sent earlier | ||
cloneSphere.Shoot(position, rotation, 0, 0, chargeNormalized); | ||
// We override this field (set by .Shoot) with the right data | ||
cloneSphere._consumption = consumption; | ||
|
||
// Code from Bullet.Update when finding an object to hit | ||
cloneSphere._visible = true; | ||
cloneSphere.OnMadeVisible(); | ||
cloneSphere.OnHit(default); | ||
cloneSphere.Deactivate(); | ||
} | ||
|
||
private StasisSphere EnsurePlayerHasSphere(ushort playerId) | ||
{ | ||
if (stasisSpherePerPlayerId.TryGetValue(playerId, out StasisSphere remoteSphere) && remoteSphere) | ||
{ | ||
return remoteSphere; | ||
} | ||
|
||
// It should be set to inactive automatically in Bullet.Awake | ||
GameObject playerSphereClone = GameObject.Instantiate(stasisSpherePrefab); | ||
// We mark it to be able to ignore events from remote bullets | ||
playerSphereClone.AddComponent<RemotePlayerBullet>(); | ||
StasisSphere stasisSphere = playerSphereClone.GetComponent<StasisSphere>(); | ||
|
||
stasisSpherePerPlayerId[playerId] = stasisSphere; | ||
return stasisSphere; | ||
} | ||
|
||
private void DestroyPlayerSphere(ushort playerId) | ||
{ | ||
if (stasisSpherePerPlayerId.TryGetValue(playerId, out StasisSphere stasisSphere) && stasisSphere) | ||
{ | ||
GameObject.Destroy(stasisSphere.gameObject); | ||
} | ||
stasisSpherePerPlayerId.Remove(playerId); | ||
} | ||
|
||
public IEnumerator Initialize() | ||
{ | ||
TaskResult<GameObject> result = new(); | ||
|
||
// Load torpedo types prefab and store them by tech type | ||
foreach (TechType techType in PreloadedVehicleTypes) | ||
{ | ||
yield return DefaultWorldEntitySpawner.RequestPrefab(techType, result); | ||
if (result.value && result.value.TryGetComponent(out Vehicle vehicle) && vehicle.torpedoTypes != null) | ||
{ | ||
foreach (TorpedoType torpedoType in vehicle.torpedoTypes) | ||
{ | ||
torpedoPrefabByTechType[torpedoType.techType] = torpedoType.prefab; | ||
} | ||
} | ||
} | ||
|
||
// Load the stasis sphere prefab | ||
yield return DefaultWorldEntitySpawner.RequestPrefab(TechType.StasisRifle, result); | ||
StasisRifle rifle = result.value.GetComponent<StasisRifle>(); | ||
if (rifle) | ||
{ | ||
stasisSpherePrefab = rifle.effectSpherePrefab; | ||
} | ||
|
||
// Setup remote players' stasis spheres | ||
foreach (RemotePlayer remotePlayer in playerManager.GetAll()) | ||
{ | ||
EnsurePlayerHasSphere(remotePlayer.PlayerId); | ||
} | ||
|
||
playerManager.onCreate += (playerId, _) => { EnsurePlayerHasSphere(playerId); }; | ||
playerManager.onRemove += (playerId, _) => { DestroyPlayerSphere(playerId); }; | ||
} | ||
|
||
public class RemotePlayerBullet : MonoBehaviour { } | ||
} |
Oops, something went wrong.