Introduce PersistentPlayerId: a stable id that survives an app restart and is
unique per install (built on the UGS install-path-namespaced anonymous
PlayerId, with a local PlayerPrefs GUID fallback for loopback). Clones on the
same machine stay distinct.
Each client reports its id to the server on connect via a new Match_Identity
named message (mirroring Match_ReportHit, so no ConnectionApproval timing
risk); the host records its own directly. The server keeps an ephemeral
clientId -> persistent id map, exposed via PersistentIdOf(clientId) as the
foundation for later reconnect recognition. Map entries are cleared on
disconnect and net stop.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The freshly converted hunter's body was hidden for the settle window via a
WaitForSeconds coroutine. If the object was disabled or the converting owner
disconnected mid-settle, the coroutine was stranded and _renderGate stayed
true forever, leaving the avatar invisible on every remote.
Replace it with a frame-driven Time.time deadline (_renderGateUntil) lifted
in UpdateVisibility, which runs every frame the component is active and can
never get stuck. Remove the coroutine and the now-unused System.Collections
using. Visible behaviour in the normal case is unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Move scripts under Assets/Scripts/ into Components, GameMode, Helper,
Network, Enum, Struct and ScriptableObject folders. Pure file moves
(plus folder .meta files); no code changes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>