Skip to content

Commit

Permalink
Refactor and fix EscapePodMetadata handling
Browse files Browse the repository at this point in the history
  • Loading branch information
Jannify committed Jan 13, 2025
1 parent b27021f commit d076af6
Show file tree
Hide file tree
Showing 13 changed files with 249 additions and 189 deletions.
18 changes: 9 additions & 9 deletions Nitrox.Test/Server/Serialization/WorldPersistenceTest.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using Nitrox.Test;
using Nitrox.Test.Helper.Faker;
using NitroxModel.Core;
using NitroxModel.DataStructures;
using NitroxModel.DataStructures.GameLogic;
using NitroxModel.DataStructures.GameLogic.Entities;
using NitroxModel.DataStructures.GameLogic.Entities.Bases;
Expand Down Expand Up @@ -199,8 +198,9 @@ private static void EntityTest(Entity entity, Entity entityAfter)
case BatteryMetadata metadata when entityAfter.Metadata is BatteryMetadata metadataAfter:
Assert.AreEqual(metadata.Charge, metadataAfter.Charge);
break;
case RepairedComponentMetadata metadata when entityAfter.Metadata is RepairedComponentMetadata metadataAfter:
Assert.AreEqual(metadata.TechType, metadataAfter.TechType);
case EscapePodMetadata metadata when entityAfter.Metadata is EscapePodMetadata metadataAfter:
Assert.AreEqual(metadata.PodRepaired, metadataAfter.PodRepaired);
Assert.AreEqual(metadata.RadioRepaired, metadataAfter.RadioRepaired);
break;
case CrafterMetadata metadata when entityAfter.Metadata is CrafterMetadata metadataAfter:
Assert.AreEqual(metadata.TechType, metadataAfter.TechType);
Expand Down Expand Up @@ -337,9 +337,9 @@ private static void EntityTest(Entity entity, Entity entityAfter)
case PlaceholderGroupWorldEntity placeholderGroupWorldEntity when worldEntityAfter is PlaceholderGroupWorldEntity placeholderGroupWorldEntityAfter:
Assert.AreEqual(placeholderGroupWorldEntity.ComponentIndex, placeholderGroupWorldEntityAfter.ComponentIndex);
break;
case CellRootEntity _ when worldEntityAfter is CellRootEntity _:
case CellRootEntity when worldEntityAfter is CellRootEntity:
break;
case PlacedWorldEntity _ when worldEntityAfter is PlacedWorldEntity _:
case PlacedWorldEntity when worldEntityAfter is PlacedWorldEntity:
break;
case OxygenPipeEntity oxygenPipeEntity when worldEntityAfter is OxygenPipeEntity oxygenPipeEntityAfter:
Assert.AreEqual(oxygenPipeEntity.ParentPipeId, oxygenPipeEntityAfter.ParentPipeId);
Expand All @@ -351,7 +351,7 @@ private static void EntityTest(Entity entity, Entity entityAfter)
break;
case SerializedWorldEntity serializedWorldEntity when entityAfter is SerializedWorldEntity serializedWorldEntityAfter:
Assert.AreEqual(serializedWorldEntity.AbsoluteEntityCell, serializedWorldEntityAfter.AbsoluteEntityCell);
AssertHelper.IsListEqual(serializedWorldEntity.Components.OrderBy(c => c.GetHashCode()), serializedWorldEntityAfter.Components.OrderBy(c => c.GetHashCode()), (SerializedComponent c1, SerializedComponent c2) => c1.Equals(c2));
AssertHelper.IsListEqual(serializedWorldEntity.Components.OrderBy(c => c.GetHashCode()), serializedWorldEntityAfter.Components.OrderBy(c => c.GetHashCode()), (c1, c2) => c1.Equals(c2));
Assert.AreEqual(serializedWorldEntity.Layer, serializedWorldEntityAfter.Layer);
Assert.AreEqual(serializedWorldEntity.BatchId, serializedWorldEntityAfter.BatchId);
Assert.AreEqual(serializedWorldEntity.CellId, serializedWorldEntityAfter.CellId);
Expand Down Expand Up @@ -410,9 +410,9 @@ private static void EntityTest(Entity entity, Entity entityAfter)
case MoonpoolEntity moonpoolEntity when globalRootEntityAfter is MoonpoolEntity moonpoolEntityAfter:
Assert.AreEqual(moonpoolEntity.Cell, moonpoolEntityAfter.Cell);
break;
case PlanterEntity _ when globalRootEntityAfter is PlanterEntity:
case PlanterEntity when globalRootEntityAfter is PlanterEntity:
break;
case PlayerWorldEntity _ when globalRootEntityAfter is PlayerWorldEntity:
case PlayerWorldEntity when globalRootEntityAfter is PlayerWorldEntity:
break;
case VehicleWorldEntity vehicleWorldEntity when globalRootEntityAfter is VehicleWorldEntity vehicleWorldEntityAfter:
Assert.AreEqual(vehicleWorldEntity.SpawnerId, vehicleWorldEntityAfter.SpawnerId);
Expand Down Expand Up @@ -448,7 +448,7 @@ private static void EntityTest(Entity entity, Entity entityAfter)
case PathBasedChildEntity pathBasedChildEntity when entityAfter is PathBasedChildEntity pathBasedChildEntityAfter:
Assert.AreEqual(pathBasedChildEntity.Path, pathBasedChildEntityAfter.Path);
break;
case InstalledBatteryEntity _ when entityAfter is InstalledBatteryEntity _:
case InstalledBatteryEntity when entityAfter is InstalledBatteryEntity:
break;
case InstalledModuleEntity installedModuleEntity when entityAfter is InstalledModuleEntity installedModuleEntityAfter:
Assert.AreEqual(installedModuleEntity.Slot, installedModuleEntityAfter.Slot);
Expand Down
1 change: 1 addition & 0 deletions Nitrox.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Gameobject/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=gameobjects/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ingame/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=lifepod/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Mathf/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Medkit/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Moonpool/@EntryIndexedValue">True</s:Boolean>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using NitroxClient.Communication;
using NitroxClient.GameLogic.FMOD;
using NitroxClient.GameLogic.Spawning.Metadata.Processor.Abstract;
using NitroxModel.DataStructures.GameLogic.Entities.Metadata;
using NitroxModel.Packets;
using UnityEngine;

