Skip to content

Commit

Permalink
move determinstic stuff to separate folder, remove WO dumps
Browse files Browse the repository at this point in the history
  • Loading branch information
misternebula committed Feb 14, 2024
1 parent b04a593 commit cb6b811
Show file tree
Hide file tree
Showing 14 changed files with 307 additions and 314 deletions.
2 changes: 1 addition & 1 deletion QSB/EchoesOfTheEye/AlarmTotemSync/AlarmTotemManager.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Cysharp.Threading.Tasks;
using QSB.EchoesOfTheEye.AlarmTotemSync.WorldObjects;
using QSB.Utility;
using QSB.Utility.Deterministic;
using QSB.WorldSync;
using System.Linq;
using System.Threading;
Expand Down
2 changes: 1 addition & 1 deletion QSB/EchoesOfTheEye/Ghosts/GhostManager.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Cysharp.Threading.Tasks;
using QSB.EchoesOfTheEye.Ghosts.WorldObjects;
using QSB.Utility;
using QSB.Utility.Deterministic;
using QSB.WorldSync;
using System.Collections.Generic;
using System.Linq;
Expand Down
2 changes: 1 addition & 1 deletion QSB/EchoesOfTheEye/LightSensorSync/LightSensorManager.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Cysharp.Threading.Tasks;
using QSB.EchoesOfTheEye.LightSensorSync.WorldObjects;
using QSB.Utility;
using QSB.Utility.Deterministic;
using QSB.WorldSync;
using System.Linq;
using System.Threading;
Expand Down
1 change: 1 addition & 0 deletions QSB/ItemSync/ItemManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using QSB.ItemSync.WorldObjects.Items;
using QSB.ItemSync.WorldObjects.Sockets;
using QSB.Utility;
using QSB.Utility.Deterministic;
using QSB.WorldSync;
using System.Linq;
using System.Threading;
Expand Down
2 changes: 1 addition & 1 deletion QSB/PoolSync/PoolManager.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using Cysharp.Threading.Tasks;
using QSB.Utility;
using QSB.Utility.Deterministic;
using QSB.WorldSync;
using System.Threading;

Expand Down
1 change: 1 addition & 0 deletions QSB/QSBCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
using UnityEngine;
using UnityEngine.InputSystem;
using Random = System.Random;
using QSB.Utility.Deterministic;

