Skip to content

Commit

Permalink
Some refactoring, added a temporary (to be changed later on) Resolve<…
Browse files Browse the repository at this point in the history
…T> for DI in metadata extractors and processors
  • Loading branch information
tornac1234 committed Jan 5, 2024
1 parent 031a5ff commit b794c7f
Show file tree
Hide file tree
Showing 12 changed files with 80 additions and 36 deletions.
20 changes: 13 additions & 7 deletions Nitrox.Test/Server/Serialization/WorldPersistenceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,18 @@
using System.Reflection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Nitrox.Test;
using Nitrox.Test.Helper;
using Nitrox.Test.Helper.Faker;
using NitroxModel.Core;
using NitroxModel.DataStructures;
using NitroxModel.DataStructures.GameLogic;
using NitroxServer_Subnautica;
using NitroxServer.GameLogic;
using NitroxServer.GameLogic.Unlockables;
using NitroxServer.Serialization.World;
using NitroxModel.DataStructures.GameLogic.Entities;
using NitroxModel.DataStructures.GameLogic.Entities.Bases;
using NitroxModel.DataStructures.GameLogic.Entities.Metadata;
using NitroxModel.DataStructures.GameLogic.Entities.Metadata.Bases;
using NitroxModel.DataStructures;
using NitroxServer.GameLogic;
using NitroxServer.GameLogic.Unlockables;
using NitroxServer.Serialization.World;
using NitroxServer_Subnautica;

namespace NitroxServer.Serialization;

Expand Down Expand Up @@ -321,6 +320,10 @@ private static void EntityTest(Entity entity, Entity entityAfter)
case BeaconMetadata metadata when entityAfter.Metadata is BeaconMetadata metadataAfter:
Assert.AreEqual(metadata.Label, metadataAfter.Label);
break;
case RadiationMetadata metadata when entityAfter.Metadata is RadiationMetadata metadataAfter:
Assert.AreEqual(metadata.Health, metadataAfter.Health);
Assert.AreEqual(metadata.FixRealTime, metadataAfter.FixRealTime);
break;
default:
Assert.Fail($"Runtime type of {nameof(Entity)}.{nameof(Entity.Metadata)} is not equal: {entity.Metadata?.GetType().Name} - {entityAfter.Metadata?.GetType().Name}");
break;
Expand Down Expand Up @@ -413,8 +416,11 @@ private static void EntityTest(Entity entity, Entity entityAfter)
Assert.AreEqual(vehicleWorldEntity.SpawnerId, vehicleWorldEntityAfter.SpawnerId);
Assert.AreEqual(vehicleWorldEntity.ConstructionTime, vehicleWorldEntityAfter.ConstructionTime);
break;
case RadiationLeakEntity radiationLeakEntity when globalRootEntityAfter is RadiationLeakEntity radiationLeakEntityAfter:
Assert.AreEqual(radiationLeakEntity.ObjectIndex, radiationLeakEntityAfter.ObjectIndex);
break;
default:
Assert.Fail($"Runtime type of {nameof(WorldEntity)} is not equal even after the check: {worldEntity.GetType().Name} - {globalRootEntityAfter.GetType().Name}");
Assert.Fail($"Runtime type of {nameof(GlobalRootEntity)} is not equal even after the check: {worldEntity.GetType().Name} - {globalRootEntityAfter.GetType().Name}");
break;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public GlobalRootInitialSyncProcessor(Entities entities)
// inventory items to them. Eventually, all of the below processors will become entities on their own
AddDependency<PlayerInitialSyncProcessor>();
AddDependency<RemotePlayerInitialSyncProcessor>();
AddDependency<StoryGoalInitialSyncProcessor>();
}

public override IEnumerator Process(InitialPlayerSync packet, WaitScreen.ManualWaitItem waitScreenItem)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using NitroxModel.Core;
using NitroxModel.DataStructures.GameLogic.Entities.Metadata;
using NitroxModel.DataStructures.Util;

Expand All @@ -13,4 +14,9 @@ public Optional<EntityMetadata> From(object o)

return Optional.OfNullable(result);
}

