From a3c65aa8e02b278f691dc88a89c483f23b34af29 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sun, 14 Jun 2026 11:28:10 +0100 Subject: [PATCH] Route input remaps through typed commit boundary --- .voidbot/state/aetheria.cc | Bin 84893 -> 85257 bytes Assets/Scripts/Gameplay/ActionGameManager.cs | 28 ++++++++++++----- .../ServerShared/RuntimePlayerSettings.cs | 29 ++++++++++++++++++ .../UI/InputScreen/InputDisplayLayout.cs | 16 +++------- docs/aetheria-perfect-machine-map.md | 17 +++++----- 5 files changed, 62 insertions(+), 28 deletions(-) diff --git a/.voidbot/state/aetheria.cc b/.voidbot/state/aetheria.cc index 02cfebc0ec989ec7db9b72925e6a27993b110a86..2242c66e09c045f16278bb6e7f388958e09c9cce 100644 GIT binary patch delta 1355 zcmZux&1+m$6!+z;i6~8r--w<~5uu%$F@cOJ)`_BKku)Sk!jR3Kd1q#>zIX4-z4v7p zT?`^F1UK>)1A>KWVz$B{?Jn)I#6@%yBCUUbh{b&to_p`S$yi*?aNha)eVqGUcl@hw z$A9{9>~Q4ELAYeYnH>Ezj}(h8GCB6@$hBX3ua8yl zcYY71%V?UYI0G({)PTa6B?%V|NHuEUMuTh#*jNI&g9+Oh8k0s_KjqE<=^vK-OrJ0NN1u2C7JFTk;X|mB}0A3RxeZJu^`E z(TBlHo#XdYladQOww6?%fNsh(3W+wsHP^jn?TA~%EG z%TuqsuEg@Dr5UO+6`@5;!Wm?tUAU#V71Vp#J7Ae5AXVQ~xg9iwT#>v{8|q5N_7Z9` z#9rwrnaCH=%MW?$vK`*VCZ7}l!4(jc)NrcVS_AA%jC4?;K0cL@%R@%D6F4c zE^CcOXMfBrTwQq&>s-*Z9J#04y9{DFaT#h7jv3faG0pzE^GcwzmD*Ij{Z2)A{N&MwJDJ zFJv31moEC}YQ8jE*)^=8A3U+#`}*{`v8VRju6wC{S$_ULc=-0zATv7}eKCK%W@qwe t?qIV2^37)dj6P2<+(dWxoj?u}=Urm49DJUK=3MRV-^#(gsX=V6@-O@d^L+pS delta 1052 zcmZ`&y=xRf6n8Hl7>l667(~Pe!9qw*FD8*h2qeZL#z;sMBnaNz?z_9u-I;Y}Hu2H~ zD-o-(#etxO_|XbSNF%5L3$ZYTg^5~N>%S22&Fc^6}kqB`Dtbtoza?CM1aER0dQpyGR3tN$LUY1 z=2X4~qXjRR)aw(6QXs&jTE_JK%?T! z=d0+QR*^6~K+shdV*aH;p}7=0_pj1;3$mErSmx+^pnb!ApA6;N=tQ}$%7_{z1mYx@ z(SwyL3J}cjWdu_TsbXzU%&_rj8Vr3#=_I7A_KfhKXc9*8osGk5Pp2hiV1RiZ2wX`s zw9Z8h#GtD(AtX*a`85xRK=qMoFR&QzuHEqYz5fXeUDyV?o zfTpQM9)vz#qSp{_7slcx)jd1AkmfW`=TI%8G4wDsIm%6%q=vGRK@&Vpy@aG3!NW3( zd;?|j$0izIaj(bKmF~vYm#rS>SpCzWbEEO&XaAu%_pvYD*gM&iuHw+x$kH>zD*D^L z*~YKEBkh~rIp_OCSJsWU+m5zYax7Wf`oN^~rdb+3)7sn4`oSqjX60eKy!9tj&b_R3 R&XzVOE;#SHTD3x9={EobclZDR diff --git a/Assets/Scripts/Gameplay/ActionGameManager.cs b/Assets/Scripts/Gameplay/ActionGameManager.cs index 8f6d5b37f..86f17256f 100644 --- a/Assets/Scripts/Gameplay/ActionGameManager.cs +++ b/Assets/Scripts/Gameplay/ActionGameManager.cs @@ -73,15 +73,27 @@ public class ActionGameManager : MonoBehaviour } } + public static void CommitRuntimeInputBindingOverride(string actionName, int bindingIndex, string inputSystemPath) + { + RuntimePlayerSettings.InputSettings.SetBindingOverride(actionName, bindingIndex, inputSystemPath); + QueueRuntimePlayerSettingsCommit(); + } + + public static void CommitRuntimeActionBarInput(string inputSystemPath, bool enabled) + { + RuntimePlayerSettings.InputSettings.SetActionBarInputEnabled(inputSystemPath, enabled); + QueueRuntimePlayerSettingsCommit(); + } + private static RuntimePlayerSettings CreateDefaultRuntimePlayerSettings() { var settings = new RuntimePlayerSettings(); settings.Name = Environment.UserName; - settings.InputSettings.ActionBarInputs.Add("/leftShift"); - settings.InputSettings.ActionBarInputs.Add("/leftButton"); - settings.InputSettings.ActionBarInputs.Add("/rightButton"); - settings.InputSettings.ActionBarInputs.Add("/middleButton"); - for (int i = 1; i < 6; i++) settings.InputSettings.ActionBarInputs.Add($"/{i}"); + settings.InputSettings.SetActionBarInputEnabled("/leftShift", true); + settings.InputSettings.SetActionBarInputEnabled("/leftButton", true); + settings.InputSettings.SetActionBarInputEnabled("/rightButton", true); + settings.InputSettings.SetActionBarInputEnabled("/middleButton", true); + for (int i = 1; i < 6; i++) settings.InputSettings.SetActionBarInputEnabled($"/{i}", true); return settings; } @@ -138,14 +150,14 @@ public class ActionGameManager : MonoBehaviour if (string.IsNullOrWhiteSpace(binding.ActionName) || string.IsNullOrWhiteSpace(binding.BindingPath) || binding.BindingIndex < 0) continue; - settings.InputSettings.InputActionMap[(binding.ActionName, binding.BindingIndex)] = binding.BindingPath; + settings.InputSettings.SetBindingOverride(binding.ActionName, binding.BindingIndex, binding.BindingPath); } settings.InputSettings.ActionBarInputs.Clear(); foreach (var input in stored.ActionBarInputs) { - if (!string.IsNullOrWhiteSpace(input) && !settings.InputSettings.ActionBarInputs.Contains(input)) - settings.InputSettings.ActionBarInputs.Add(input); + if (!string.IsNullOrWhiteSpace(input)) + settings.InputSettings.SetActionBarInputEnabled(input, true); } } diff --git a/Assets/Scripts/ServerShared/RuntimePlayerSettings.cs b/Assets/Scripts/ServerShared/RuntimePlayerSettings.cs index 59a4c4d5a..2b9158f9a 100644 --- a/Assets/Scripts/ServerShared/RuntimePlayerSettings.cs +++ b/Assets/Scripts/ServerShared/RuntimePlayerSettings.cs @@ -63,6 +63,35 @@ public class RuntimePlayerInputSettings { public Dictionary<(string action, int binding), string> InputActionMap = new Dictionary<(string action, int binding), string>(); public List ActionBarInputs = new List(); + + public void SetBindingOverride(string action, int binding, string inputSystemPath) + { + if (string.IsNullOrWhiteSpace(action)) + throw new ArgumentException("Action name is required.", nameof(action)); + if (binding < 0) + throw new ArgumentOutOfRangeException(nameof(binding)); + if (string.IsNullOrWhiteSpace(inputSystemPath)) + throw new ArgumentException("Input path is required.", nameof(inputSystemPath)); + + InputActionMap[(action, binding)] = inputSystemPath; + } + + public void SetActionBarInputEnabled(string inputSystemPath, bool enabled) + { + if (string.IsNullOrWhiteSpace(inputSystemPath)) + throw new ArgumentException("Input path is required.", nameof(inputSystemPath)); + + var index = ActionBarInputs.IndexOf(inputSystemPath); + if (enabled) + { + if (index < 0) + ActionBarInputs.Add(inputSystemPath); + } + else if (index >= 0) + { + ActionBarInputs.RemoveAt(index); + } + } } public enum Quality diff --git a/Assets/Scripts/UI/InputScreen/InputDisplayLayout.cs b/Assets/Scripts/UI/InputScreen/InputDisplayLayout.cs index 6ade0bf6a..0ee2c0891 100644 --- a/Assets/Scripts/UI/InputScreen/InputDisplayLayout.cs +++ b/Assets/Scripts/UI/InputScreen/InputDisplayLayout.cs @@ -415,10 +415,9 @@ public class InputDisplayLayout : MonoBehaviour private void CommitBindingOverride(InputAction action, InputBinding binding, string inputSystemPath) { - binding.overridePath = inputSystemPath; - action.ApplyBindingOverride(binding); - ActionGameManager.RuntimePlayerSettings.InputSettings.InputActionMap[(action.name, action.GetBindingIndex(binding))] = inputSystemPath; - QueueRuntimeInputSettingsCommit(); + var bindingIndex = action.GetBindingIndex(binding); + action.ApplyBindingOverride(bindingIndex, inputSystemPath); + ActionGameManager.CommitRuntimeInputBindingOverride(action.name, bindingIndex, inputSystemPath); } private void OnEnable() @@ -463,17 +462,10 @@ public class InputDisplayLayout : MonoBehaviour .Subscribe(data => { buttonMapping.IsActionBarButton = !buttonMapping.IsActionBarButton; + ActionGameManager.CommitRuntimeActionBarInput(buttonMapping.Button.InputSystemPath, buttonMapping.IsActionBarButton); if (buttonMapping.IsActionBarButton) - { - ActionGameManager.RuntimePlayerSettings.InputSettings.ActionBarInputs.Add(buttonMapping.Button.InputSystemPath); foreach(var overlap in OverlappingLabels(buttonMapping.ButtonRect)) PlaceLabel(overlap); - } - else - { - ActionGameManager.RuntimePlayerSettings.InputSettings.ActionBarInputs.Remove(buttonMapping.Button.InputSystemPath); - } - QueueRuntimeInputSettingsCommit(); AssignColor(buttonMapping); }); diff --git a/docs/aetheria-perfect-machine-map.md b/docs/aetheria-perfect-machine-map.md index 5217dcd1a..daade6200 100644 --- a/docs/aetheria-perfect-machine-map.md +++ b/docs/aetheria-perfect-machine-map.md @@ -72,12 +72,13 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted. name, tutorial flag, story-file hash cursors, gameplay formatting, graphics preferences, input binding overrides, and action-bar inputs. Unity's menu and input screens mutate `RuntimePlayerSettings` in memory and queue typed Verse - commits through the shared player-settings commit primitive; the in-memory + commits through shared player-settings commit primitives; the in-memory projection is not portable state authority. Aetheria has its own remapping UI that calls Unity's InputSystem at the binding/action layer; Unity's generated `AetheriaInput` class is the edge consumer of typed binding overrides, not - the durable owner. Binding drag/drop and action-bar remapping both queue the - same typed player-settings commit after mutating the runtime projection. The + the durable owner. Binding drag/drop and action-bar remapping both route + through named runtime input commit methods instead of writing the input + collections directly. The action bar also uses typed runtime catalog category rows to reject non-consumable inventory drops and creates consumable bindings around typed catalog rows. Missing typed rows are rejected for consumable binding instead @@ -1088,9 +1089,9 @@ First Aetheria surfaces to publish: `RuntimePlayerSettings`; `AetheriaPlayerSettings` remains the typed Verse state document owner, while Unity only keeps a session projection and queues typed player-settings commits. - - Done: route input-screen binding/action-bar edits through the typed - player-settings commit primitive now that the Unity state package is live; - the stale runtime-only keyboard layout warning is gone. + - Done: route input-screen binding/action-bar edits through named typed + player-settings commit methods on the Unity runtime boundary, so the UI is + no longer a direct writer of input binding or action-bar collections. - Remaining: delete or quarantine old cache abstractions that no longer protect an invariant once catalog migration has a typed reader. @@ -1148,8 +1149,8 @@ First Aetheria surfaces to publish: - Unity runtime settings projection is now `RuntimePlayerSettings`; live Unity source has no standalone `PlayerSettings` class/property/method symbols. - Input binding and action-bar edits now queue the same typed player-settings - commit path as menu settings changes; the old `SaveLayout` runtime-only - warning is gone. The generated `AetheriaInput` class still calls Unity's + commit path as menu settings changes through named runtime input commit + methods; the old `SaveLayout` runtime-only warning is gone. The generated `AetheriaInput` class still calls Unity's `InputActionAsset.FromJson`, but that JSON belongs to Unity's generated input action lowering under Aetheria's remapping system. It is not durable Aetheria state and does not own remapping authority.