/*
Copyright (C) 2020 - 2023
Expand Down
1 change: 1 addition & 0 deletions QSB/Syncs/Occasional/OccasionalManager.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Cysharp.Threading.Tasks;
using Mirror;
using QSB.Utility;
using QSB.Utility.Deterministic;
using QSB.WorldSync;
using System.Collections.Generic;
using System.Linq;
Expand Down
2 changes: 1 addition & 1 deletion QSB/Tools/ProbeLauncherTool/ProbeLauncherManager.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Cysharp.Threading.Tasks;
using QSB.Tools.ProbeLauncherTool.WorldObjects;
using QSB.Utility;
using QSB.Utility.Deterministic;
using QSB.WorldSync;
using System.Linq;
using System.Threading;
Expand Down
3 changes: 0 additions & 3 deletions QSB/Utility/DebugSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ namespace QSB.Utility;
[JsonObject(MemberSerialization.OptIn)]
public class DebugSettings
{
[JsonProperty("dumpWorldObjects")]
public bool DumpWorldObjects;

[JsonProperty("logQSBMessages")]
public bool LogQSBMessages;

Expand Down
80 changes: 80 additions & 0 deletions QSB/Utility/Deterministic/DeterministicManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using HarmonyLib;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

namespace QSB.Utility.Deterministic;

/// <summary>
/// TODO make this only do cache clearing on pre scene load when HOSTING instead of just all the time
/// </summary>
public static class DeterministicManager
{
private static readonly Harmony _harmony = new(typeof(DeterministicManager).FullName);
private static bool _patched;

public static readonly Dictionary<Transform, (int SiblingIndex, Transform Parent)> Cache = new();

public static void Init() =>
QSBSceneManager.OnPreSceneLoad += (_, _) =>
{
DebugLog.DebugWrite("cleared cache");
Cache.Clear();
if (!_patched)
{
_harmony.PatchAll(typeof(OWRigidbodyPatches));
_patched = true;
}
};

public static void OnWorldObjectsAdded()
{
//DebugLog.DebugWrite($"cleared cache of {_cache.Count} entries");
//_cache.Clear();

if (_patched)
{
_harmony.UnpatchSelf();
_patched = false;
}
}

/// <summary>
/// only call this before world objects added
/// </summary>
public static string DeterministicPath(this Component component)
{
var sb = new StringBuilder();
var transform = component.transform;
while (true)
{
if (!Cache.TryGetValue(transform, out var data))
{
data = (transform.GetSiblingIndex(), transform.parent);
Cache.Add(transform, data);
}

if (!data.Parent)
{
break;
}

sb.Append(transform.name);
sb.Append(' ');
sb.Append(data.SiblingIndex);
sb.Append(' ');
transform = data.Parent;
}

sb.Append(transform.name);
return sb.ToString();
}

/// <summary>
/// only call this before world objects added
/// </summary>
public static IEnumerable<T> SortDeterministic<T>(this IEnumerable<T> components) where T : Component
=> components.OrderBy(DeterministicPath);
}
217 changes: 217 additions & 0 deletions QSB/Utility/Deterministic/OWRigidbodyPatches.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
using HarmonyLib;
using System.Collections.Generic;
using UnityEngine;

namespace QSB.Utility.Deterministic;

[HarmonyPatch(typeof(OWRigidbody))]
public static class OWRigidbodyPatches
{
private static readonly Dictionary<OWRigidbody, Transform> _setParentQueue = new();

[HarmonyPrefix]
[HarmonyPatch(nameof(OWRigidbody.Awake))]
private static bool Awake(OWRigidbody __instance)
{
__instance._transform = __instance.transform;

// ADDED
DeterministicManager.Cache.Add(__instance._transform, (__instance._transform.GetSiblingIndex(), __instance._transform.parent));

if (!__instance._scaleRoot)
{
__instance._scaleRoot = __instance._transform;
}

CenterOfTheUniverse.TrackRigidbody(__instance);
__instance._offsetApplier = __instance.gameObject.GetAddComponent<CenterOfTheUniverseOffsetApplier>();
__instance._offsetApplier.Init(__instance);
if (__instance._simulateInSector)
{
__instance._simulateInSector.OnSectorOccupantsUpdated += __instance.OnSectorOccupantsUpdated;
}

__instance._origParent = __instance._transform.parent;
__instance._origParentBody = __instance._origParent ? __instance._origParent.GetAttachedOWRigidbody() : null;

// ADDED
if (__instance._transform.parent)
{
_setParentQueue[__instance] = null;
}

// REMOVED
/*if (__instance._transform.parent != null)
{
__instance._transform.parent = null;
}*/

__instance._rigidbody = __instance.GetRequiredComponent<Rigidbody>();
__instance._rigidbody.interpolation = RigidbodyInterpolation.None;

if (!__instance._autoGenerateCenterOfMass)
{
__instance._rigidbody.centerOfMass = __instance._centerOfMass;
}

if (__instance.IsSimulatedKinematic())
{
__instance.EnableKinematicSimulation();
}

__instance._origCenterOfMass = __instance.RunningKinematicSimulation() ? __instance._kinematicRigidbody.centerOfMass : __instance._rigidbody.centerOfMass;
__instance._referenceFrame = new ReferenceFrame(__instance);

return false;
}

[HarmonyPrefix]
[HarmonyPatch(nameof(OWRigidbody.Start))]
private static void Start(OWRigidbody __instance)
{
if (_setParentQueue.TryGetValue(__instance, out var parent))
{
__instance._transform.parent = parent;
_setParentQueue.Remove(__instance);
}
}

[HarmonyPrefix]
[HarmonyPatch(nameof(OWRigidbody.OnDestroy))]
private static void OnDestroy(OWRigidbody __instance)
{
DeterministicManager.Cache.Remove(__instance._transform);
_setParentQueue.Remove(__instance);
}