protected T Resolve<T>() where T : class
{
return NitroxServiceLocator.Cache<T>.Value;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using NitroxClient.GameLogic.Spawning.Metadata.Extractor.Abstract;
using NitroxModel.Core;
using NitroxModel.DataStructures.GameLogic.Entities.Metadata;

namespace NitroxClient.GameLogic.Spawning.Metadata.Extractor;
Expand All @@ -9,8 +8,7 @@ public class RadiationMetadataExtractor : EntityMetadataExtractor<RadiationLeak,
public override RadiationMetadata Extract(RadiationLeak leak)
{
// Note: this extractor should only be used when this radiation leak is being repaired
TimeManager timeManager = NitroxServiceLocator.LocateService<TimeManager>();
float realTimeFix = leak.liveMixin.IsFullHealth() ? (float)timeManager.RealTimeElapsed : -1;
float realTimeFix = leak.liveMixin.IsFullHealth() ? (float)Resolve<TimeManager>().RealTimeElapsed : -1;
return new(leak.liveMixin.health, realTimeFix);
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using NitroxModel.Core;
using NitroxModel.DataStructures.GameLogic.Entities.Metadata;
using UnityEngine;

Expand All @@ -11,4 +12,9 @@ public void ProcessMetadata(GameObject gameObject, EntityMetadata metadata)
{
ProcessMetadata(gameObject, (T)metadata);
}

protected T Resolve<T>() where T : class
{
return NitroxServiceLocator.Cache<T>.Value;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using NitroxClient.Communication;
using NitroxClient.GameLogic.Spawning.Metadata.Processor.Abstract;
using NitroxModel.Core;
using NitroxModel.DataStructures.GameLogic.Entities.Metadata;
using NitroxModel.Packets;
using UnityEngine;
Expand All @@ -16,10 +15,9 @@ public override void ProcessMetadata(GameObject gameObject, RadiationMetadata me
Log.Error($"[{nameof(RadiationMetadataProcessor)}] Couldn't find LiveMixin on {gameObject}");
return;
}
LiveMixinManager liveMixinManager = NitroxServiceLocator.LocateService<LiveMixinManager>();
using (PacketSuppressor<EntityMetadataUpdate>.Suppress())
{
liveMixinManager.SyncRemoteHealth(liveMixin, metadata.Health);
Resolve<LiveMixinManager>().SyncRemoteHealth(liveMixin, metadata.Health);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace NitroxClient.GameLogic.Spawning.WorldEntities;

public class RadiationLeakEntitySpawner : SyncEntitySpawner<RadiationLeakEntity>
{
// This constant is defined by Subnautica and should never be modified (same as for SubnauticaWorldModifier)
private const int TOTAL_LEAKS = 11;
private readonly TimeManager timeManager;
private readonly List<float> registeredLeaksFixTime = new();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Runtime.Serialization;
using BinaryPack.Attributes;

namespace NitroxModel.DataStructures.GameLogic.Entities.Metadata;

Expand All @@ -12,9 +13,20 @@ public class RadiationMetadata : EntityMetadata
[DataMember(Order = 2)]
public float FixRealTime { get; set; }

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

public RadiationMetadata(float health, float fixRealTime = -1)
{
Health = health;
FixRealTime = fixRealTime;
}

public override string ToString()
{
return $"[{nameof(RadiationMetadata)} Health: {Health}, FixRealTime: {FixRealTime}]";
}
}
5 changes: 4 additions & 1 deletion NitroxServer-Subnautica/GameLogic/SubnauticaWorldModifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ namespace NitroxServer_Subnautica.GameLogic;

public class SubnauticaWorldModifier : IWorldModifier
{
// This constant is defined by Subnautica and should never be modified
private const int TOTAL_LEAKS = 11;

public void ModifyWorld(World world)
{
// Creating entities for the 11 RadiationLeakPoint located at (Aurora Scene) //Aurora-MainPrefab/Aurora/radiationleaks/RadiationLeaks(Clone)
for (int i = 0; i < 11; i++)
for (int i = 0; i < TOTAL_LEAKS; i++)
{
RadiationLeakEntity leakEntity = new(new(), i, new(0));
world.WorldEntityManager.AddGlobalRootEntity(leakEntity);
Expand Down
38 changes: 23 additions & 15 deletions NitroxServer/GameLogic/StoryManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace NitroxServer.GameLogic;
/// <summary>
/// Keeps track of time and Aurora-related events.
/// </summary>
public class StoryManager
public class StoryManager : IDisposable
{
private readonly PlayerManager playerManager;
private readonly PDAStateData pdaStateData;
Expand Down Expand Up @@ -50,24 +50,26 @@ public StoryManager(PlayerManager playerManager, PDAStateData pdaStateData, Stor
AuroraCountdownTimeMs = auroraExplosionTime ?? GenerateDeterministicAuroraTime(seed);
AuroraWarningTimeMs = auroraWarningTime ?? ElapsedMilliseconds;
// +27 is from CrashedShipExploder.IsExploded, -480 is from the default time (see TimeKeeper)
AuroraRealExplosionTime = auroraRealExplosionTime ?? AuroraCountdownTimeMs * 0.001 + 27 - 480;
AuroraRealExplosionTime = auroraRealExplosionTime ?? AuroraCountdownTimeMs * 0.001 + 27 - TimeKeeper.DEFAULT_TIME;

timeKeeper.OnTimeSkipped += timeSkipped =>
timeKeeper.TimeSkipped += ReadjustAuroraRealExplosionTime;
}

public void ReadjustAuroraRealExplosionTime(double skipAmount)
{
// Readjust the aurora real explosion time when time skipping because it's based on in-game time
if (AuroraRealExplosionTime > timeKeeper.RealTimeElapsed)
{
// Readjust the aurora real explosion time when time skipping because it's based on in-game time
if (AuroraRealExplosionTime > timeKeeper.RealTimeElapsed)
double newTime = timeKeeper.RealTimeElapsed + skipAmount;
if (newTime > AuroraRealExplosionTime)
{
AuroraRealExplosionTime = timeKeeper.RealTimeElapsed;
}
else
{
double newTime = timeKeeper.RealTimeElapsed + timeSkipped;
if (newTime > AuroraRealExplosionTime)
{
AuroraRealExplosionTime = timeKeeper.RealTimeElapsed;
}
else
{
AuroraRealExplosionTime -= timeSkipped;
}
AuroraRealExplosionTime -= skipAmount;
}
};
}
}

/// <param name="instantaneous">Whether we should make Aurora explode instantly or after a short countdown</param>
Expand Down Expand Up @@ -195,6 +197,12 @@ public TimeData GetTimeData()
return new(timeKeeper.MakeTimePacket(), MakeAuroraData());
}

public void Dispose()
{
timeKeeper.TimeSkipped -= ReadjustAuroraRealExplosionTime;
GC.SuppressFinalize(this);
}

public enum TimeModification
{
DAY, NIGHT, SKIP
Expand Down
14 changes: 9 additions & 5 deletions NitroxServer/GameLogic/TimeKeeper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ public class TimeKeeper

private readonly Stopwatch stopWatch = new();

/// <summary>
/// Default time in Base SN is 480s
/// </summary>
public const int DEFAULT_TIME = 480;

/// <summary>
/// Latest registered time without taking the current stopwatch time in account.
/// </summary>
Expand Down Expand Up @@ -65,14 +70,13 @@ public double ElapsedSeconds
/// </remarks>
private const int RESYNC_INTERVAL = 60;

public TimeSkipped OnTimeSkipped;
public TimeSkippedEventHandler TimeSkipped;

public TimeKeeper(PlayerManager playerManager, double elapsedSeconds, double realTimeElapsed)
{
this.playerManager = playerManager;

// Default time in Base SN is 480s
elapsedTimeOutsideStopWatchMs = elapsedSeconds == 0 ? TimeSpan.FromSeconds(480).TotalMilliseconds : elapsedSeconds * 1000;
elapsedTimeOutsideStopWatchMs = elapsedSeconds == 0 ? TimeSpan.FromSeconds(DEFAULT_TIME).TotalMilliseconds : elapsedSeconds * 1000;
this.realTimeElapsed = realTimeElapsed;
ResyncTimer = MakeResyncTimer();
}
Expand Down Expand Up @@ -134,7 +138,7 @@ public void ChangeTime(TimeModification type)
if (skipAmount > 0)
{
ElapsedSeconds += skipAmount;
OnTimeSkipped?.Invoke(skipAmount);
TimeSkipped?.Invoke(skipAmount);

playerManager.SendPacketToAllPlayers(MakeTimePacket());
}
Expand All @@ -145,5 +149,5 @@ public TimeChange MakeTimePacket()
return new(ElapsedSeconds, DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), RealTimeElapsed);
}

public delegate void TimeSkipped(double skipAmount);
public delegate void TimeSkippedEventHandler(double skipAmount);
}
5 changes: 3 additions & 2 deletions NitroxServer/Serialization/World/WorldPersistence.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,16 @@ public class WorldPersistence
private readonly ServerJsonSerializer jsonSerializer;
private readonly ServerConfig config;
private readonly RandomStartGenerator randomStart;
private readonly IWorldModifier worldModifier;
private readonly SaveDataUpgrade[] upgrades;

public WorldPersistence(ServerProtoBufSerializer protoBufSerializer, ServerJsonSerializer jsonSerializer, ServerConfig config, RandomStartGenerator randomStart, SaveDataUpgrade[] upgrades)
public WorldPersistence(ServerProtoBufSerializer protoBufSerializer, ServerJsonSerializer jsonSerializer, ServerConfig config, RandomStartGenerator randomStart, IWorldModifier worldModifier, SaveDataUpgrade[] upgrades)
{
this.protoBufSerializer = protoBufSerializer;
this.jsonSerializer = jsonSerializer;
this.config = config;
this.randomStart = randomStart;
this.worldModifier = worldModifier;
this.upgrades = upgrades;

UpdateSerializer(config.SerializerMode);
Expand Down Expand Up @@ -177,7 +179,6 @@ private World CreateFreshWorld()
};

World newWorld = CreateWorld(pWorldData, config.GameMode);
IWorldModifier worldModifier = NitroxServiceLocator.LocateService<IWorldModifier>();
worldModifier.ModifyWorld(newWorld);

return newWorld;
Expand Down

0 comments on commit b794c7f

Please sign in to comment.