namespace NitroxClient.GameLogic.Spawning.Metadata.Processor;

public class EscapePodMetadataProcessor : EntityMetadataProcessor<EscapePodMetadata>
{
public override void ProcessMetadata(GameObject gameObject, EscapePodMetadata metadata)
{
if (!gameObject.TryGetComponent(out EscapePod pod))
{
Log.Error($"[{nameof(EscapePodMetadataProcessor)}] Could not get the EscapePod component from the provided gameobject.");
return;
}

if (!pod.radioSpawner.spawnedObj.TryGetComponent(out Radio radio))
{
Log.Error($"[{nameof(EscapePodMetadataProcessor)}] Could not get Radio from EscapePod.");
return;
}

if (!pod.liveMixin.IsFullHealth() && metadata.PodRepaired)
{
pod.OnRepair();
}

if (!radio.liveMixin.IsFullHealth() && metadata.RadioRepaired)
{
radio.OnRepair();
}

ProcessInitialSyncMetadata(pod, radio, metadata);
}

public static void ProcessInitialSyncMetadata(EscapePod pod, Radio radio, EscapePodMetadata metadata)
{
using FMODSoundSuppressor soundSuppressor = FMODSystem.SuppressSubnauticaSounds();
using PacketSuppressor<EntityMetadataUpdate> packetSuppressor = PacketSuppressor<EntityMetadataUpdate>.Suppress();

if (metadata.PodRepaired)
{
pod.liveMixin.health = pod.liveMixin.maxHealth;
pod.healthScalar = 1;
pod.damageEffectsShowing = true;

using (FMODSystem.SuppressSubnauticaSounds())
{
pod.UpdateDamagedEffects();
}
pod.lightingController.SnapToState(0);
}
else
{
IntroLifepodDirector introLifepodDirector = pod.GetComponent<IntroLifepodDirector>();
introLifepodDirector.OnProtoDeserializeObjectTree(null);
introLifepodDirector.ToggleActiveObjects(false);
pod.lightingController.SnapToState(2);
}

if (metadata.RadioRepaired)
{
radio.liveMixin.health = radio.liveMixin.maxHealth;
Object.Destroy(radio.liveMixin.loopingDamageEffectObj);
}
else
{
pod.DamageRadio();
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using System.Collections;
using NitroxClient.GameLogic.Spawning.Metadata;
using NitroxClient.GameLogic.Spawning.Metadata.Processor;
using NitroxClient.MonoBehaviours;
using NitroxClient.MonoBehaviours.CinematicController;
using NitroxModel.DataStructures.GameLogic.Entities;
using NitroxModel.DataStructures.GameLogic.Entities.Metadata;
using NitroxModel.DataStructures.Util;
using NitroxModel_Subnautica.DataStructures;
using UnityEngine;
Expand All @@ -11,13 +12,6 @@ namespace NitroxClient.GameLogic.Spawning.WorldEntities;

public class EscapePodWorldEntitySpawner : IWorldEntitySpawner
{
private readonly EntityMetadataManager entityMetadataManager;

public EscapePodWorldEntitySpawner(EntityMetadataManager entityMetadataManager)
{
this.entityMetadataManager = entityMetadataManager;
}

/*
* When creating additional escape pods (multiple users with multiple pods)
* we want to suppress the escape pod's awake method so it doesn't override
Expand Down Expand Up @@ -49,12 +43,11 @@ private GameObject CreateNewEscapePod(EscapePodWorldEntity escapePodEntity)
// This will require some work as instantiating the prefab as-is will not make it visible.
//GameObject escapePod = Object.Instantiate(EscapePod.main.gameObject);
GameObject escapePod = EscapePod.main.gameObject;
EscapePod pod = escapePod.GetComponent<EscapePod>();

Object.DestroyImmediate(escapePod.GetComponent<NitroxEntity>()); // if template has a pre-existing NitroxEntity, remove.
NitroxEntity.SetNewId(escapePod, escapePodEntity.Id);

entityMetadataManager.ApplyMetadata(escapePod, escapePodEntity.Metadata);

if (escapePod.TryGetComponent(out Rigidbody rigidbody))
{
rigidbody.constraints = RigidbodyConstraints.FreezeAll;
Expand All @@ -66,6 +59,19 @@ private GameObject CreateNewEscapePod(EscapePodWorldEntity escapePodEntity)

escapePod.transform.position = escapePodEntity.Transform.Position.ToUnity();

pod.ForceSkyApplier();
pod.escapePodCinematicControl.StopAll();

if (escapePodEntity.Metadata is EscapePodMetadata metadata)
{
Radio radio = pod.radioSpawner.spawnedObj.GetComponent<Radio>();
EscapePodMetadataProcessor.ProcessInitialSyncMetadata(pod, radio, metadata);
}
else
{
Log.Error($"[{nameof(EscapePodWorldEntitySpawner)}] Metadata was not of type {nameof(EscapePodMetadata)}.");
}

FixStartMethods(escapePod);

return escapePod;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,17 @@ public class WorldEntitySpawnerResolver
public WorldEntitySpawnerResolver(EntityMetadataManager entityMetadataManager, PlayerManager playerManager, ILocalNitroxPlayer localPlayer, Entities entities, SimulationOwnership simulationOwnership)
{
customSpawnersByTechType[TechType.Crash] = new CrashEntitySpawner();
customSpawnersByTechType[TechType.EscapePod] = new EscapePodWorldEntitySpawner(entityMetadataManager);
customSpawnersByTechType[TechType.EscapePod] = new EscapePodWorldEntitySpawner();

vehicleWorldEntitySpawner = new(entities);
prefabPlaceholderEntitySpawner = new(defaultEntitySpawner);
vehicleWorldEntitySpawner = new VehicleWorldEntitySpawner(entities);
prefabPlaceholderEntitySpawner = new PrefabPlaceholderEntitySpawner(defaultEntitySpawner);
placeholderGroupWorldEntitySpawner = new PlaceholderGroupWorldEntitySpawner(entities, this, defaultEntitySpawner, entityMetadataManager, prefabPlaceholderEntitySpawner);
playerWorldEntitySpawner = new PlayerWorldEntitySpawner(playerManager, localPlayer);
serializedWorldEntitySpawner = new SerializedWorldEntitySpawner();
geyserWorldEntitySpawner = new(entities);
geyserWorldEntitySpawner = new GeyserWorldEntitySpawner(entities);
reefbackChildEntitySpawner = new ReefbackChildEntitySpawner();
reefbackEntitySpawner = new ReefbackEntitySpawner(reefbackChildEntitySpawner);
creatureRespawnEntitySpawner = new(simulationOwnership);
creatureRespawnEntitySpawner = new CreatureRespawnEntitySpawner(simulationOwnership);
}

public IWorldEntitySpawner ResolveEntitySpawner(WorldEntity entity)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace NitroxModel.DataStructures.GameLogic.Entities.Metadata
[ProtoInclude(60, typeof(ConstructorMetadata))]
[ProtoInclude(61, typeof(FlashlightMetadata))]
[ProtoInclude(62, typeof(BatteryMetadata))]
[ProtoInclude(63, typeof(RepairedComponentMetadata))]
[ProtoInclude(63, typeof(EscapePodMetadata))]
[ProtoInclude(64, typeof(CrafterMetadata))]
[ProtoInclude(65, typeof(PlantableMetadata))]
[ProtoInclude(66, typeof(CyclopsMetadata))]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using System.Runtime.Serialization;
using BinaryPack.Attributes;

namespace NitroxModel.DataStructures.GameLogic.Entities.Metadata;

[Serializable]
[DataContract]
public class EscapePodMetadata : EntityMetadata
{
[DataMember(Order = 1)]
public bool PodRepaired { get; }

[DataMember(Order = 2)]
public bool RadioRepaired { get; }

[IgnoreConstructor]
protected EscapePodMetadata()
{
//Constructor for serialization. Has to be "protected" for json serialization.
}

public EscapePodMetadata(bool podRepaired, bool radioRepaired)
{
PodRepaired = podRepaired;
RadioRepaired = radioRepaired;
}

public override string ToString()
{
return $"[{nameof(EscapePodMetadata)} - PodRepaired: {PodRepaired}, RadioRepaired: {RadioRepaired}]";
}
}

This file was deleted.

8 changes: 4 additions & 4 deletions NitroxPatcher/Patches/Dynamic/EscapePod_OnRepair_Patch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@
using NitroxModel.DataStructures.GameLogic.Entities.Metadata;
using NitroxModel.DataStructures;
using NitroxModel.Helper;
using NitroxModel_Subnautica.DataStructures;

namespace NitroxPatcher.Patches.Dynamic;

public sealed partial class EscapePod_OnRepair_Patch : NitroxPatch, IDynamicPatch
{
public static readonly MethodInfo TARGET_METHOD = Reflect.Method((EscapePod t) => t.OnRepair());
private static readonly MethodInfo TARGET_METHOD = Reflect.Method((EscapePod t) => t.OnRepair());

public static void Prefix(EscapePod __instance)
{
if (__instance.TryGetIdOrWarn(out NitroxId id))
if (__instance.TryGetIdOrWarn(out NitroxId id) &&
__instance.radioSpawner.spawnedObj.TryGetComponent(out Radio radio))
{
Resolve<Entities>().BroadcastMetadataUpdate(id, new RepairedComponentMetadata(TechType.EscapePod.ToDto()));
Resolve<Entities>().BroadcastMetadataUpdate(id, new EscapePodMetadata(true, radio.liveMixin.IsFullHealth()));
}
}
}
7 changes: 4 additions & 3 deletions NitroxPatcher/Patches/Dynamic/Radio_OnRepair_Patch.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using System.Reflection;
using NitroxClient.GameLogic;
using NitroxClient.Unity.Helper;
using NitroxModel.DataStructures;
using NitroxModel.DataStructures.GameLogic.Entities.Metadata;
using NitroxModel.Helper;
using NitroxModel_Subnautica.DataStructures;

namespace NitroxPatcher.Patches.Dynamic;

Expand All @@ -13,9 +13,10 @@ public sealed partial class Radio_OnRepair_Patch : NitroxPatch, IDynamicPatch

public static void Prefix(Radio __instance)
{
if (__instance.TryGetIdOrWarn(out NitroxId id))
if (__instance.TryGetComponentInParent(out EscapePod pod) &&
pod.TryGetIdOrWarn(out NitroxId id))
{
Resolve<Entities>().BroadcastMetadataUpdate(id, new RepairedComponentMetadata(TechType.Radio.ToDto()));
Resolve<Entities>().BroadcastMetadataUpdate(id, new EscapePodMetadata(pod.liveMixin.IsFullHealth(), true));
}
}
}
Loading

0 comments on commit d076af6

Please sign in to comment.