Skip to content

Commit 936a621

Browse files
committed
Added a new system for persisting entity metadata and broadcasting those updates; this is modeled after drop actions and build metadata processors. Initial implementation uses the keypad class as an example (though it doesn't work in game as the nitrox ids for this entity type are not yet spawned by the server).
1 parent 69a4116 commit 936a621

17 files changed

Lines changed: 294 additions & 1 deletion

File tree

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using NitroxClient.Communication.Packets.Processors.Abstract;
2+
using NitroxClient.GameLogic.Spawning.Metadata;
3+
using NitroxClient.MonoBehaviours;
4+
using NitroxModel.DataStructures.Util;
5+
using NitroxModel.Helper;
6+
using NitroxModel.Packets;
7+
using UnityEngine;
8+
9+
namespace NitroxClient.Communication.Packets.Processors
10+
{
11+
public class EntityMetadataUpdateProcessor : ClientPacketProcessor<EntityMetadataUpdate>
12+
{
13+
public override void Process(EntityMetadataUpdate update)
14+
{
15+
GameObject gameObject = NitroxEntity.RequireObjectFrom(update.Id);
16+
17+
Optional<EntityMetadataProcessor> metadataProcessor = EntityMetadataProcessor.FromMetaData(update.NewValue);
18+
Validate.IsTrue(metadataProcessor.HasValue, $"No processor found for EntityMetadata of type {update.NewValue.GetType()}");
19+
20+
metadataProcessor.Value.ProcessMetadata(gameObject, update.NewValue);
21+
}
22+
}
23+
}

NitroxClient/GameLogic/Entities.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using NitroxClient.MonoBehaviours;
66
using NitroxModel.DataStructures;
77
using NitroxModel.DataStructures.GameLogic;
8+
using NitroxModel.DataStructures.GameLogic.Entities.Metadata;
89
using NitroxModel.DataStructures.Util;
910
using NitroxModel.Helper;
1011
using NitroxModel.Logger;
@@ -50,6 +51,12 @@ public void BroadcastTransforms(Dictionary<NitroxId, GameObject> gameObjectsById
5051
packetSender.Send(update);
5152
}
5253

54+
public void BroadcastMetadataUpdate(NitroxId id, EntityMetadata metadata)
55+
{
56+
EntityMetadataUpdate update = new EntityMetadataUpdate(id, metadata);
57+
packetSender.Send(update);
58+
}
59+
5360
public void Spawn(List<Entity> entities)
5461
{
5562
foreach (Entity entity in entities)

NitroxClient/GameLogic/Spawning/DefaultEntitySpawner.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using NitroxClient.MonoBehaviours;
1+
using NitroxClient.GameLogic.Spawning.Metadata;
2+
using NitroxClient.MonoBehaviours;
23
using NitroxModel.DataStructures.GameLogic;
34
using NitroxModel.DataStructures.Util;
45
using NitroxModel_Subnautica.Helper;
@@ -45,6 +46,13 @@ public Optional<GameObject> Spawn(Entity entity, Optional<GameObject> parent, En
4546
gameObject.SetActive(true);
4647
}
4748

49+
Optional<EntityMetadataProcessor> metadataProcessor = EntityMetadataProcessor.FromMetaData(entity.Metadata);
50+
51+
if (metadataProcessor.HasValue)
52+
{
53+
metadataProcessor.Value.ProcessMetadata(gameObject, entity.Metadata);
54+
}
55+
4856
return Optional.Of(gameObject);
4957
}
5058

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Reflection;
5+
using NitroxModel.DataStructures.GameLogic.Entities.Metadata;
6+
using NitroxModel.DataStructures.Util;
7+
using UnityEngine;
8+
9+
namespace NitroxClient.GameLogic.Spawning.Metadata
10+
{
11+
public abstract class EntityMetadataProcessor
12+
{
13+
public abstract void ProcessMetadata(GameObject gameObject, EntityMetadata metadata);
14+
15+
private static Dictionary<Type, Optional<EntityMetadataProcessor>> processorsByType = new Dictionary<Type, Optional<EntityMetadataProcessor>>();
16+
17+
static EntityMetadataProcessor()
18+
{
19+
IEnumerable<EntityMetadataProcessor> processors = Assembly.GetExecutingAssembly()
20+
.GetTypes()
21+
.Where(t => typeof(EntityMetadataProcessor).IsAssignableFrom(t) &&
22+
t.IsClass &&
23+
!t.IsAbstract
24+
)
25+
.Select(Activator.CreateInstance)
26+
.Cast<EntityMetadataProcessor>();
27+
28+
foreach (EntityMetadataProcessor processor in processors)
29+
{
30+
Type metadataType = processor.GetType().BaseType.GetGenericArguments()[0];
31+
processorsByType.Add(metadataType, Optional.Of(processor));
32+
}
33+
}
34+
35+
public static Optional<EntityMetadataProcessor> FromMetaData(EntityMetadata metadata)
36+
{
37+
Optional<EntityMetadataProcessor> processor;
38+
39+
if (metadata != null && processorsByType.TryGetValue(metadata.GetType(), out processor))
40+
{
41+
return processor;
42+
}
43+
44+
return Optional.Empty;
45+
}
46+
}
47+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using NitroxModel.DataStructures.GameLogic.Entities.Metadata;
2+
using UnityEngine;
3+
4+
namespace NitroxClient.GameLogic.Spawning.Metadata
5+
{
6+
public abstract class GenericEntityMetadataProcessor<T> : EntityMetadataProcessor where T : EntityMetadata
7+
{
8+
public abstract void ProcessMetadata(GameObject gameObject, T metadata);
9+
10+
public override void ProcessMetadata(GameObject gameObject, EntityMetadata metadata)
11+
{
12+
ProcessMetadata(gameObject, (T)metadata);
13+
}
14+
}
15+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using NitroxModel.DataStructures.GameLogic.Entities.Metadata;
2+
using NitroxModel.Logger;
3+
using UnityEngine;
4+
5+
namespace NitroxClient.GameLogic.Spawning.Metadata
6+
{
7+
public class KeypadMetadataProcessor : GenericEntityMetadataProcessor<KeypadMetadata>
8+
{
9+
public override void ProcessMetadata(GameObject gameObject, KeypadMetadata metadata)
10+
{
11+
Log.Info($"Received keypad metadata chagen for {gameObject.name} with data of {metadata}");
12+
13+
KeypadDoorConsole keypad = gameObject.GetComponent<KeypadDoorConsole>();
14+
keypad.unlocked = metadata.Unlocked;
15+
16+
if (metadata.Unlocked)
17+
{
18+
if (keypad.root)
19+
{
20+
keypad.root.BroadcastMessage("UnlockDoor");
21+
}
22+
else
23+
{
24+
keypad.BroadcastMessage("UnlockDoor");
25+
}
26+
27+
keypad.UnlockDoor();
28+
}
29+
}
30+
}
31+
}

NitroxClient/GameLogic/Spawning/SerializedEntitySpawner.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using NitroxClient.GameLogic.Helper;
22
using NitroxClient.GameLogic.ItemDropActions;
3+
using NitroxClient.GameLogic.Spawning.Metadata;
34
using NitroxClient.MonoBehaviours;
45
using NitroxClient.Unity.Helper;
56
using NitroxModel.DataStructures;
@@ -30,6 +31,13 @@ public Optional<GameObject> Spawn(Entity entity, Optional<GameObject> parent, En
3031

3132
NitroxEntity.SetNewId(gameObject, entity.Id);
3233

34+
Optional<EntityMetadataProcessor> metadataProcessor = EntityMetadataProcessor.FromMetaData(entity.Metadata);
35+
36+
if (metadataProcessor.HasValue)
37+
{
38+
metadataProcessor.Value.ProcessMetadata(gameObject, entity.Metadata);
39+
}
40+
3341
return Optional.Of(gameObject);
3442
}
3543

NitroxClient/NitroxClient.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@
234234
<Compile Include="ClientAutoFacRegistrar.cs" />
235235
<Compile Include="Communication\PacketReceiver.cs" />
236236
<Compile Include="Communication\Packets\Processors\BedEnterProcessor.cs" />
237+
<Compile Include="Communication\Packets\Processors\EntityMetadataUpdateProcessor.cs" />
237238
<Compile Include="Communication\Packets\Processors\PingRenamedProcessor.cs" />
238239
<Compile Include="Communication\Packets\Processors\RadioPlayPendingMessageProcessor.cs" />
239240
<Compile Include="Communication\Packets\Processors\ExosuitArmActionProcessor.cs" />
@@ -242,6 +243,9 @@
242243
<Compile Include="GameLogic\Bases\Spawning\BaseLadderSpawnProcessor.cs" />
243244
<Compile Include="GameLogic\Bases\Spawning\NoOpBasePieceSpawnProcessor.cs" />
244245
<Compile Include="GameLogic\ChatUI\PlayerChatManager.cs" />
246+
<Compile Include="GameLogic\Spawning\Metadata\KeypadMetadataProcessor.cs" />
247+
<Compile Include="GameLogic\Spawning\Metadata\EntityMetadataProcessor.cs" />
248+
<Compile Include="GameLogic\Spawning\Metadata\GenericEntityMetadataProcessor.cs" />
245249
<Compile Include="GameLogic\InitialSync\CyclopsInitialAsyncProcessor.cs" />
246250
<Compile Include="GameLogic\InitialSync\PlayerModulesInitialSyncProcessor.cs" />
247251
<Compile Include="GameLogic\InitialSync\StorageSlotsInitialSyncProcessor.cs" />
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
using ProtoBufNet;
3+
4+
namespace NitroxModel.DataStructures.GameLogic.Entities.Metadata
5+
{
6+
[Serializable]
7+
[ProtoContract, ProtoInclude(50, typeof(KeypadMetadata))]
8+
public abstract class EntityMetadata
9+
{
10+
}
11+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System;
2+
using ProtoBufNet;
3+
4+
namespace NitroxModel.DataStructures.GameLogic.Entities.Metadata
5+
{
6+
[Serializable]
7+
[ProtoContract]
8+
public class KeypadMetadata : EntityMetadata
9+
{
10+
[ProtoMember(1)]
11+
public bool Unlocked { get; }
12+
13+
public KeypadMetadata()
14+
{
15+
// Constructor for serialization
16+
}
17+
18+
public KeypadMetadata(bool unlocked)
19+
{
20+
Unlocked = Unlocked;
21+
}
22+
}
23+
}

0 commit comments

Comments
 (0)