Skip to content

Commit 3456686

Browse files
authored
Fix cyclops initsync (SubnauticaNitrox#1065)
* Added logging and TryGetVehicle variant to check return value instead of exception * Added ToString for VehicleModel.cs * Fixed CyclopsLightingPanel trying to get NitroxID from wrong GO It checked the instance.gameObject which is the LightsControl sub GO of the Cyclops GO. So it's fixed by getting the parent of the instance.gameObject, being the Cyclops main GO. * Used Optional.OfNullable for TryGetVehicle instead of .Of() * Handled Unity object destroyed case for Optional.OfNullable()
1 parent 3eb1bf5 commit 3456686

4 files changed

Lines changed: 51 additions & 16 deletions

File tree

NitroxClient/GameLogic/Vehicles.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ public void SetOnPilotMode(NitroxId vehicleId, ushort playerId, bool isPiloting)
412412
public void AddVehicle(VehicleModel vehicleModel)
413413
{
414414
vehiclesById.Add(vehicleModel.Id, vehicleModel);
415+
Log.Debug($"{nameof(Vehicles)}: Added vehicle {vehicleModel}");
415416
}
416417

417418
public bool RemoveVehicle(VehicleModel vehicleModel)
@@ -428,5 +429,12 @@ public T GetVehicles<T>(NitroxId vehicleId) where T : VehicleModel
428429
{
429430
return (T)vehiclesById[vehicleId];
430431
}
432+
433+
public Optional<T> TryGetVehicle<T>(NitroxId vehicleId) where T : VehicleModel
434+
{
435+
VehicleModel vehicle;
436+
vehiclesById.TryGetValue(vehicleId, out vehicle);
437+
return Optional.OfNullable((T)vehicle);
438+
}
431439
}
432440
}

NitroxModel/DataStructures/GameLogic/VehicleModel.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,10 @@ public VehicleModel(TechType techType, NitroxId id, Vector3 position, Quaternion
6161
Colours = colours;
6262
Health = health;
6363
}
64+
65+
public override string ToString()
66+
{
67+
return $"{nameof(TechType)}: {TechType}, {nameof(Id)}: {Id}, {nameof(Position)}: {Position}, {nameof(Name)}: {Name}";
68+
}
6469
}
6570
}

NitroxModel/DataStructures/Optional.cs

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,27 +22,27 @@ public struct Optional<T> : ISerializable
2222
public T Value { get; private set; }
2323

2424
private bool hasValue;
25-
25+
2626
[ProtoMember(2)]
2727
public bool HasValue
2828
{
2929
get
3030
{
31-
if (ReferenceEquals(Value, null))
32-
{
33-
return false;
34-
}
35-
36-
// Check to satisfy unity objects. Sometimes they are internally destroyed but are not considered null.
37-
// For the purpose of optional, we consider a dead object to be the same as null.
38-
return Value.ToString() != "null";
31+
return !IsDestroyedUnityObjectOrNull(Value);
3932
}
4033
set
4134
{
4235
hasValue = value;
4336
}
4437
}
4538

39+
private static bool IsDestroyedUnityObjectOrNull<TValue>(TValue value)
40+
{
41+
// Check to satisfy unity objects. Sometimes they are internally destroyed but are not considered null.
42+
// For the purpose of optional, we consider a dead object to be the same as null.
43+
return ReferenceEquals(value, null) || value.ToString() == "null";
44+
}
45+
4646
private Optional(T value)
4747
{
4848
Value = value;
@@ -66,6 +66,10 @@ internal static Optional<T> Of(T value)
6666

6767
internal static Optional<T> OfNullable(T value)
6868
{
69+
if (IsDestroyedUnityObjectOrNull(value))
70+
{
71+
return Optional.Empty;
72+
}
6973
return Equals(default(T), value) ? Optional.Empty : new Optional<T>(value);
7074
}
7175

@@ -88,7 +92,10 @@ public void GetObjectData(SerializationInfo info, StreamingContext context)
8892
info.AddValue("hasValue", HasValue);
8993
}
9094

91-
public static implicit operator Optional<T>(OptionalEmpty none) => new Optional<T>();
95+
public static implicit operator Optional<T>(OptionalEmpty none)
96+
{
97+
return new Optional<T>();
98+
}
9299

93100
public static implicit operator Optional<T>?(T obj)
94101
{
@@ -118,8 +125,15 @@ public static class Optional
118125
{
119126
public static OptionalEmpty Empty { get; } = new OptionalEmpty();
120127

121-
public static Optional<T> Of<T>(T value) => Optional<T>.Of(value);
122-
public static Optional<T> OfNullable<T>(T value) => Optional<T>.OfNullable(value);
128+
public static Optional<T> Of<T>(T value)
129+
{
130+
return Optional<T>.Of(value);
131+
}
132+
133+
public static Optional<T> OfNullable<T>(T value)
134+
{
135+
return Optional<T>.OfNullable(value);
136+
}
123137
}
124138

125139
public sealed class OptionalNullException<T> : Exception

NitroxPatcher/Patches/Dynamic/CyclopsLightingPanel_OnSubConstructionComplete_Patch.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
using Harmony;
44
using NitroxClient.GameLogic;
55
using NitroxClient.MonoBehaviours;
6+
using NitroxClient.Unity.Helper;
67
using NitroxModel.Core;
78
using NitroxModel.DataStructures;
9+
using NitroxModel.DataStructures.Util;
10+
using NitroxModel.Logger;
811
using NitroxModel_Subnautica.DataStructures.GameLogic;
912
using UnityEngine;
1013

@@ -18,11 +21,16 @@ class CyclopsLightingPanel_OnSubConstructionComplete_Patch : NitroxPatch, IDynam
1821
public static bool Prefix(CyclopsLightingPanel __instance)
1922
{
2023
// Suppress powered on if a cyclops´s floodlight is set to false
21-
GameObject gameObject = __instance.gameObject;
24+
GameObject gameObject = __instance.gameObject.transform.parent.gameObject; // GO = LightsControl, Parent = main cyclops game object
2225
NitroxId id = NitroxEntity.GetId(gameObject);
23-
CyclopsModel model = NitroxServiceLocator.LocateService<Vehicles>().GetVehicles<CyclopsModel>(id);
24-
25-
return model.FloodLightsOn;
26+
Optional<CyclopsModel> model = NitroxServiceLocator.LocateService<Vehicles>().TryGetVehicle<CyclopsModel>(id);
27+
if (!model.HasValue)
28+
{
29+
Log.Error($"{nameof(CyclopsLightingPanel_OnSubConstructionComplete_Patch)}: Could not find {nameof(CyclopsModel)} by Nitrox id {id}.\nGO containing wrong id: {__instance.GetHierarchyPath()}");
30+
return false;
31+
}
32+
33+
return model.Value.FloodLightsOn;
2634
}
2735

2836
public override void Patch(HarmonyInstance harmony)

0 commit comments

Comments
 (0)