diff --git a/CommunityBugFixCollection/Locale/de.json b/CommunityBugFixCollection/Locale/de.json index fa1e280..cbc35a2 100644 --- a/CommunityBugFixCollection/Locale/de.json +++ b/CommunityBugFixCollection/Locale/de.json @@ -30,6 +30,7 @@ "CommunityBugFixCollection.ImportWebFilesAsUrls.Description": "Sorgt dafür, dass URLs zu Textdateien oder Resonite Packages nicht importiert werden, statt als Hyperlink aufzutauchen.", "CommunityBugFixCollection.IndependentlyScaleDirectCursor.Description": "Verhindert, dass der direkte Cursor sehr groß wird, wenn er an einem deutlich nährem Objekt hängt als der echte Cursor.", "CommunityBugFixCollection.LongerWorldLoadingFailIndication.Description": "Lässt den Welt-Ladefortschritts-Indikator frühestens nach 20s verschwinden, falls der Vorgang fehlgeschlagen ist.", + "CommunityBugFixCollection.NaNtEqual.Description": "Sorgt dafür, dass NaN float / double Werte sich bei den == und != ProtoFlux Nodes sowie bei der ValueEqualityDriver Komponente niemals gleichen.", "CommunityBugFixCollection.NoLossOfColorProfile.Description": "Verhindert, dass Farbprofile nicht bei allen Berechnungen erhalten bleiben.", "CommunityBugFixCollection.NoZeroScaleToolRaycast.Description": "Verhinder einen Crash wenn (Multi-)Werkzeuge auf null skaliert werden.", "CommunityBugFixCollection.NodeNameAdjustments.Description": "Korrigiert, dass die Namen der meisten ProtoFlux Nodes in Strings > Constants unsichtbar sind.", diff --git a/CommunityBugFixCollection/Locale/en.json b/CommunityBugFixCollection/Locale/en.json index badb36e..b1b5d13 100644 --- a/CommunityBugFixCollection/Locale/en.json +++ b/CommunityBugFixCollection/Locale/en.json @@ -30,6 +30,7 @@ "CommunityBugFixCollection.ImportWebFilesAsUrls.Description": "Fixes URLs to text files or Resonite Packages failing to import instead of appearing as a hyperlink.", "CommunityBugFixCollection.IndependentlyScaleDirectCursor.Description": "Fixes direct cursor size becoming very large when snapped to an object much closer than the true cursor.", "CommunityBugFixCollection.LongerWorldLoadingFailIndication.Description": "Only lets the World Load Progress Indicator disappear after 20s or more if the process failed.", + "CommunityBugFixCollection.NaNtEqual.Description": "Makes NaN floats / doubles never equal to each other for the ProtoFlux == and != nodes, as well as the ValueEqualityDriver component.", "CommunityBugFixCollection.NoLossOfColorProfile.Description": "Fixes Color Profile not being preserved on all operations.", "CommunityBugFixCollection.NoZeroScaleToolRaycast.Description": "Fixes a crash when a (multi)tool is scaled to zero.", "CommunityBugFixCollection.NodeNameAdjustments.Description": "Fixes most ProtoFlux nodes in Strings > Constants having invisible names.", diff --git a/CommunityBugFixCollection/NaNtEqual.cs b/CommunityBugFixCollection/NaNtEqual.cs new file mode 100644 index 0000000..dc30344 --- /dev/null +++ b/CommunityBugFixCollection/NaNtEqual.cs @@ -0,0 +1,114 @@ +using Elements.Core; +using FrooxEngine; +using HarmonyLib; +using MonkeyLoader.Resonite; +using ProtoFlux.Core; +using ProtoFlux.Runtimes.Execution; +using ProtoFlux.Runtimes.Execution.Nodes; +using System; +using System.Collections.Generic; +using System.Text; + +namespace CommunityBugFixCollection +{ + [HarmonyPatch] + [HarmonyPatchCategory(nameof(NaNtEqual))] + internal sealed class NaNtEqual : ResoniteMonkey + { + public override IEnumerable Authors => Contributors.Banane9; + + public override bool CanBeDisabled => true; + + [HarmonyPrefix] + [HarmonyPatch(typeof(ValueEqualityDriver), nameof(ValueEqualityDriver.OnChanges))] + private static bool ValueEqualityDriverDoublePrefix(ValueEqualityDriver __instance) + { + if (!Enabled) + return true; + + if (!__instance.Target.IsLinkValid) + return false; + + var value = __instance.TargetValue.Target?.Value ?? default; + + var areEqual = (!__instance.UseApproximateComparison.Value || !Coder.SupportsApproximateComparison) + ? value == __instance.Reference.Value + : Coder.Approximately(value, __instance.Reference.Value); + + // XOR inverts the other bool + __instance.Target.Target.Value = __instance.Invert.Value ^ areEqual; + + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(ValueEqualityDriver), nameof(ValueEqualityDriver.OnChanges))] + private static bool ValueEqualityDriverFloatPrefix(ValueEqualityDriver __instance) + { + if (!Enabled) + return true; + + if (!__instance.Target.IsLinkValid) + return false; + + var value = __instance.TargetValue.Target?.Value ?? default; + + var areEqual = (!__instance.UseApproximateComparison.Value || !Coder.SupportsApproximateComparison) + ? value == __instance.Reference.Value + : Coder.Approximately(value, __instance.Reference.Value); + + // XOR inverts the other bool + __instance.Target.Target.Value = __instance.Invert.Value ^ areEqual; + + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(ValueEquals), nameof(ValueEquals.Compute))] + private static bool ValueEqualsDoublePrefix(ExecutionContext context, ref bool __result) + { + if (!Enabled) + return true; + + __result = 0.ReadValue(context) == 1.ReadValue(context); + + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(ValueEquals), nameof(ValueEquals.Compute))] + private static bool ValueEqualsFloatPrefix(ExecutionContext context, ref bool __result) + { + if (!Enabled) + return true; + + __result = 0.ReadValue(context) == 1.ReadValue(context); + + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(ValueNotEquals), nameof(ValueNotEquals.Compute))] + private static bool ValueNotEqualsDoublePrefix(ExecutionContext context, ref bool __result) + { + if (!Enabled) + return true; + + __result = 0.ReadValue(context) != 1.ReadValue(context); + + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(ValueNotEquals), nameof(ValueNotEquals.Compute))] + private static bool ValueNotEqualsFloatPrefix(ExecutionContext context, ref bool __result) + { + if (!Enabled) + return true; + + __result = 0.ReadValue(context) != 1.ReadValue(context); + + return false; + } + } +} \ No newline at end of file diff --git a/README.md b/README.md index 0749191..200eead 100644 --- a/README.md +++ b/README.md @@ -44,9 +44,10 @@ just disable them in the settings in the meantime. * The NoDestroyUndo component not preventing undoing the destruction of something (https://github.com/Yellow-Dog-Man/Resonite-Issues/issues/979) * References in multiple duplicated or transferred-between-worlds items breaking (https://github.com/Yellow-Dog-Man/Resonite-Issues/issues/984) * Context Menu changing size and becoming unusable with extreme FOVs (https://github.com/Yellow-Dog-Man/Resonite-Issues/issues/991) -* World Load Progress Indicator disappearing too quickly on fail (https://github.com/Yellow-Dog-Man/Resonite-Issues/issues/1019) * Hyperlink components only opening http(s) links (https://github.com/Yellow-Dog-Man/Resonite-Issues/issues/1018) +* World Load Progress Indicator disappearing too quickly on fail (https://github.com/Yellow-Dog-Man/Resonite-Issues/issues/1019) * Context Menu label outline not fading out like everything else (https://github.com/Yellow-Dog-Man/Resonite-Issues/issues/1027) +* NaN floats / doubles compare as equal in ProtoFlux and ValueEqualityDriver (but only when not approximate) (https://github.com/Yellow-Dog-Man/Resonite-Issues/issues/1046) * ColorX From HexCode (ProtoFlux node) defaults to Linear profile (https://github.com/Yellow-Dog-Man/Resonite-Issues/issues/1404) * UserInspectors not listing existing users in the session for non-host users (https://github.com/Yellow-Dog-Man/Resonite-Issues/issues/1964) * ProtoFlux value casts from byte to other values converting incorrectly (mono / graphical client only) (https://github.com/Yellow-Dog-Man/Resonite-Issues/issues/2257)