Skip to content

Commit

Permalink
Sync leviathans (beginning)
Browse files Browse the repository at this point in the history
  • Loading branch information
tornac1234 committed Jan 10, 2024
1 parent 8abb67b commit 905edef
Show file tree
Hide file tree
Showing 30 changed files with 717 additions and 107 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using HarmonyLib;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NitroxTest.Patcher;

namespace NitroxPatcher.Patches.Dynamic;

[TestClass]
public class AggressiveWhenSeeTarget_ScanForAggressionTarget_PatchTest
{
[TestMethod]
public void Sanity()
{
IEnumerable<CodeInstruction> originalIl = PatchTestHelper.GetInstructionsFromMethod(AggressiveWhenSeeTarget_ScanForAggressionTarget_Patch.TARGET_METHOD);
IEnumerable<CodeInstruction> transformedIl = AggressiveWhenSeeTarget_ScanForAggressionTarget_Patch.Transpiler(originalIl);
transformedIl.Count().Should().Be(originalIl.Count() + 3);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using HarmonyLib;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NitroxTest.Patcher;

namespace NitroxPatcher.Patches.Dynamic;

[TestClass]
public class AttackCyclops_OnCollisionEnter_PatchTest
{
[TestMethod]
public void Sanity()
{
IEnumerable<CodeInstruction> originalIl = PatchTestHelper.GetInstructionsFromMethod(AttackCyclops_OnCollisionEnter_Patch.TARGET_METHOD);
IEnumerable<CodeInstruction> transformedIl = AttackCyclops_OnCollisionEnter_Patch.Transpiler(originalIl);
transformedIl.Count().Should().Be(originalIl.Count() - 17);

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using HarmonyLib;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NitroxTest.Patcher;

namespace NitroxPatcher.Patches.Dynamic;

[TestClass]
public class AttackCyclops_UpdateAggression_PatchTest
{
[TestMethod]
public void Sanity()
{
IEnumerable<CodeInstruction> originalIl = PatchTestHelper.GetInstructionsFromMethod(AttackCyclops_UpdateAggression_Patch.TARGET_METHOD);
IEnumerable<CodeInstruction> transformedIl = AttackCyclops_UpdateAggression_Patch.Transpiler(originalIl);
transformedIl.Count().Should().Be(originalIl.Count() - 23);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using NitroxClient.Communication.Packets.Processors.Abstract;
using NitroxClient.GameLogic;
using NitroxModel.Packets;

namespace NitroxClient.Communication.Packets.Processors;

public class AggressiveWhenSeeTargetChangedProcessor : ClientPacketProcessor<AggressiveWhenSeeTargetChanged>
{
public override void Process(AggressiveWhenSeeTargetChanged packet)
{
AI.AggressiveWhenSeeTargetChanged(packet.CreatureId, packet.TargetId, packet.Locked, packet.AggressionAmount);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using NitroxClient.Communication.Packets.Processors.Abstract;
using NitroxClient.GameLogic;
using NitroxModel.Packets;

namespace NitroxClient.Communication.Packets.Processors;

public class AttackCyclopsTargetChangedProcessor : ClientPacketProcessor<AttackCyclopsTargetChanged>
{
public override void Process(AttackCyclopsTargetChanged packet)
{
AI.AttackCyclopsTargetChanged(packet.CreatureId, packet.TargetId, packet.AggressiveToNoiseAmount);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using NitroxClient.Communication.Packets.Processors.Abstract;
using NitroxClient.GameLogic;
using NitroxModel.Packets;

namespace NitroxClient.Communication.Packets.Processors;

public class CreatureActionProcessor : ClientPacketProcessor<CreatureActionChanged>
{
private readonly AI ai;

public CreatureActionProcessor(AI ai)
{
this.ai = ai;
}

public override void Process(CreatureActionChanged packet)
{
ai.CreatureActionChanged(packet.CreatureId, packet.CreatureActionType);
}
}
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
using NitroxClient.Communication.Packets.Processors.Abstract;
using NitroxClient.GameLogic.HUD;
using NitroxClient.GameLogic;
using NitroxClient.MonoBehaviours.Gui.HUD;
using NitroxModel.Packets;

namespace NitroxClient.Communication.Packets.Processors;

public class PlayerStatsProcessor : ClientPacketProcessor<PlayerStats>
{
private readonly PlayerVitalsManager vitalsManager;
private readonly PlayerManager playerManager;

public PlayerStatsProcessor(PlayerVitalsManager vitalsManager)
public PlayerStatsProcessor(PlayerManager playerManager)
{
this.vitalsManager = vitalsManager;
this.playerManager = playerManager;
}

public override void Process(PlayerStats playerStats)
{
if (vitalsManager.TryFindForPlayer(playerStats.PlayerId, out RemotePlayerVitals vitals))
if (playerManager.TryFind(playerStats.PlayerId, out RemotePlayer remotePlayer))
{
RemotePlayerVitals vitals = remotePlayer.vitals;
vitals.SetOxygen(playerStats.Oxygen, playerStats.MaxOxygen);
vitals.SetHealth(playerStats.Health);
vitals.SetFood(playerStats.Food);
vitals.SetWater(playerStats.Water);
remotePlayer.UpdateHealthAndInfection(playerStats.Health, playerStats.InfectionAmount);
}
}
}
128 changes: 107 additions & 21 deletions NitroxClient/GameLogic/AI.cs
Original file line number Diff line number Diff line change
@@ -1,36 +1,122 @@
using NitroxClient.Communication.Abstract;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using NitroxClient.Communication.Abstract;
using NitroxClient.MonoBehaviours;
using NitroxModel.DataStructures;
using NitroxModel_Subnautica.DataStructures.GameLogic.Creatures.Actions;
using NitroxModel_Subnautica.Packets;
using NitroxModel.Packets;
using UnityEngine;

namespace NitroxClient.GameLogic
namespace NitroxClient.GameLogic;

public class AI
{
public class AI
private readonly IPacketSender packetSender;
private readonly Dictionary<Creature, CreatureAction> actions = [];
private readonly Dictionary<string, Type> cachedCreatureActionTypeByFullName;

/// <summary>
/// Contains the types derived from CreatureAction which should be synced.
/// Actions concerning the creature movement should be ignored as it's already done through SplineFollowing
/// </summary>
private readonly HashSet<Type> creatureActionWhitelist =
[
typeof(AttackLastTarget), typeof(AttackCyclops)
];

public AI(IPacketSender packetSender)
{
private readonly IPacketSender packetSender;
this.packetSender = packetSender;
Assembly assembly = Assembly.GetAssembly(typeof(CreatureAction));
cachedCreatureActionTypeByFullName = assembly.GetTypes()
.Where(type => typeof(CreatureAction).IsAssignableFrom(type))
.ToDictionary(t => t.FullName, t => t);
}

public AI(IPacketSender packetSender)
public void BroadcastNewAction(NitroxId creatureId, Creature creature, CreatureAction newAction)
{
if (creature is not ReaperLeviathan)
{
this.packetSender = packetSender;
return;
}

public void CreatureActionChanged(NitroxId id, CreatureAction newAction)
ErrorMessage.AddMessage($"[SEND] reaper action: {newAction.GetType().FullName}");
packetSender.Send(new CreatureActionChanged(creatureId, newAction.GetType().FullName));
}

public void CreatureActionChanged(NitroxId id, string creatureActionTypeName)
{
if (!NitroxEntity.TryGetComponentFrom(id, out Creature creature))
{
return;
}
if (cachedCreatureActionTypeByFullName.TryGetValue(creatureActionTypeName, out Type creatureActionType))
{
SerializableCreatureAction creatureAction = null;
ErrorMessage.AddMessage($"[GET] {creatureActionType}");
if (creature.TryGetComponent(creatureActionType, out Component component) && component is CreatureAction creatureAction)
{
actions[creature] = creatureAction;
}
}
}

/*
Example for next implementation:
public static void AggressiveWhenSeeTargetChanged(NitroxId creatureId, NitroxId targetId, bool locked, float aggressionAmount)
{
if (!NitroxEntity.TryGetComponentFrom(creatureId, out AggressiveWhenSeeTarget aggressiveWhenSeeTarget) ||
!NitroxEntity.TryGetObjectFrom(targetId, out GameObject targetObject))
{
return;
}

if (newAction.GetType() == typeof(SwimToPoint))
{
creatureAction = new SwimToPointAction(((SwimToPoint)newAction).Target);
}*/
ErrorMessage.AddMessage($"[GET] {aggressiveWhenSeeTarget.gameObject.name} chases {targetObject.name}");

if (creatureAction != null)
{
CreatureActionChanged actionChanged = new CreatureActionChanged(id, creatureAction);
packetSender.Send(actionChanged);
}
Creature creature = aggressiveWhenSeeTarget.creature;

// Code from AggressiveWhenSeeTarget.ScanForAggressionTarget
creature.Aggression.Value = aggressionAmount;
LastTarget lastTarget = aggressiveWhenSeeTarget.lastTarget;
lastTarget.SetTargetInternal(targetObject);
lastTarget.targetLocked = locked;

if (aggressiveWhenSeeTarget.sightedSound != null && !aggressiveWhenSeeTarget.sightedSound.GetIsPlaying())
{
// TODO: Adapt this code when #1780 is merged
aggressiveWhenSeeTarget.sightedSound.StartEvent();
}

if (creature.TryGetComponent(out AttackLastTarget attackLastTarget))
{
attackLastTarget.currentTarget = targetObject;
}
}

public static void AttackCyclopsTargetChanged(NitroxId creatureId, NitroxId targetId, float aggressiveToNoiseAmount)
{
if (!NitroxEntity.TryGetComponentFrom(creatureId, out AttackCyclops attackCyclops) ||
!NitroxEntity.TryGetObjectFrom(targetId, out GameObject targetObject))
{
return;
}

ErrorMessage.AddMessage($"[GET] {attackCyclops.gameObject.name} attacks {targetObject.name}");

// Kinda stuff from AttackCyclops.UpdateAggression
attackCyclops.aggressiveToNoise.Value = aggressiveToNoiseAmount;
// Force currentTarget to null to ensure SetCurrentTarget detects a change
attackCyclops.currentTarget = null;
attackCyclops.SetCurrentTarget(targetObject, targetObject.GetComponent<CyclopsDecoy>());
}

public bool TryGetActionForCreature(Creature creature, out CreatureAction action)
{
// TODO: Fix ondeath cinematic being played for all players when getting bitten by a reaper
// TODO: When #2043 is merged, blacklist the cinematic
return actions.TryGetValue(creature, out action);
}

public bool IsCreatureActionWhitelisted(CreatureAction creatureAction)
{
return creatureActionWhitelist.Contains(creatureAction.GetType());
}
}
Loading

0 comments on commit 905edef

Please sign in to comment.