[HarmonyPrefix]
[HarmonyPatch(nameof(OWRigidbody.Suspend), typeof(Transform), typeof(OWRigidbody))]
private static bool Suspend(OWRigidbody __instance, Transform suspensionParent, OWRigidbody suspensionBody)
{
if (!__instance._suspended || __instance._unsuspendNextUpdate)
{
__instance._suspensionBody = suspensionBody;
var direction = __instance.GetVelocity() - suspensionBody.GetPointVelocity(__instance._transform.position);
__instance._cachedRelativeVelocity = suspensionBody.transform.InverseTransformDirection(direction);
__instance._cachedAngularVelocity = __instance.RunningKinematicSimulation() ? __instance._kinematicRigidbody.angularVelocity : __instance._rigidbody.angularVelocity;
__instance.enabled = false;
__instance._offsetApplier.enabled = false;

if (__instance.RunningKinematicSimulation())
{
__instance._kinematicRigidbody.enabled = false;
}
else
{
__instance.MakeKinematic();
}

// ADDED
if (_setParentQueue.ContainsKey(__instance))
{
_setParentQueue[__instance] = suspensionParent;
}
else
{
__instance._transform.parent = suspensionParent;
}

// REMOVED
// __instance._transform.parent = suspensionParent;

__instance._suspended = true;
__instance._unsuspendNextUpdate = false;
if (!Physics.autoSyncTransforms)
{
Physics.SyncTransforms();
}

if (__instance._childColliders == null)
{
__instance._childColliders = __instance.GetComponentsInChildren<Collider>();

// CLEANED
foreach (var childCollider in __instance._childColliders)
{
childCollider.gameObject.GetAddComponent<OWCollider>().ListenForParentBodySuspension();
}
}

__instance.RaiseEvent(nameof(__instance.OnSuspendOWRigidbody), __instance);
}

return false;
}

[HarmonyPrefix]
[HarmonyPatch(nameof(OWRigidbody.ChangeSuspensionBody))]
private static bool ChangeSuspensionBody(OWRigidbody __instance, OWRigidbody newSuspensionBody)
{
if (__instance._suspended)
{
__instance._cachedRelativeVelocity = Vector3.zero;
__instance._suspensionBody = newSuspensionBody;

// ADDED
if (_setParentQueue.ContainsKey(__instance))
{
_setParentQueue[__instance] = newSuspensionBody.transform;
}
else
{
__instance._transform.parent = newSuspensionBody.transform;
}

// REMOVED
// __instance._transform.parent = newSuspensionBody.transform;
}

return false;
}

[HarmonyPrefix]
[HarmonyPatch(nameof(OWRigidbody.UnsuspendImmediate))]
private static bool UnsuspendImmediate(OWRigidbody __instance, bool restoreCachedVelocity)
{
if (__instance._suspended)
{
if (__instance.RunningKinematicSimulation())
{
__instance._kinematicRigidbody.enabled = true;
}
else
{
__instance.MakeNonKinematic();
}

__instance.enabled = true;

// ADDED
if (_setParentQueue.ContainsKey(__instance))
{
_setParentQueue[__instance] = null;
}
else
{
__instance._transform.parent = null;
}

// REMOVED
// __instance._transform.parent = null;

if (!Physics.autoSyncTransforms)
{
Physics.SyncTransforms();
}

var cachedVelocity = restoreCachedVelocity ? __instance._suspensionBody.transform.TransformDirection(__instance._cachedRelativeVelocity) : Vector3.zero;
__instance.SetVelocity(__instance._suspensionBody.GetPointVelocity(__instance._transform.position) + cachedVelocity);
__instance.SetAngularVelocity(restoreCachedVelocity ? __instance._cachedAngularVelocity : Vector3.zero);
__instance._suspended = false;
__instance._suspensionBody = null;
__instance.RaiseEvent(nameof(__instance.OnUnsuspendOWRigidbody), __instance);
}

return false;
}
}
Loading

0 comments on commit cb6b811

Please sign in to comment.