From 00ebe46abe0b821cc4fcf2ea8e8b5691d23896a9 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Thu, 17 Sep 2026 17:22:09 +0200 Subject: [PATCH] Move mouse-look sensitivity into the PlayerSettings CultCache global ActionGameManager.Sensitivity was a Unity-serialized public float2, but CultMath's float2 isn't Unity-serializable, so ARPG.unity's stored value loaded as zero and mouse look went dead. Sensitivity is a player preference, so it belongs in PlayerInputSettings (key 2) with the prior default (-0.001, 0.001) as a field initializer, so a pre-existing player store missing the key still deserializes to the working default instead of zero. ActionGameManager now reads PlayerSettings.InputSettings.Sensitivity directly; no cached copy on the MonoBehaviour. Adds a pinning test that simulates an old store lacking key 2 and asserts the default, plus a round-trip test for a non-default value. Co-Authored-By: Claude Opus 5 --- Assets/Scripts/Gameplay/ActionGameManager.cs | 4 +- Assets/Scripts/ServerShared/PlayerSettings.cs | 3 ++ .../PlayerSettingsSensitivityTests.cs | 43 +++++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 tests/Aetheria.Shared.Tests/PlayerSettingsSensitivityTests.cs diff --git a/Assets/Scripts/Gameplay/ActionGameManager.cs b/Assets/Scripts/Gameplay/ActionGameManager.cs index 4ac68c248..3573dfba3 100644 --- a/Assets/Scripts/Gameplay/ActionGameManager.cs +++ b/Assets/Scripts/Gameplay/ActionGameManager.cs @@ -98,7 +98,6 @@ public class ActionGameManager : MonoBehaviour public GameSettings Settings; //public string StarterShipTemplate = "Longinus"; - public float2 Sensitivity; public int Credits = 15000000; public float TargetSpottedBlinkFrequency = 20; public float TargetSpottedBlinkOffset = -.25f; @@ -1226,7 +1225,8 @@ public class ActionGameManager : MonoBehaviour } } var look = Input.Player.Look.ReadValue(); - _entityYawPitch = float2(_entityYawPitch.x + look.x * Sensitivity.x, clamp(_entityYawPitch.y + look.y * Sensitivity.y, -.45f * PI, .45f * PI)); + var sensitivity = PlayerSettings.InputSettings.Sensitivity; + _entityYawPitch = float2(_entityYawPitch.x + look.x * sensitivity.x, clamp(_entityYawPitch.y + look.y * sensitivity.y, -.45f * PI, .45f * PI)); _viewDirection = mul(float3(0, 0, 1), CultMath.float3x3.Euler(float3(_entityYawPitch.yx, 0), RotationOrder.YXZ)); CurrentEntity.LookDirection = _viewDirection; HeatstrokePost.weight = saturate(unlerp(0, Settings.GameplaySettings.SevereHeatstrokeRiskThreshold, CurrentEntity.Heatstroke)); diff --git a/Assets/Scripts/ServerShared/PlayerSettings.cs b/Assets/Scripts/ServerShared/PlayerSettings.cs index e52f785e6..d3c809fed 100644 --- a/Assets/Scripts/ServerShared/PlayerSettings.cs +++ b/Assets/Scripts/ServerShared/PlayerSettings.cs @@ -2,7 +2,9 @@ using GameCult.Caching; using System; using System.Collections.Generic; using System.Globalization; +using CultMath; using MessagePack; +using static CultMath.math; [CultDocument("aetheria.playersettings", "1"), CultGlobal, MessagePackObject] public class PlayerSettings @@ -71,6 +73,7 @@ public class PlayerInputSettings // MessagePack's untrusted-data security refuses to read it back. [Key(0)] public Dictionary> InputActionMap = new Dictionary>(); [Key(1)] public List ActionBarInputs = new List(); + [Key(2)] public float2 Sensitivity = float2(-0.001f, 0.001f); } public enum Quality diff --git a/tests/Aetheria.Shared.Tests/PlayerSettingsSensitivityTests.cs b/tests/Aetheria.Shared.Tests/PlayerSettingsSensitivityTests.cs new file mode 100644 index 000000000..c44af58aa --- /dev/null +++ b/tests/Aetheria.Shared.Tests/PlayerSettingsSensitivityTests.cs @@ -0,0 +1,43 @@ +using CultMath; +using GameCult.Caching.MessagePack; +using MessagePack; +using Xunit; +using static CultMath.math; + +// Pins the fix for the zero-sensitivity regression: ActionGameManager.Sensitivity (a Unity-serialized float2) was +// deleted because CultMath's float2 isn't Unity-serializable, and the setting moved into the CultCache +// PlayerInputSettings global. A player store written before this field existed has no key 2 for Sensitivity; it must +// deserialize with the look-sensitivity default, not zero, or mouse look goes dead again. +public sealed class PlayerSettingsSensitivityTests +{ + private static readonly MessagePackSerializerOptions Options = + CultDocumentMessagePackSerialization.OptionsFor(typeof(PlayerInputSettings).Assembly); + + [Fact] + public void MissingSensitivityKeyDeserializesToDefault() + { + // Simulate a pre-existing store: a PlayerInputSettings array holding only keys 0 and 1, so key 2 + // (Sensitivity) was never written. + var buffer = new System.Buffers.ArrayBufferWriter(); + var writer = new MessagePackWriter(buffer); + writer.WriteArrayHeader(2); + MessagePackSerializer.Serialize(ref writer, new System.Collections.Generic.Dictionary>(), Options); + MessagePackSerializer.Serialize(ref writer, new System.Collections.Generic.List(), Options); + writer.Flush(); + + var settings = MessagePackSerializer.Deserialize(buffer.WrittenMemory, Options); + + Assert.Equal(float2(-0.001f, 0.001f), settings.Sensitivity); + } + + [Fact] + public void NonDefaultSensitivityRoundTrips() + { + var settings = new PlayerInputSettings { Sensitivity = float2(0.5f, -0.25f) }; + + var bytes = MessagePackSerializer.Serialize(settings, Options); + var result = MessagePackSerializer.Deserialize(bytes, Options); + + Assert.Equal(float2(0.5f, -0.25f), result.Sensitivity); + } +}