Batch 37 · R2a player slots and exclusive device ownership¶
Checkpoint update, 2026-10-26: implementation committed separately as 936d7c76 at the owner's request. Documentation/evidence is kept in a separate commit; no push. The validation account below records the pre-commit work. Follow the per-batch commit workflow.
2026-10-26, dev-0.9.0-bootloader, HEAD remains dd0a666b. One bounded R2 implementation after batch 36. Added four C# files and five metadata files, and intentionally changed only the package manifest/lock to pin Input System 1.17.0. All previous runtime code/assets/settings, including batches 35/36, remain byte-preserved. No player build, commit or push.
Package and owner decisions¶
Pinned com.unity.inputsystem 1.17.0: Unity's 6.2 package reference lists that version as released for the Editor line. Resolved package metadata requires Unity 2022.3 or later, and this project's actual 6000.2.8f1 Editor compiles/tests it. No claim that it is the latest package. The sole package dependency is uielements 1.0.0, already present; no existing dependency version changed. Active Input Handling remains its original raw value2, with both SDK and legacy defines verified. Unity's installation reference describes this coexistence. This is a migration bridge, not completed physical compatibility or retirement of the legacy path.
The concrete pairing owner is InputUser per local roster slot. Future per-slot action copies must associate with this existing user; do not add an independently auto-pairing PlayerInput to the actor. InputUser API permits shared devices, so exclusivity is enforced by this roster rather than assumed from the SDK. PackageCache source was inspected for pairing/lost-device order and unpair semantics. InputUser is runtime/Play Mode scoped; the new service rejects Edit Mode construction.
LocalPlayerSlot has a unique session PlayerId, display slot, selected CharacterId and explicit device/user state. It is not a persistent profile ID, hardware index or actor. LocalPlayerRoster supports one through four slots: P1 keyboard or gamepad; P2–P4 distinct gamepads. It rejects unavailable, shared or externally paired devices before changing existing ownership. Reassignment and temporary unassignment preserve the surviving player and SDK user; leaving a slot releases its user, and rejoining allocates a new player identity. Character IDs are retained selection data, not proof of catalog/unlock validation.
A device change cannot select a different device by index/name/activity. Loss keeps the slot/player; restoration reconciles only the explicitly reserved reference after the SDK input update, avoiding a race with InputUser's Added reconciliation. Unexpected SDK auto-pairing by description is rejected. Native devices without a serial require explicit reassignment after loss, even when the backend reuses an object. Serial changes also invalidate automatic restoration. This is conservative identity handling; real backend serial quality/reconnect UX remains a physical-device gate. No auto-pause, invulnerability, player removal or reward-forfeiture policy is introduced.
RosterRunParticipant connects this same roster to the verified shared host. Preparation validates device assignments and locks setup; activation validates again; release unlocks setup without disposing the session's devices/users. Membership/device/character edits and disposal are rejected while locked. Retry and actual scene reload retain player identity, selected character and device/user. This does not assemble a production player or validate a complete stage/unlock/modifier request. No setup UI, action asset, sampler, binding IDs, remapping/profile writer, context routing, physical prompts or gameplay consumer migration was implemented in this slice. PS-03 and the other later gates remain open.
Checks and initial failure disposition¶
Actual required Editor 6000.2.8f1, direct batchmode/nographics entry TinyChaos.EditorTools.PlayerRosterChecks.RunBatch37, no immediate -quit. Final authoritative process exits 0, summary 9 passed / 0 failed.
The initial run reported 3 passed / 8 failures: six failed groups plus final-stop/scene-restore errors. Headless focus policy withheld keyboard availability; the fixture now clones InputSettings, permits its simulated devices under controlled focus, and restores the original settings object. The returning-device check also exposed eager roster pairing conflicting with InputUser's own lost-device reconciliation. Restoration now waits for onAfterUpdate; the same P05 case passes. The runner restores scene setup only after the native Play Mode exit has settled. These are recorded initial failures, not omitted passing evidence or a reproduction of the shipping game/freeze.
| Group | Final actual result |
|---|---|
| P01 | PASS: invalid capacity/blank character rejected, four unique stable slots, retained selection, no device owner created by merely adding slots. |
| P02 | PASS: eight approved keyboard-plus-pad/pad-only combinations for one through four slots; one SDK owner per assigned device, no leaked users. |
| P03 | PASS: secondary keyboard, shared/unavailable/mouse/null/out-of-range/foreign-owner requests rejected; prior player/selection/pairing preserved. |
| P04 | PASS: explicit pad/keyboard reassignment and unassign/reassign preserve player and SDK user; pad can move from P1 setup to P2 setup without being stolen/shared. |
| P05 | PASS: disabled device cannot activate, failure releases preparation; removal during Running retains player and clock policy; exact-reference restoration retains the SDK user. |
| P06 | PASS: SDK pairing of an unexpected replacement is rejected; explicit replacement preserves the player/user, and the old device cannot reclaim the slot. |
| P07 | PASS: removing setup slots releases only their users and returning members get new identities. Also tests native/no-serial ambiguity using a fixture-owned device's SDK native flag, requiring explicit reassignment. |
| P08 | PASS: invalid roster cannot leave partial active scene; three fresh run IDs, locked setup, retained identity/user/character across retry and actual scene reload, and unchanged F0 launcher path. |
| P09 | PASS: idempotent owned disposal, externally shared device reported invalid, foreign cleanup preserves owned user, worker-thread mutations rejected, both backend defines and legacy GetAxis/GetKey API smoke succeed. |
Devices are SDK-created keyboard/gamepads/mouse; no physical-controller UX is certified. The native-identity branch uses narrow Editor reflection on the pinned SDK's device flags for a fixture-owned gamepad, restoring flags afterward. It is not an OS reconnect test. Controlled InputSystem.Update calls settle synthetic device processing, not movement/timing performance. Scoped settings, virtual devices/users, run state and scene setup are cleaned up. No existing input action is remapped, no command sampler/press-edge behavior is verified, and no actor moves from these pairings yet.
Final log has no unexpected exception/compiler-error marker. Existing-category CS8785 generator warnings (two emitted) and unchanged StabilizationChecks CS0252 warnings (three emitted) remain; this is not warning-free. Raw local diagnostics stay private: /tmp/tinychaos-batch37-editor.log for the initial failures and /tmp/tinychaos-batch37-editor-final.log for the passing run, with matching redirected stdout. Retained checks reproduce the scenarios; temporary paths are not portable test archives.
Preservation and exact implementation manifest¶
Pre-run backup: /tmp/tinychaos-batch37-preserve-215da5615a/, containing exact project bytes/hashes for 2,838 files, 8,160 inspected Unity/profile files and documentation hashes. Final differences among those project files are exactly the two intentionally updated package files; all other 2,836 match, including the previous 19 batch-35/36 additions and Gameplay.unity. The original 608-file baseline is not regenerated: 606 pins match; manifest/lock are the two explicitly expected SDK-install differences, with current hashes below.
Unity additionally inserted its Linux toolchain dependency during verification. Generated copies were archived and only that unrequested dependency removed, retaining the intentional input dependency. No existing dependency version changes. Shared engine preferences changed three values and were restored. Four automatic Unity session/count keys in the normal game's prefs were restored; its one captured existing file now matches. No normal game save/config IO is called by the roster/checks. Five external engine bookkeeping files changed and remain engine state; no new external profile file. Do not claim the entire Unity tree is unchanged. New metadata empty-field trailing spaces were trimmed with parsed YAML/GUID equality; existing metadata was not reformatted.
| Implementation path | Kind | SHA-256 |
|---|---|---|
| Assets/Script/External/Editor/PlayerRosterChecks.cs | Editor checks | 60916a438554f703c8cec741255dad7002a6d26e4e2b41a89e143eb05f9e932f |
| Assets/Script/External/Editor/PlayerRosterChecks.cs.meta | metadata | e45f27a6d4aa6e6f0394730d4a6f55cdae7ab86f2426e043e32b1e871eeb9dee |
| Assets/Script/Game/GameSystem/Input.meta | metadata | d3449b1776c09bc56e280e86d9cdaf6f431ffaa5aef31ccae2f5ac1bb29f7bf4 |
| Assets/Script/Game/GameSystem/Input/LocalPlayerRoster.cs | runtime roster/input ownership | 63428c22208a296ffc6b15b3005e26febcdbfa8840f19a9c13baaf39e57263bb |
| Assets/Script/Game/GameSystem/Input/LocalPlayerRoster.cs.meta | metadata | 03ef3fba2b978dd09ec1ffd096796a6fd16e0421befe338bea35d5ed0ef276ee |
| Assets/Script/Game/GameSystem/Input/LocalPlayerSlot.cs | runtime roster/input ownership | 9bb5acadfd48df1c974181ae9637c51d94181ae367a0a2884f172a047bcbdfb8 |
| Assets/Script/Game/GameSystem/Input/LocalPlayerSlot.cs.meta | metadata | 6ce9d9e97d823a113aa7943dafd5111155cb2dac194c26f1c4c0a6ceece8df14 |
| Assets/Script/Game/GameSystem/Input/RosterRunParticipant.cs | runtime roster/input ownership | ff2078e4a7335c7b2fb7524ba8cd068a694ab2d10e9cadbb4e5f2738fd895020 |
| Assets/Script/Game/GameSystem/Input/RosterRunParticipant.cs.meta | metadata | d2ab756c9b2f6d8c394a2562a3bc9b0228f7e263163815962dba1a5a21c5c9d3 |
| Packages/manifest.json | pinned package manifest/lock | f30669e7f986120f363f5688feb0e0b53f4b7d228e3bed920dbe8d32583f6a5f |
| Packages/packages-lock.json | pinned package manifest/lock | e0cb5239f78a95b790178443a7558b4dd782d1c111a91f75091e7f974f79770a |
Final static checks pass: all 2,836 non-package prior project files and 19 previous implementation files match; the original pin set is retained with exactly two intended package differences and 606 unchanged pins. Five new GUIDs are unique, inventory covers 239 scripts with all 235 prior rows byte-preserved, and the legacy map adds only one Editor smoke row. All 50 prior gate rows remain byte-preserved; nine new SDK groups pass while all 27 later workstream follow-ups stay open. All 53 issue IDs route once; 697 local documentation links and whitespace pass. Isolated Git-index reviews verify the combined 30-file implementation group and separate documentation/evidence without changing the real index or HEAD.
Next and commit boundaries¶
Next is a bounded R2 input-session/action-definition/context slice using these existing InputUsers. Specify stable action/binding identities and the concrete package override format; preserve legacy layouts, dead zones/smoothing/normalization/button edges and UI timing with controlled traces before moving consumers. Minimum profile import/persistence/rebind behavior must pass disposable fixtures before normal-profile writes; PS-03 is not cleared by installing the package. Setup/reassignment recovery UI and per-profile remapping remain required R2 work. Actor assembly and production selection integration follow their dependencies. No new Reroll shortcut, hot join, split keyboard, guessed payout or unrelated feature.
Keep this implementation group (nine additions plus two package changes) separate from documentation/inventory/gate/status evidence, and preserve prior batch-35/36 groups. These groups are now committed separately in dependency order; future verified implementation batches also require separate commits. Documentation-only planning checkpoint remains dd0a666b. No commit/push is implied. GAME-01 and Tutorial completion stay deferred; no full-game playability, Windows/IL2CPP, physical-input equivalence or release acceptance is claimed.